summaryrefslogtreecommitdiff
path: root/Modules/_pickle.c
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/_pickle.c')
-rw-r--r--Modules/_pickle.c92
1 files changed, 55 insertions, 37 deletions
diff --git a/Modules/_pickle.c b/Modules/_pickle.c
index 920b46fc28..e65b88e9c0 100644
--- a/Modules/_pickle.c
+++ b/Modules/_pickle.c
@@ -346,7 +346,7 @@ _Pickle_FastCall(PyObject *func, PyObject *obj)
{
PyObject *result;
- result = _PyObject_CallArg1(func, obj);
+ result = PyObject_CallFunctionObjArgs(func, obj, NULL);
Py_DECREF(obj);
return result;
}
@@ -1936,7 +1936,7 @@ save_long(PicklerObject *self, PyObject *obj)
goto error;
}
else {
- char *string;
+ const char *string;
/* proto < 2: write the repr and newline. This is quadratic-time (in
the number of digits), in both directions. We add a trailing 'L'
@@ -2213,7 +2213,7 @@ write_unicode_binary(PicklerObject *self, PyObject *obj)
{
PyObject *encoded = NULL;
Py_ssize_t size;
- char *data;
+ const char *data;
int r;
if (PyUnicode_READY(obj))
@@ -2782,10 +2782,10 @@ batch_dict_exact(PicklerObject *self, PyObject *obj)
const char setitem_op = SETITEM;
const char setitems_op = SETITEMS;
- assert(obj != NULL);
+ assert(obj != NULL && PyDict_CheckExact(obj));
assert(self->proto > 0);
- dict_size = PyDict_Size(obj);
+ dict_size = PyDict_GET_SIZE(obj);
/* Special-case len(d) == 1 to save space. */
if (dict_size == 1) {
@@ -2814,7 +2814,7 @@ batch_dict_exact(PicklerObject *self, PyObject *obj)
}
if (_Pickler_Write(self, &setitems_op, 1) < 0)
return -1;
- if (PyDict_Size(obj) != dict_size) {
+ if (PyDict_GET_SIZE(obj) != dict_size) {
PyErr_Format(
PyExc_RuntimeError,
"dictionary changed size during iteration");
@@ -2832,6 +2832,7 @@ save_dict(PicklerObject *self, PyObject *obj)
char header[3];
Py_ssize_t len;
int status = 0;
+ assert(PyDict_Check(obj));
if (self->fast && !fast_save_enter(self, obj))
goto error;
@@ -2850,14 +2851,10 @@ save_dict(PicklerObject *self, PyObject *obj)
if (_Pickler_Write(self, header, len) < 0)
goto error;
- /* Get dict size, and bow out early if empty. */
- if ((len = PyDict_Size(obj)) < 0)
- goto error;
-
if (memo_put(self, obj) < 0)
goto error;
- if (len != 0) {
+ if (PyDict_GET_SIZE(obj)) {
/* Save the dict items. */
if (PyDict_CheckExact(obj) && self->proto > 0) {
/* We can take certain shortcuts if we know this is a dict and
@@ -4565,8 +4562,8 @@ find_class(UnpicklerObject *self, PyObject *module_name, PyObject *global_name)
{
_Py_IDENTIFIER(find_class);
- return _PyObject_CallMethodId((PyObject *)self, &PyId_find_class, "OO",
- module_name, global_name);
+ return _PyObject_CallMethodIdObjArgs((PyObject *)self, &PyId_find_class,
+ module_name, global_name, NULL);
}
static Py_ssize_t
@@ -4756,7 +4753,7 @@ static int
load_long(UnpicklerObject *self)
{
PyObject *value;
- char *s;
+ char *s = NULL;
Py_ssize_t len;
if ((len = _Unpickler_Readline(self, &s)) < 0)
@@ -4987,7 +4984,7 @@ load_unicode(UnpicklerObject *self)
{
PyObject *str;
Py_ssize_t len;
- char *s;
+ char *s = NULL;
if ((len = _Unpickler_Readline(self, &s)) < 0)
return -1;
@@ -5178,7 +5175,7 @@ instantiate(PyObject *cls, PyObject *args)
else {
_Py_IDENTIFIER(__new__);
- result = _PyObject_CallMethodId(cls, &PyId___new__, "O", cls);
+ result = _PyObject_CallMethodIdObjArgs(cls, &PyId___new__, cls, NULL);
}
return result;
}
@@ -5726,7 +5723,7 @@ load_put(UnpicklerObject *self)
PyObject *key, *value;
Py_ssize_t idx;
Py_ssize_t len;
- char *s;
+ char *s = NULL;
if ((len = _Unpickler_Readline(self, &s)) < 0)
return -1;
@@ -5810,7 +5807,9 @@ static int
do_append(UnpicklerObject *self, Py_ssize_t x)
{
PyObject *value;
+ PyObject *slice;
PyObject *list;
+ PyObject *result;
Py_ssize_t len, i;
len = Py_SIZE(self->stack);
@@ -5821,8 +5820,7 @@ do_append(UnpicklerObject *self, Py_ssize_t x)
list = self->stack->data[x - 1];
- if (PyList_Check(list)) {
- PyObject *slice;
+ if (PyList_CheckExact(list)) {
Py_ssize_t list_len;
int ret;
@@ -5835,27 +5833,47 @@ do_append(UnpicklerObject *self, Py_ssize_t x)
return ret;
}
else {
- PyObject *append_func;
- _Py_IDENTIFIER(append);
-
- append_func = _PyObject_GetAttrId(list, &PyId_append);
- if (append_func == NULL)
- return -1;
- for (i = x; i < len; i++) {
- PyObject *result;
-
- value = self->stack->data[i];
- result = _Pickle_FastCall(append_func, value);
- if (result == NULL) {
- Pdata_clear(self->stack, i + 1);
- Py_SIZE(self->stack) = x;
- Py_DECREF(append_func);
+ PyObject *extend_func;
+ _Py_IDENTIFIER(extend);
+
+ extend_func = _PyObject_GetAttrId(list, &PyId_extend);
+ if (extend_func != NULL) {
+ slice = Pdata_poplist(self->stack, x);
+ if (!slice) {
+ Py_DECREF(extend_func);
return -1;
}
+ result = _Pickle_FastCall(extend_func, slice);
+ Py_DECREF(extend_func);
+ if (result == NULL)
+ return -1;
Py_DECREF(result);
}
- Py_SIZE(self->stack) = x;
- Py_DECREF(append_func);
+ else {
+ PyObject *append_func;
+ _Py_IDENTIFIER(append);
+
+ /* Even if the PEP 307 requires extend() and append() methods,
+ fall back on append() if the object has no extend() method
+ for backward compatibility. */
+ PyErr_Clear();
+ append_func = _PyObject_GetAttrId(list, &PyId_append);
+ if (append_func == NULL)
+ return -1;
+ for (i = x; i < len; i++) {
+ value = self->stack->data[i];
+ result = _Pickle_FastCall(append_func, value);
+ if (result == NULL) {
+ Pdata_clear(self->stack, i + 1);
+ Py_SIZE(self->stack) = x;
+ Py_DECREF(append_func);
+ return -1;
+ }
+ Py_DECREF(result);
+ }
+ Py_SIZE(self->stack) = x;
+ Py_DECREF(append_func);
+ }
}
return 0;
@@ -6872,7 +6890,7 @@ Unpickler_set_memo(UnpicklerObject *self, PyObject *obj)
Py_ssize_t i = 0;
PyObject *key, *value;
- new_memo_size = PyDict_Size(obj);
+ new_memo_size = PyDict_GET_SIZE(obj);
new_memo = _Unpickler_NewMemo(new_memo_size);
if (new_memo == NULL)
return -1;