summaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/Python/marshal.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/tools/python3/Python/marshal.c')
-rw-r--r--contrib/tools/python3/Python/marshal.c57
1 files changed, 43 insertions, 14 deletions
diff --git a/contrib/tools/python3/Python/marshal.c b/contrib/tools/python3/Python/marshal.c
index 65481341bdf..1bbce41d65f 100644
--- a/contrib/tools/python3/Python/marshal.c
+++ b/contrib/tools/python3/Python/marshal.c
@@ -310,7 +310,6 @@ static int
w_ref(PyObject *v, char *flag, WFILE *p)
{
_Py_hashtable_entry_t *entry;
- int w;
if (p->version < 3 || p->hashtable == NULL)
return 0; /* not writing object references */
@@ -327,20 +326,28 @@ w_ref(PyObject *v, char *flag, WFILE *p)
entry = _Py_hashtable_get_entry(p->hashtable, v);
if (entry != NULL) {
/* write the reference index to the stream */
- w = (int)(uintptr_t)entry->value;
+ uintptr_t w = (uintptr_t)entry->value;
+ if (w & 0x80000000LU) {
+ PyErr_Format(PyExc_ValueError, "cannot marshal recursion %T objects", v);
+ goto err;
+ }
/* we don't store "long" indices in the dict */
- assert(0 <= w && w <= 0x7fffffff);
+ assert(w <= 0x7fffffff);
w_byte(TYPE_REF, p);
- w_long(w, p);
+ w_long((int)w, p);
return 1;
} else {
- size_t s = p->hashtable->nentries;
+ size_t w = p->hashtable->nentries;
/* we don't support long indices */
- if (s >= 0x7fffffff) {
+ if (w >= 0x7fffffff) {
PyErr_SetString(PyExc_ValueError, "too many objects");
goto err;
}
- w = (int)s;
+ // Corresponding code should call w_complete() after
+ // writing the object.
+ if (PyCode_Check(v)) {
+ w |= 0x80000000LU;
+ }
if (_Py_hashtable_set(p->hashtable, Py_NewRef(v),
(void *)(uintptr_t)w) < 0) {
Py_DECREF(v);
@@ -355,6 +362,27 @@ err:
}
static void
+w_complete(PyObject *v, WFILE *p)
+{
+ if (p->version < 3 || p->hashtable == NULL) {
+ return;
+ }
+ if (Py_REFCNT(v) == 1) {
+ return;
+ }
+
+ _Py_hashtable_entry_t *entry = _Py_hashtable_get_entry(p->hashtable, v);
+ if (entry == NULL) {
+ return;
+ }
+ assert(entry != NULL);
+ uintptr_t w = (uintptr_t)entry->value;
+ assert(w & 0x80000000LU);
+ w &= ~0x80000000LU;
+ entry->value = (void *)(uintptr_t)w;
+}
+
+static void
w_complex_object(PyObject *v, char flag, WFILE *p);
static void
@@ -603,6 +631,7 @@ w_complex_object(PyObject *v, char flag, WFILE *p)
w_object(co->co_linetable, p);
w_object(co->co_exceptiontable, p);
Py_DECREF(co_code);
+ w_complete(v, p);
}
else if (PyObject_CheckBuffer(v)) {
/* Write unknown bytes-like objects as a bytes object */
@@ -1458,7 +1487,7 @@ r_object(RFILE *p)
goto code_error;
firstlineno = (int)r_long(p);
if (firstlineno == -1 && PyErr_Occurred())
- break;
+ goto code_error;
linetable = r_object(p);
if (linetable == NULL)
goto code_error;
@@ -1866,14 +1895,14 @@ marshal.dumps
Return the bytes object that would be written to a file by dump(value, file).
-Raise a ValueError exception if value has (or contains an object that has) an
-unsupported type.
+Raise a ValueError exception if value has (or contains an object that
+has) an unsupported type.
[clinic start generated code]*/
static PyObject *
marshal_dumps_impl(PyObject *module, PyObject *value, int version,
int allow_code)
-/*[clinic end generated code: output=115f90da518d1d49 input=167eaecceb63f0a8]*/
+/*[clinic end generated code: output=115f90da518d1d49 input=d9609c4dee4507fb]*/
{
return _PyMarshal_WriteObjectToString(value, version, allow_code);
}
@@ -1889,13 +1918,13 @@ marshal.loads
Convert the bytes-like object to a value.
-If no valid value is found, raise EOFError, ValueError or TypeError. Extra
-bytes in the input are ignored.
+If no valid value is found, raise EOFError, ValueError or TypeError.
+Extra bytes in the input are ignored.
[clinic start generated code]*/
static PyObject *
marshal_loads_impl(PyObject *module, Py_buffer *bytes, int allow_code)
-/*[clinic end generated code: output=62c0c538d3edc31f input=14de68965b45aaa7]*/
+/*[clinic end generated code: output=62c0c538d3edc31f input=286f1dbd6811d2ad]*/
{
RFILE rf;
char *s = bytes->buf;