diff options
Diffstat (limited to 'Modules/_pickle.c')
-rw-r--r-- | Modules/_pickle.c | 206 |
1 files changed, 126 insertions, 80 deletions
diff --git a/Modules/_pickle.c b/Modules/_pickle.c index 10eb513..7a234f1 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -420,22 +420,22 @@ static int Pdata_grow(Pdata *self) { PyObject **data = self->data; - Py_ssize_t allocated = self->allocated; - Py_ssize_t new_allocated; + size_t allocated = (size_t)self->allocated; + size_t new_allocated; new_allocated = (allocated >> 3) + 6; /* check for integer overflow */ - if (new_allocated > PY_SSIZE_T_MAX - allocated) + if (new_allocated > (size_t)PY_SSIZE_T_MAX - allocated) goto nomemory; new_allocated += allocated; - if (new_allocated > (PY_SSIZE_T_MAX / sizeof(PyObject *))) + if (new_allocated > ((size_t)PY_SSIZE_T_MAX / sizeof(PyObject *))) goto nomemory; data = PyMem_REALLOC(data, new_allocated * sizeof(PyObject *)); if (data == NULL) goto nomemory; self->data = data; - self->allocated = new_allocated; + self->allocated = (Py_ssize_t)new_allocated; return 0; nomemory: @@ -850,7 +850,7 @@ _Pickler_ClearBuffer(PicklerObject *self) static void _write_size64(char *out, size_t value) { - int i; + size_t i; assert(sizeof(size_t) <= 8); @@ -1456,7 +1456,7 @@ memo_get(PicklerObject *self, PyObject *key) pdata[1] = (unsigned char)(*value & 0xff); len = 2; } - else if (*value <= 0xffffffffL) { + else if ((size_t)*value <= 0xffffffffUL) { pdata[0] = LONG_BINGET; pdata[1] = (unsigned char)(*value & 0xff); pdata[2] = (unsigned char)((*value >> 8) & 0xff); @@ -1513,7 +1513,7 @@ memo_put(PicklerObject *self, PyObject *obj) pdata[1] = (unsigned char)idx; len = 2; } - else if (idx <= 0xffffffffL) { + else if ((size_t)idx <= 0xffffffffUL) { pdata[0] = LONG_BINPUT; pdata[1] = (unsigned char)(idx & 0xff); pdata[2] = (unsigned char)((idx >> 8) & 0xff); @@ -1535,69 +1535,109 @@ memo_put(PicklerObject *self, PyObject *obj) } static PyObject * -getattribute(PyObject *obj, PyObject *name, int allow_qualname) { - PyObject *dotted_path; - Py_ssize_t i; +get_dotted_path(PyObject *obj, PyObject *name, int allow_qualname) { _Py_static_string(PyId_dot, "."); _Py_static_string(PyId_locals, "<locals>"); + PyObject *dotted_path; + Py_ssize_t i, n; dotted_path = PyUnicode_Split(name, _PyUnicode_FromId(&PyId_dot), -1); - if (dotted_path == NULL) { + if (dotted_path == NULL) return NULL; - } - assert(Py_SIZE(dotted_path) >= 1); - if (!allow_qualname && Py_SIZE(dotted_path) > 1) { - PyErr_Format(PyExc_AttributeError, - "Can't get qualified attribute %R on %R;" - "use protocols >= 4 to enable support", - name, obj); + n = PyList_GET_SIZE(dotted_path); + assert(n >= 1); + if (!allow_qualname && n > 1) { + if (obj == NULL) + PyErr_Format(PyExc_AttributeError, + "Can't pickle qualified object %R; " + "use protocols >= 4 to enable support", + name); + else + PyErr_Format(PyExc_AttributeError, + "Can't pickle qualified attribute %R on %R; " + "use protocols >= 4 to enable support", + name, obj); Py_DECREF(dotted_path); return NULL; } - Py_INCREF(obj); - for (i = 0; i < Py_SIZE(dotted_path); i++) { + for (i = 0; i < n; i++) { PyObject *subpath = PyList_GET_ITEM(dotted_path, i); - PyObject *tmp; PyObject *result = PyUnicode_RichCompare( subpath, _PyUnicode_FromId(&PyId_locals), Py_EQ); int is_equal = (result == Py_True); assert(PyBool_Check(result)); Py_DECREF(result); if (is_equal) { - PyErr_Format(PyExc_AttributeError, - "Can't get local attribute %R on %R", name, obj); + if (obj == NULL) + PyErr_Format(PyExc_AttributeError, + "Can't pickle local object %R", name); + else + PyErr_Format(PyExc_AttributeError, + "Can't pickle local attribute %R on %R", name, obj); Py_DECREF(dotted_path); - Py_DECREF(obj); return NULL; } - tmp = PyObject_GetAttr(obj, subpath); + } + return dotted_path; +} + +static PyObject * +get_deep_attribute(PyObject *obj, PyObject *names) +{ + Py_ssize_t i, n; + + assert(PyList_CheckExact(names)); + Py_INCREF(obj); + n = PyList_GET_SIZE(names); + for (i = 0; i < n; i++) { + PyObject *name = PyList_GET_ITEM(names, i); + PyObject *tmp; + tmp = PyObject_GetAttr(obj, name); Py_DECREF(obj); - if (tmp == NULL) { - if (PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Clear(); - PyErr_Format(PyExc_AttributeError, - "Can't get attribute %R on %R", name, obj); - } - Py_DECREF(dotted_path); + if (tmp == NULL) return NULL; - } obj = tmp; } - Py_DECREF(dotted_path); return obj; } +static void +reformat_attribute_error(PyObject *obj, PyObject *name) +{ + if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + PyErr_Format(PyExc_AttributeError, + "Can't get attribute %R on %R", name, obj); + } +} + + +static PyObject * +getattribute(PyObject *obj, PyObject *name, int allow_qualname) +{ + PyObject *dotted_path, *attr; + + dotted_path = get_dotted_path(obj, name, allow_qualname); + if (dotted_path == NULL) + return NULL; + attr = get_deep_attribute(obj, dotted_path); + Py_DECREF(dotted_path); + if (attr == NULL) + reformat_attribute_error(obj, name); + return attr; +} + static PyObject * whichmodule(PyObject *global, PyObject *global_name, int allow_qualname) { PyObject *module_name; PyObject *modules_dict; PyObject *module; - PyObject *obj; - Py_ssize_t i, j; + Py_ssize_t i; _Py_IDENTIFIER(__module__); _Py_IDENTIFIER(modules); _Py_IDENTIFIER(__main__); + PyObject *dotted_path; module_name = _PyObject_GetAttrId(global, &PyId___module__); @@ -1616,43 +1656,49 @@ whichmodule(PyObject *global, PyObject *global_name, int allow_qualname) } assert(module_name == NULL); + /* Fallback on walking sys.modules */ modules_dict = _PySys_GetObjectId(&PyId_modules); if (modules_dict == NULL) { PyErr_SetString(PyExc_RuntimeError, "unable to get sys.modules"); return NULL; } + dotted_path = get_dotted_path(NULL, global_name, allow_qualname); + if (dotted_path == NULL) + return NULL; + i = 0; - while ((j = PyDict_Next(modules_dict, &i, &module_name, &module))) { - PyObject *result = PyUnicode_RichCompare( - module_name, _PyUnicode_FromId(&PyId___main__), Py_EQ); - int is_equal = (result == Py_True); - assert(PyBool_Check(result)); - Py_DECREF(result); - if (is_equal) + while (PyDict_Next(modules_dict, &i, &module_name, &module)) { + PyObject *candidate; + if (PyUnicode_Check(module_name) && + !PyUnicode_CompareWithASCIIString(module_name, "__main__")) continue; if (module == Py_None) continue; - obj = getattribute(module, global_name, allow_qualname); - if (obj == NULL) { - if (!PyErr_ExceptionMatches(PyExc_AttributeError)) + candidate = get_deep_attribute(module, dotted_path); + if (candidate == NULL) { + if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { + Py_DECREF(dotted_path); return NULL; + } PyErr_Clear(); continue; } - if (obj == global) { - Py_DECREF(obj); + if (candidate == global) { Py_INCREF(module_name); + Py_DECREF(dotted_path); + Py_DECREF(candidate); return module_name; } - Py_DECREF(obj); + Py_DECREF(candidate); } /* If no module is found, use __main__. */ module_name = _PyUnicode_FromId(&PyId___main__); Py_INCREF(module_name); + Py_DECREF(dotted_path); return module_name; } @@ -2013,7 +2059,7 @@ save_bytes(PicklerObject *self, PyObject *obj) header[1] = (unsigned char)size; len = 2; } - else if (size <= 0xffffffffL) { + else if ((size_t)size <= 0xffffffffUL) { header[0] = BINBYTES; header[1] = (unsigned char)(size & 0xff); header[2] = (unsigned char)((size >> 8) & 0xff); @@ -2050,9 +2096,10 @@ save_bytes(PicklerObject *self, PyObject *obj) static PyObject * raw_unicode_escape(PyObject *obj) { - PyObject *repr, *result; + PyObject *repr; char *p; - Py_ssize_t i, size, expandsize; + Py_ssize_t i, size; + size_t expandsize; void *data; unsigned int kind; @@ -2067,15 +2114,16 @@ raw_unicode_escape(PyObject *obj) else expandsize = 6; - if (size > PY_SSIZE_T_MAX / expandsize) + if ((size_t)size > (size_t)PY_SSIZE_T_MAX / expandsize) return PyErr_NoMemory(); - repr = PyByteArray_FromStringAndSize(NULL, expandsize * size); + repr = PyBytes_FromStringAndSize(NULL, expandsize * size); if (repr == NULL) return NULL; if (size == 0) - goto done; + return repr; + assert(Py_REFCNT(repr) == 1); - p = PyByteArray_AS_STRING(repr); + p = PyBytes_AS_STRING(repr); for (i=0; i < size; i++) { Py_UCS4 ch = PyUnicode_READ(kind, data, i); /* Map 32-bit characters to '\Uxxxxxxxx' */ @@ -2104,12 +2152,10 @@ raw_unicode_escape(PyObject *obj) else *p++ = (char) ch; } - size = p - PyByteArray_AS_STRING(repr); - -done: - result = PyBytes_FromStringAndSize(PyByteArray_AS_STRING(repr), size); - Py_DECREF(repr); - return result; + size = p - PyBytes_AS_STRING(repr); + if (_PyBytes_Resize(&repr, size) < 0) + return NULL; + return repr; } static int @@ -2118,12 +2164,13 @@ write_utf8(PicklerObject *self, char *data, Py_ssize_t size) char header[9]; Py_ssize_t len; + assert(size >= 0); if (size <= 0xff && self->proto >= 4) { header[0] = SHORT_BINUNICODE; header[1] = (unsigned char)(size & 0xff); len = 2; } - else if (size <= 0xffffffffUL) { + else if ((size_t)size <= 0xffffffffUL) { header[0] = BINUNICODE; header[1] = (unsigned char)(size & 0xff); header[2] = (unsigned char)((size >> 8) & 0xff); @@ -3459,20 +3506,19 @@ save_reduce(PicklerObject *self, PyObject *args, PyObject *obj) } PyErr_Clear(); } - else if (self->proto >= 4) { - _Py_IDENTIFIER(__newobj_ex__); - use_newobj_ex = PyUnicode_Check(name) && - PyUnicode_Compare( - name, _PyUnicode_FromId(&PyId___newobj_ex__)) == 0; - Py_DECREF(name); - } - else { - _Py_IDENTIFIER(__newobj__); - use_newobj = PyUnicode_Check(name) && - PyUnicode_Compare( - name, _PyUnicode_FromId(&PyId___newobj__)) == 0; - Py_DECREF(name); + else if (PyUnicode_Check(name)) { + if (self->proto >= 4) { + _Py_IDENTIFIER(__newobj_ex__); + use_newobj_ex = PyUnicode_Compare( + name, _PyUnicode_FromId(&PyId___newobj_ex__)) == 0; + } + if (!use_newobj_ex) { + _Py_IDENTIFIER(__newobj__); + use_newobj = PyUnicode_Compare( + name, _PyUnicode_FromId(&PyId___newobj__)) == 0; + } } + Py_XDECREF(name); } if (use_newobj_ex) { @@ -4533,10 +4579,10 @@ static Py_ssize_t calc_binsize(char *bytes, int nbytes) { unsigned char *s = (unsigned char *)bytes; - int i; + Py_ssize_t i; size_t x = 0; - for (i = 0; i < nbytes && i < sizeof(size_t); i++) { + for (i = 0; i < nbytes && (size_t)i < sizeof(size_t); i++) { x |= (size_t) s[i] << (8 * i); } @@ -4555,7 +4601,7 @@ static long calc_binint(char *bytes, int nbytes) { unsigned char *s = (unsigned char *)bytes; - int i; + Py_ssize_t i; long x = 0; for (i = 0; i < nbytes; i++) { |