summaryrefslogtreecommitdiffstats
path: root/Modules/_pickle.c
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/_pickle.c')
-rw-r--r--Modules/_pickle.c206
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++) {