Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9716aaa

Browse files
committed
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.
1 parent 6128091 commit 9716aaa

1 file changed

Lines changed: 50 additions & 24 deletions

File tree

Modules/cPickle.c

Lines changed: 50 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
cPickle.c,v 1.46 1997/12/04 00:08:07 jim Exp
2+
cPickle.c,v 1.48 1997/12/07 14:37:39 jim Exp
33
44
Copyright
55
@@ -55,7 +55,7 @@
5555
static char cPickle_module_documentation[] =
5656
"C implementation and optimization of the Python pickle module\n"
5757
"\n"
58-
"cPickle.c,v 1.46 1997/12/04 00:08:07 jim Exp\n"
58+
"cPickle.c,v 1.48 1997/12/07 14:37:39 jim Exp\n"
5959
;
6060

6161
#include "Python.h"
@@ -132,7 +132,7 @@ static PyObject *empty_tuple;
132132
static PyObject *__class___str, *__getinitargs___str, *__dict___str,
133133
*__getstate___str, *__setstate___str, *__name___str, *__reduce___str,
134134
*write_str, *__safe_for_unpickling___str, *append_str,
135-
*read_str, *readline_str, *__main___str,
135+
*read_str, *readline_str, *__main___str, *__basicnew___str,
136136
*copy_reg_str, *dispatch_table_str, *safe_constructors_str;
137137

138138
static int save();
@@ -155,7 +155,7 @@ typedef struct {
155155
PyObject *class_map;
156156
} Picklerobject;
157157

158-
static PyTypeObject Picklertype;
158+
staticforward PyTypeObject Picklertype;
159159

160160
typedef struct {
161161
PyObject_HEAD
@@ -180,7 +180,7 @@ typedef struct {
180180
PyObject *class_map;
181181
} Unpicklerobject;
182182

183-
static PyTypeObject Unpicklertype;
183+
staticforward PyTypeObject Unpicklertype;
184184

185185
int
186186
cPickle_PyMapping_HasKey(PyObject *o, PyObject *key) {
@@ -1659,7 +1659,7 @@ save(Picklerobject *self, PyObject *args, int pers_save) {
16591659
state = PyTuple_GET_ITEM(t, 2);
16601660
}
16611661

1662-
UNLESS(PyTuple_Check(arg_tup)) {
1662+
UNLESS(PyTuple_Check(arg_tup) || arg_tup==Py_None) {
16631663
PyErr_Format(PicklingError, "Second element of tuple "
16641664
"returned by %s must be a tuple", "O", __reduce__);
16651665
goto finally;
@@ -1931,9 +1931,8 @@ static char Picklertype__doc__[] =
19311931
"Objects that know how to pickle objects\n"
19321932
;
19331933

1934-
static PyTypeObject Picklertype_value() {
1935-
PyTypeObject Picklertype = {
1936-
PyObject_HEAD_INIT(&PyType_Type)
1934+
static PyTypeObject Picklertype = {
1935+
PyObject_HEAD_INIT(NULL)
19371936
0, /*ob_size*/
19381937
"Pickler", /*tp_name*/
19391938
sizeof(Picklerobject), /*tp_basicsize*/
@@ -1955,9 +1954,7 @@ static PyTypeObject Picklertype_value() {
19551954
/* Space for future expansion */
19561955
0L,0L,0L,0L,
19571956
Picklertype__doc__ /* Documentation string */
1958-
};
1959-
return Picklertype;
1960-
}
1957+
};
19611958

19621959
static PyObject *
19631960
find_class(PyObject *class_map,
@@ -2257,14 +2254,30 @@ load_binfloat(Unpicklerobject *self) {
22572254
static int
22582255
load_string(Unpicklerobject *self) {
22592256
PyObject *str = 0;
2260-
int len, res = -1;
2261-
char *s;
2257+
int len, res = -1, nslash;
2258+
char *s, q, *p;
22622259

22632260
static PyObject *eval_dict = 0;
22642261

22652262
if ((len = (*self->readline_func)(self, &s)) < 0) return -1;
22662263
UNLESS(s=pystrndup(s,len)) return -1;
22672264

2265+
/* Check for unquoted quotes (evil strings) */
2266+
q=*s;
2267+
if(q != '"' && q != '\'') goto insecure;
2268+
for(p=s+1, nslash=0; *p; p++)
2269+
{
2270+
if(*p==q && nslash%2==0) break;
2271+
if(*p=='\\') nslash++;
2272+
else nslash=0;
2273+
}
2274+
if(*p==q)
2275+
{
2276+
for(p++; *p; p++) if(*p > ' ') goto insecure;
2277+
}
2278+
else goto insecure;
2279+
/********************************************/
2280+
22682281
UNLESS(eval_dict)
22692282
UNLESS(eval_dict = Py_BuildValue("{s{}}", "__builtins__"))
22702283
goto finally;
@@ -2282,6 +2295,11 @@ load_string(Unpicklerobject *self) {
22822295
Py_XDECREF(str);
22832296

22842297
return res;
2298+
2299+
insecure:
2300+
free(s);
2301+
PyErr_SetString(PyExc_ValueError,"insecure string pickle");
2302+
return -1;
22852303
}
22862304

22872305

@@ -2555,6 +2573,17 @@ Instance_New(PyObject *cls, PyObject *args) {
25552573
return NULL;
25562574
}
25572575

2576+
if(args==Py_None)
2577+
{
2578+
/* Special case, call cls.__basicnew__() */
2579+
PyObject *basicnew;
2580+
2581+
UNLESS(basicnew=PyObject_GetAttr(cls, __basicnew___str)) return NULL;
2582+
r=PyObject_CallObject(basicnew, NULL);
2583+
Py_DECREF(basicnew);
2584+
if(r) return r;
2585+
}
2586+
25582587
if((r=PyObject_CallObject(cls, args))) return r;
25592588

25602589
err:
@@ -4129,9 +4158,8 @@ cpm_loads(PyObject *self, PyObject *args) {
41294158
static char Unpicklertype__doc__[] =
41304159
"Objects that know how to unpickle";
41314160

4132-
static PyTypeObject Unpicklertype_value() {
4133-
PyTypeObject Unpicklertype = {
4134-
PyObject_HEAD_INIT(&PyType_Type)
4161+
static PyTypeObject Unpicklertype = {
4162+
PyObject_HEAD_INIT(NULL)
41354163
0, /*ob_size*/
41364164
"Unpickler", /*tp_name*/
41374165
sizeof(Unpicklerobject), /*tp_basicsize*/
@@ -4153,9 +4181,7 @@ static PyTypeObject Unpicklertype_value() {
41534181
/* Space for future expansion */
41544182
0L,0L,0L,0L,
41554183
Unpicklertype__doc__ /* Documentation string */
4156-
};
4157-
return Unpicklertype;
4158-
}
4184+
};
41594185

41604186
static struct PyMethodDef cPickle_methods[] = {
41614187
{"dump", (PyCFunction)cpm_dump, 1,
@@ -4227,6 +4253,7 @@ init_stuff(PyObject *module, PyObject *module_dict) {
42274253
INIT_STR(copy_reg);
42284254
INIT_STR(dispatch_table);
42294255
INIT_STR(safe_constructors);
4256+
INIT_STR(__basicnew__);
42304257

42314258
UNLESS(copy_reg = PyImport_ImportModule("copy_reg"))
42324259
return -1;
@@ -4280,19 +4307,18 @@ init_stuff(PyObject *module, PyObject *module_dict) {
42804307
void
42814308
initcPickle() {
42824309
PyObject *m, *d, *v;
4283-
char *rev="1.46";
4310+
char *rev="1.48";
42844311
PyObject *format_version;
42854312
PyObject *compatible_formats;
42864313

4314+
Picklertype.ob_type = &PyType_Type;
4315+
Unpicklertype.ob_type = &PyType_Type;
42874316

42884317
/* Create the module and add the functions */
42894318
m = Py_InitModule4("cPickle", cPickle_methods,
42904319
cPickle_module_documentation,
42914320
(PyObject*)NULL,PYTHON_API_VERSION);
42924321

4293-
Picklertype=Picklertype_value();
4294-
Unpicklertype=Unpicklertype_value();
4295-
42964322
/* Add some symbolic constants to the module */
42974323
d = PyModule_GetDict(m);
42984324
PyDict_SetItemString(d,"__version__", v = PyString_FromString(rev));

0 commit comments

Comments
 (0)