Added handling of PyOS_double_to_string out-of-memory errors. Closes issue 5775.
This commit is contained in:
parent
960dc3626a
commit
b1a03cf716
|
@ -47,9 +47,14 @@
|
||||||
#define TYPE_SET '<'
|
#define TYPE_SET '<'
|
||||||
#define TYPE_FROZENSET '>'
|
#define TYPE_FROZENSET '>'
|
||||||
|
|
||||||
|
#define WFERR_OK 0
|
||||||
|
#define WFERR_UNMARSHALLABLE 1
|
||||||
|
#define WFERR_NESTEDTOODEEP 2
|
||||||
|
#define WFERR_NOMEMORY 3
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
int error;
|
int error; /* see WFERR_* values */
|
||||||
int depth;
|
int depth;
|
||||||
/* If fp == NULL, the following are valid: */
|
/* If fp == NULL, the following are valid: */
|
||||||
PyObject *str;
|
PyObject *str;
|
||||||
|
@ -182,7 +187,7 @@ w_object(PyObject *v, WFILE *p)
|
||||||
p->depth++;
|
p->depth++;
|
||||||
|
|
||||||
if (p->depth > MAX_MARSHAL_STACK_DEPTH) {
|
if (p->depth > MAX_MARSHAL_STACK_DEPTH) {
|
||||||
p->error = 2;
|
p->error = WFERR_NESTEDTOODEEP;
|
||||||
}
|
}
|
||||||
else if (v == NULL) {
|
else if (v == NULL) {
|
||||||
w_byte(TYPE_NULL, p);
|
w_byte(TYPE_NULL, p);
|
||||||
|
@ -229,7 +234,7 @@ w_object(PyObject *v, WFILE *p)
|
||||||
unsigned char buf[8];
|
unsigned char buf[8];
|
||||||
if (_PyFloat_Pack8(PyFloat_AsDouble(v),
|
if (_PyFloat_Pack8(PyFloat_AsDouble(v),
|
||||||
buf, 1) < 0) {
|
buf, 1) < 0) {
|
||||||
p->error = 1;
|
p->error = WFERR_UNMARSHALLABLE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
w_byte(TYPE_BINARY_FLOAT, p);
|
w_byte(TYPE_BINARY_FLOAT, p);
|
||||||
|
@ -238,8 +243,10 @@ w_object(PyObject *v, WFILE *p)
|
||||||
else {
|
else {
|
||||||
char *buf = PyOS_double_to_string(PyFloat_AS_DOUBLE(v),
|
char *buf = PyOS_double_to_string(PyFloat_AS_DOUBLE(v),
|
||||||
'g', 17, 0, NULL);
|
'g', 17, 0, NULL);
|
||||||
if (!buf)
|
if (!buf) {
|
||||||
return;
|
p->error = WFERR_NOMEMORY;
|
||||||
|
return;
|
||||||
|
}
|
||||||
n = strlen(buf);
|
n = strlen(buf);
|
||||||
w_byte(TYPE_FLOAT, p);
|
w_byte(TYPE_FLOAT, p);
|
||||||
w_byte((int)n, p);
|
w_byte((int)n, p);
|
||||||
|
@ -253,14 +260,14 @@ w_object(PyObject *v, WFILE *p)
|
||||||
unsigned char buf[8];
|
unsigned char buf[8];
|
||||||
if (_PyFloat_Pack8(PyComplex_RealAsDouble(v),
|
if (_PyFloat_Pack8(PyComplex_RealAsDouble(v),
|
||||||
buf, 1) < 0) {
|
buf, 1) < 0) {
|
||||||
p->error = 1;
|
p->error = WFERR_UNMARSHALLABLE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
w_byte(TYPE_BINARY_COMPLEX, p);
|
w_byte(TYPE_BINARY_COMPLEX, p);
|
||||||
w_string((char*)buf, 8, p);
|
w_string((char*)buf, 8, p);
|
||||||
if (_PyFloat_Pack8(PyComplex_ImagAsDouble(v),
|
if (_PyFloat_Pack8(PyComplex_ImagAsDouble(v),
|
||||||
buf, 1) < 0) {
|
buf, 1) < 0) {
|
||||||
p->error = 1;
|
p->error = WFERR_UNMARSHALLABLE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
w_string((char*)buf, 8, p);
|
w_string((char*)buf, 8, p);
|
||||||
|
@ -270,16 +277,20 @@ w_object(PyObject *v, WFILE *p)
|
||||||
w_byte(TYPE_COMPLEX, p);
|
w_byte(TYPE_COMPLEX, p);
|
||||||
buf = PyOS_double_to_string(PyComplex_RealAsDouble(v),
|
buf = PyOS_double_to_string(PyComplex_RealAsDouble(v),
|
||||||
'g', 17, 0, NULL);
|
'g', 17, 0, NULL);
|
||||||
if (!buf)
|
if (!buf) {
|
||||||
return;
|
p->error = WFERR_NOMEMORY;
|
||||||
|
return;
|
||||||
|
}
|
||||||
n = strlen(buf);
|
n = strlen(buf);
|
||||||
w_byte((int)n, p);
|
w_byte((int)n, p);
|
||||||
w_string(buf, (int)n, p);
|
w_string(buf, (int)n, p);
|
||||||
PyMem_Free(buf);
|
PyMem_Free(buf);
|
||||||
buf = PyOS_double_to_string(PyComplex_ImagAsDouble(v),
|
buf = PyOS_double_to_string(PyComplex_ImagAsDouble(v),
|
||||||
'g', 17, 0, NULL);
|
'g', 17, 0, NULL);
|
||||||
if (!buf)
|
if (!buf) {
|
||||||
return;
|
p->error = WFERR_NOMEMORY;
|
||||||
|
return;
|
||||||
|
}
|
||||||
n = strlen(buf);
|
n = strlen(buf);
|
||||||
w_byte((int)n, p);
|
w_byte((int)n, p);
|
||||||
w_string(buf, (int)n, p);
|
w_string(buf, (int)n, p);
|
||||||
|
@ -293,7 +304,7 @@ w_object(PyObject *v, WFILE *p)
|
||||||
if (n > INT_MAX) {
|
if (n > INT_MAX) {
|
||||||
/* huge strings are not supported */
|
/* huge strings are not supported */
|
||||||
p->depth--;
|
p->depth--;
|
||||||
p->error = 1;
|
p->error = WFERR_UNMARSHALLABLE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
w_long((long)n, p);
|
w_long((long)n, p);
|
||||||
|
@ -304,14 +315,14 @@ w_object(PyObject *v, WFILE *p)
|
||||||
utf8 = PyUnicode_AsUTF8String(v);
|
utf8 = PyUnicode_AsUTF8String(v);
|
||||||
if (utf8 == NULL) {
|
if (utf8 == NULL) {
|
||||||
p->depth--;
|
p->depth--;
|
||||||
p->error = 1;
|
p->error = WFERR_UNMARSHALLABLE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
w_byte(TYPE_UNICODE, p);
|
w_byte(TYPE_UNICODE, p);
|
||||||
n = PyBytes_GET_SIZE(utf8);
|
n = PyBytes_GET_SIZE(utf8);
|
||||||
if (n > INT_MAX) {
|
if (n > INT_MAX) {
|
||||||
p->depth--;
|
p->depth--;
|
||||||
p->error = 1;
|
p->error = WFERR_UNMARSHALLABLE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
w_long((long)n, p);
|
w_long((long)n, p);
|
||||||
|
@ -356,14 +367,14 @@ w_object(PyObject *v, WFILE *p)
|
||||||
n = PyObject_Size(v);
|
n = PyObject_Size(v);
|
||||||
if (n == -1) {
|
if (n == -1) {
|
||||||
p->depth--;
|
p->depth--;
|
||||||
p->error = 1;
|
p->error = WFERR_UNMARSHALLABLE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
w_long((long)n, p);
|
w_long((long)n, p);
|
||||||
it = PyObject_GetIter(v);
|
it = PyObject_GetIter(v);
|
||||||
if (it == NULL) {
|
if (it == NULL) {
|
||||||
p->depth--;
|
p->depth--;
|
||||||
p->error = 1;
|
p->error = WFERR_UNMARSHALLABLE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
while ((value = PyIter_Next(it)) != NULL) {
|
while ((value = PyIter_Next(it)) != NULL) {
|
||||||
|
@ -373,7 +384,7 @@ w_object(PyObject *v, WFILE *p)
|
||||||
Py_DECREF(it);
|
Py_DECREF(it);
|
||||||
if (PyErr_Occurred()) {
|
if (PyErr_Occurred()) {
|
||||||
p->depth--;
|
p->depth--;
|
||||||
p->error = 1;
|
p->error = WFERR_UNMARSHALLABLE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -403,14 +414,14 @@ w_object(PyObject *v, WFILE *p)
|
||||||
Py_buffer view;
|
Py_buffer view;
|
||||||
if ((*pb->bf_getbuffer)(v, &view, PyBUF_SIMPLE) != 0) {
|
if ((*pb->bf_getbuffer)(v, &view, PyBUF_SIMPLE) != 0) {
|
||||||
w_byte(TYPE_UNKNOWN, p);
|
w_byte(TYPE_UNKNOWN, p);
|
||||||
p->error = 1;
|
p->error = WFERR_UNMARSHALLABLE;
|
||||||
}
|
}
|
||||||
w_byte(TYPE_STRING, p);
|
w_byte(TYPE_STRING, p);
|
||||||
n = view.len;
|
n = view.len;
|
||||||
s = view.buf;
|
s = view.buf;
|
||||||
if (n > INT_MAX) {
|
if (n > INT_MAX) {
|
||||||
p->depth--;
|
p->depth--;
|
||||||
p->error = 1;
|
p->error = WFERR_UNMARSHALLABLE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
w_long((long)n, p);
|
w_long((long)n, p);
|
||||||
|
@ -420,7 +431,7 @@ w_object(PyObject *v, WFILE *p)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
w_byte(TYPE_UNKNOWN, p);
|
w_byte(TYPE_UNKNOWN, p);
|
||||||
p->error = 1;
|
p->error = WFERR_UNMARSHALLABLE;
|
||||||
}
|
}
|
||||||
p->depth--;
|
p->depth--;
|
||||||
}
|
}
|
||||||
|
@ -431,7 +442,7 @@ PyMarshal_WriteLongToFile(long x, FILE *fp, int version)
|
||||||
{
|
{
|
||||||
WFILE wf;
|
WFILE wf;
|
||||||
wf.fp = fp;
|
wf.fp = fp;
|
||||||
wf.error = 0;
|
wf.error = WFERR_OK;
|
||||||
wf.depth = 0;
|
wf.depth = 0;
|
||||||
wf.strings = NULL;
|
wf.strings = NULL;
|
||||||
wf.version = version;
|
wf.version = version;
|
||||||
|
@ -443,7 +454,7 @@ PyMarshal_WriteObjectToFile(PyObject *x, FILE *fp, int version)
|
||||||
{
|
{
|
||||||
WFILE wf;
|
WFILE wf;
|
||||||
wf.fp = fp;
|
wf.fp = fp;
|
||||||
wf.error = 0;
|
wf.error = WFERR_OK;
|
||||||
wf.depth = 0;
|
wf.depth = 0;
|
||||||
wf.strings = (version > 0) ? PyDict_New() : NULL;
|
wf.strings = (version > 0) ? PyDict_New() : NULL;
|
||||||
wf.version = version;
|
wf.version = version;
|
||||||
|
@ -1143,7 +1154,7 @@ PyMarshal_WriteObjectToString(PyObject *x, int version)
|
||||||
return NULL;
|
return NULL;
|
||||||
wf.ptr = PyBytes_AS_STRING((PyBytesObject *)wf.str);
|
wf.ptr = PyBytes_AS_STRING((PyBytesObject *)wf.str);
|
||||||
wf.end = wf.ptr + PyBytes_Size(wf.str);
|
wf.end = wf.ptr + PyBytes_Size(wf.str);
|
||||||
wf.error = 0;
|
wf.error = WFERR_OK;
|
||||||
wf.depth = 0;
|
wf.depth = 0;
|
||||||
wf.version = version;
|
wf.version = version;
|
||||||
wf.strings = (version > 0) ? PyDict_New() : NULL;
|
wf.strings = (version > 0) ? PyDict_New() : NULL;
|
||||||
|
@ -1160,11 +1171,14 @@ PyMarshal_WriteObjectToString(PyObject *x, int version)
|
||||||
if (_PyBytes_Resize(&wf.str, (Py_ssize_t)(wf.ptr - base)) < 0)
|
if (_PyBytes_Resize(&wf.str, (Py_ssize_t)(wf.ptr - base)) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (wf.error) {
|
if (wf.error != WFERR_OK) {
|
||||||
Py_XDECREF(wf.str);
|
Py_XDECREF(wf.str);
|
||||||
PyErr_SetString(PyExc_ValueError,
|
if (wf.error == WFERR_NOMEMORY)
|
||||||
(wf.error==1)?"unmarshallable object"
|
PyErr_NoMemory();
|
||||||
:"object too deeply nested to marshal");
|
else
|
||||||
|
PyErr_SetString(PyExc_ValueError,
|
||||||
|
(wf.error==WFERR_UNMARSHALLABLE)?"unmarshallable object"
|
||||||
|
:"object too deeply nested to marshal");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (wf.str != NULL) {
|
if (wf.str != NULL) {
|
||||||
|
|
Loading…
Reference in New Issue