mirror of
https://github.com/python/cpython.git
synced 2025-11-03 19:34:08 +00:00
Jim Fulton:
- Loading non-binary string pickles checks for insecure
strings. This is needed because cPickle (still)
uses a restricted eval to parse non-binary string pickles.
This change is needed to prevent untrusted
pickles like::
"S'hello world'*2000000\012p0\012."
from hosing an application.
- User-defined types can now support unpickling without
executing a constructor.
The second value returned from __reduce__ can now be None,
rather than an argument tuple. On unpickling, if the second
value returned from __reduce__ during pickling was None, then
rather than calling the first value returned from __reduce__,
directly, the __basicnew__ method of the first value returned
from __reduce__ is called without arguments.
This commit is contained in:
parent
61280916f6
commit
9716aaa14c
1 changed files with 50 additions and 24 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
cPickle.c,v 1.46 1997/12/04 00:08:07 jim Exp
|
cPickle.c,v 1.48 1997/12/07 14:37:39 jim Exp
|
||||||
|
|
||||||
Copyright
|
Copyright
|
||||||
|
|
||||||
|
|
@ -55,7 +55,7 @@
|
||||||
static char cPickle_module_documentation[] =
|
static char cPickle_module_documentation[] =
|
||||||
"C implementation and optimization of the Python pickle module\n"
|
"C implementation and optimization of the Python pickle module\n"
|
||||||
"\n"
|
"\n"
|
||||||
"cPickle.c,v 1.46 1997/12/04 00:08:07 jim Exp\n"
|
"cPickle.c,v 1.48 1997/12/07 14:37:39 jim Exp\n"
|
||||||
;
|
;
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
|
|
@ -132,7 +132,7 @@ static PyObject *empty_tuple;
|
||||||
static PyObject *__class___str, *__getinitargs___str, *__dict___str,
|
static PyObject *__class___str, *__getinitargs___str, *__dict___str,
|
||||||
*__getstate___str, *__setstate___str, *__name___str, *__reduce___str,
|
*__getstate___str, *__setstate___str, *__name___str, *__reduce___str,
|
||||||
*write_str, *__safe_for_unpickling___str, *append_str,
|
*write_str, *__safe_for_unpickling___str, *append_str,
|
||||||
*read_str, *readline_str, *__main___str,
|
*read_str, *readline_str, *__main___str, *__basicnew___str,
|
||||||
*copy_reg_str, *dispatch_table_str, *safe_constructors_str;
|
*copy_reg_str, *dispatch_table_str, *safe_constructors_str;
|
||||||
|
|
||||||
static int save();
|
static int save();
|
||||||
|
|
@ -155,7 +155,7 @@ typedef struct {
|
||||||
PyObject *class_map;
|
PyObject *class_map;
|
||||||
} Picklerobject;
|
} Picklerobject;
|
||||||
|
|
||||||
static PyTypeObject Picklertype;
|
staticforward PyTypeObject Picklertype;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
|
|
@ -180,7 +180,7 @@ typedef struct {
|
||||||
PyObject *class_map;
|
PyObject *class_map;
|
||||||
} Unpicklerobject;
|
} Unpicklerobject;
|
||||||
|
|
||||||
static PyTypeObject Unpicklertype;
|
staticforward PyTypeObject Unpicklertype;
|
||||||
|
|
||||||
int
|
int
|
||||||
cPickle_PyMapping_HasKey(PyObject *o, PyObject *key) {
|
cPickle_PyMapping_HasKey(PyObject *o, PyObject *key) {
|
||||||
|
|
@ -1659,7 +1659,7 @@ save(Picklerobject *self, PyObject *args, int pers_save) {
|
||||||
state = PyTuple_GET_ITEM(t, 2);
|
state = PyTuple_GET_ITEM(t, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
UNLESS(PyTuple_Check(arg_tup)) {
|
UNLESS(PyTuple_Check(arg_tup) || arg_tup==Py_None) {
|
||||||
PyErr_Format(PicklingError, "Second element of tuple "
|
PyErr_Format(PicklingError, "Second element of tuple "
|
||||||
"returned by %s must be a tuple", "O", __reduce__);
|
"returned by %s must be a tuple", "O", __reduce__);
|
||||||
goto finally;
|
goto finally;
|
||||||
|
|
@ -1931,9 +1931,8 @@ static char Picklertype__doc__[] =
|
||||||
"Objects that know how to pickle objects\n"
|
"Objects that know how to pickle objects\n"
|
||||||
;
|
;
|
||||||
|
|
||||||
static PyTypeObject Picklertype_value() {
|
static PyTypeObject Picklertype = {
|
||||||
PyTypeObject Picklertype = {
|
PyObject_HEAD_INIT(NULL)
|
||||||
PyObject_HEAD_INIT(&PyType_Type)
|
|
||||||
0, /*ob_size*/
|
0, /*ob_size*/
|
||||||
"Pickler", /*tp_name*/
|
"Pickler", /*tp_name*/
|
||||||
sizeof(Picklerobject), /*tp_basicsize*/
|
sizeof(Picklerobject), /*tp_basicsize*/
|
||||||
|
|
@ -1955,9 +1954,7 @@ static PyTypeObject Picklertype_value() {
|
||||||
/* Space for future expansion */
|
/* Space for future expansion */
|
||||||
0L,0L,0L,0L,
|
0L,0L,0L,0L,
|
||||||
Picklertype__doc__ /* Documentation string */
|
Picklertype__doc__ /* Documentation string */
|
||||||
};
|
};
|
||||||
return Picklertype;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
find_class(PyObject *class_map,
|
find_class(PyObject *class_map,
|
||||||
|
|
@ -2257,14 +2254,30 @@ finally:
|
||||||
static int
|
static int
|
||||||
load_string(Unpicklerobject *self) {
|
load_string(Unpicklerobject *self) {
|
||||||
PyObject *str = 0;
|
PyObject *str = 0;
|
||||||
int len, res = -1;
|
int len, res = -1, nslash;
|
||||||
char *s;
|
char *s, q, *p;
|
||||||
|
|
||||||
static PyObject *eval_dict = 0;
|
static PyObject *eval_dict = 0;
|
||||||
|
|
||||||
if ((len = (*self->readline_func)(self, &s)) < 0) return -1;
|
if ((len = (*self->readline_func)(self, &s)) < 0) return -1;
|
||||||
UNLESS(s=pystrndup(s,len)) return -1;
|
UNLESS(s=pystrndup(s,len)) return -1;
|
||||||
|
|
||||||
|
/* Check for unquoted quotes (evil strings) */
|
||||||
|
q=*s;
|
||||||
|
if(q != '"' && q != '\'') goto insecure;
|
||||||
|
for(p=s+1, nslash=0; *p; p++)
|
||||||
|
{
|
||||||
|
if(*p==q && nslash%2==0) break;
|
||||||
|
if(*p=='\\') nslash++;
|
||||||
|
else nslash=0;
|
||||||
|
}
|
||||||
|
if(*p==q)
|
||||||
|
{
|
||||||
|
for(p++; *p; p++) if(*p > ' ') goto insecure;
|
||||||
|
}
|
||||||
|
else goto insecure;
|
||||||
|
/********************************************/
|
||||||
|
|
||||||
UNLESS(eval_dict)
|
UNLESS(eval_dict)
|
||||||
UNLESS(eval_dict = Py_BuildValue("{s{}}", "__builtins__"))
|
UNLESS(eval_dict = Py_BuildValue("{s{}}", "__builtins__"))
|
||||||
goto finally;
|
goto finally;
|
||||||
|
|
@ -2282,6 +2295,11 @@ finally:
|
||||||
Py_XDECREF(str);
|
Py_XDECREF(str);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
|
insecure:
|
||||||
|
free(s);
|
||||||
|
PyErr_SetString(PyExc_ValueError,"insecure string pickle");
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2555,6 +2573,17 @@ Instance_New(PyObject *cls, PyObject *args) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(args==Py_None)
|
||||||
|
{
|
||||||
|
/* Special case, call cls.__basicnew__() */
|
||||||
|
PyObject *basicnew;
|
||||||
|
|
||||||
|
UNLESS(basicnew=PyObject_GetAttr(cls, __basicnew___str)) return NULL;
|
||||||
|
r=PyObject_CallObject(basicnew, NULL);
|
||||||
|
Py_DECREF(basicnew);
|
||||||
|
if(r) return r;
|
||||||
|
}
|
||||||
|
|
||||||
if((r=PyObject_CallObject(cls, args))) return r;
|
if((r=PyObject_CallObject(cls, args))) return r;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
|
@ -4129,9 +4158,8 @@ finally:
|
||||||
static char Unpicklertype__doc__[] =
|
static char Unpicklertype__doc__[] =
|
||||||
"Objects that know how to unpickle";
|
"Objects that know how to unpickle";
|
||||||
|
|
||||||
static PyTypeObject Unpicklertype_value() {
|
static PyTypeObject Unpicklertype = {
|
||||||
PyTypeObject Unpicklertype = {
|
PyObject_HEAD_INIT(NULL)
|
||||||
PyObject_HEAD_INIT(&PyType_Type)
|
|
||||||
0, /*ob_size*/
|
0, /*ob_size*/
|
||||||
"Unpickler", /*tp_name*/
|
"Unpickler", /*tp_name*/
|
||||||
sizeof(Unpicklerobject), /*tp_basicsize*/
|
sizeof(Unpicklerobject), /*tp_basicsize*/
|
||||||
|
|
@ -4153,9 +4181,7 @@ static PyTypeObject Unpicklertype_value() {
|
||||||
/* Space for future expansion */
|
/* Space for future expansion */
|
||||||
0L,0L,0L,0L,
|
0L,0L,0L,0L,
|
||||||
Unpicklertype__doc__ /* Documentation string */
|
Unpicklertype__doc__ /* Documentation string */
|
||||||
};
|
};
|
||||||
return Unpicklertype;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct PyMethodDef cPickle_methods[] = {
|
static struct PyMethodDef cPickle_methods[] = {
|
||||||
{"dump", (PyCFunction)cpm_dump, 1,
|
{"dump", (PyCFunction)cpm_dump, 1,
|
||||||
|
|
@ -4227,6 +4253,7 @@ init_stuff(PyObject *module, PyObject *module_dict) {
|
||||||
INIT_STR(copy_reg);
|
INIT_STR(copy_reg);
|
||||||
INIT_STR(dispatch_table);
|
INIT_STR(dispatch_table);
|
||||||
INIT_STR(safe_constructors);
|
INIT_STR(safe_constructors);
|
||||||
|
INIT_STR(__basicnew__);
|
||||||
|
|
||||||
UNLESS(copy_reg = PyImport_ImportModule("copy_reg"))
|
UNLESS(copy_reg = PyImport_ImportModule("copy_reg"))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -4280,19 +4307,18 @@ init_stuff(PyObject *module, PyObject *module_dict) {
|
||||||
void
|
void
|
||||||
initcPickle() {
|
initcPickle() {
|
||||||
PyObject *m, *d, *v;
|
PyObject *m, *d, *v;
|
||||||
char *rev="1.46";
|
char *rev="1.48";
|
||||||
PyObject *format_version;
|
PyObject *format_version;
|
||||||
PyObject *compatible_formats;
|
PyObject *compatible_formats;
|
||||||
|
|
||||||
|
Picklertype.ob_type = &PyType_Type;
|
||||||
|
Unpicklertype.ob_type = &PyType_Type;
|
||||||
|
|
||||||
/* Create the module and add the functions */
|
/* Create the module and add the functions */
|
||||||
m = Py_InitModule4("cPickle", cPickle_methods,
|
m = Py_InitModule4("cPickle", cPickle_methods,
|
||||||
cPickle_module_documentation,
|
cPickle_module_documentation,
|
||||||
(PyObject*)NULL,PYTHON_API_VERSION);
|
(PyObject*)NULL,PYTHON_API_VERSION);
|
||||||
|
|
||||||
Picklertype=Picklertype_value();
|
|
||||||
Unpicklertype=Unpicklertype_value();
|
|
||||||
|
|
||||||
/* Add some symbolic constants to the module */
|
/* Add some symbolic constants to the module */
|
||||||
d = PyModule_GetDict(m);
|
d = PyModule_GetDict(m);
|
||||||
PyDict_SetItemString(d,"__version__", v = PyString_FromString(rev));
|
PyDict_SetItemString(d,"__version__", v = PyString_FromString(rev));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue