Commit 828bb643 authored by Jim Fulton's avatar 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 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.
parent 62b0087f
/* /*
$Id: cPickle.c,v 1.46 1997/12/04 00:08:07 jim Exp $ $Id: cPickle.c,v 1.47 1997/12/07 14:25:53 jim Exp $
Copyright Copyright
...@@ -55,7 +55,7 @@ ...@@ -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"
"$Id: cPickle.c,v 1.46 1997/12/04 00:08:07 jim Exp $\n" "$Id: cPickle.c,v 1.47 1997/12/07 14:25:53 jim Exp $\n"
; ;
#include "Python.h" #include "Python.h"
...@@ -132,7 +132,7 @@ static PyObject *empty_tuple; ...@@ -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();
...@@ -1659,7 +1659,7 @@ save(Picklerobject *self, PyObject *args, int pers_save) { ...@@ -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__[] = ...@@ -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() { ...@@ -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: ...@@ -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: ...@@ -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) { ...@@ -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: ...@@ -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() { ...@@ -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) { ...@@ -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) { ...@@ -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="$Revision: 1.46 $"; char *rev="$Revision: 1.47 $";
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));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment