bpo-39943: Clean up marshal.c. (GH-19236)
* Add consts. * Remove redundant casts and checks. * Use concrete C API macros. * Avoid raising and silencing OverflowError for ints.
This commit is contained in:
parent
a9f9687a7c
commit
2c003eff8f
|
@ -83,7 +83,7 @@ typedef struct {
|
||||||
int depth;
|
int depth;
|
||||||
PyObject *str;
|
PyObject *str;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
char *end;
|
const char *end;
|
||||||
char *buf;
|
char *buf;
|
||||||
_Py_hashtable_t *hashtable;
|
_Py_hashtable_t *hashtable;
|
||||||
int version;
|
int version;
|
||||||
|
@ -114,7 +114,7 @@ w_reserve(WFILE *p, Py_ssize_t needed)
|
||||||
}
|
}
|
||||||
assert(p->str != NULL);
|
assert(p->str != NULL);
|
||||||
pos = p->ptr - p->buf;
|
pos = p->ptr - p->buf;
|
||||||
size = PyBytes_Size(p->str);
|
size = PyBytes_GET_SIZE(p->str);
|
||||||
if (size > 16*1024*1024)
|
if (size > 16*1024*1024)
|
||||||
delta = (size >> 3); /* 12.5% overallocation */
|
delta = (size >> 3); /* 12.5% overallocation */
|
||||||
else
|
else
|
||||||
|
@ -126,7 +126,7 @@ w_reserve(WFILE *p, Py_ssize_t needed)
|
||||||
}
|
}
|
||||||
size += delta;
|
size += delta;
|
||||||
if (_PyBytes_Resize(&p->str, size) != 0) {
|
if (_PyBytes_Resize(&p->str, size) != 0) {
|
||||||
p->ptr = p->buf = p->end = NULL;
|
p->end = p->ptr = p->buf = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -138,7 +138,7 @@ w_reserve(WFILE *p, Py_ssize_t needed)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
w_string(const char *s, Py_ssize_t n, WFILE *p)
|
w_string(const void *s, Py_ssize_t n, WFILE *p)
|
||||||
{
|
{
|
||||||
Py_ssize_t m;
|
Py_ssize_t m;
|
||||||
if (!n || p->ptr == NULL)
|
if (!n || p->ptr == NULL)
|
||||||
|
@ -194,14 +194,14 @@ w_long(long x, WFILE *p)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
w_pstring(const char *s, Py_ssize_t n, WFILE *p)
|
w_pstring(const void *s, Py_ssize_t n, WFILE *p)
|
||||||
{
|
{
|
||||||
W_SIZE(n, p);
|
W_SIZE(n, p);
|
||||||
w_string(s, n, p);
|
w_string(s, n, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
w_short_pstring(const char *s, Py_ssize_t n, WFILE *p)
|
w_short_pstring(const void *s, Py_ssize_t n, WFILE *p)
|
||||||
{
|
{
|
||||||
w_byte(Py_SAFE_DOWNCAST(n, Py_ssize_t, unsigned char), p);
|
w_byte(Py_SAFE_DOWNCAST(n, Py_ssize_t, unsigned char), p);
|
||||||
w_string(s, n, p);
|
w_string(s, n, p);
|
||||||
|
@ -274,21 +274,18 @@ w_float_bin(double v, WFILE *p)
|
||||||
p->error = WFERR_UNMARSHALLABLE;
|
p->error = WFERR_UNMARSHALLABLE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
w_string((const char *)buf, 8, p);
|
w_string(buf, 8, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
w_float_str(double v, WFILE *p)
|
w_float_str(double v, WFILE *p)
|
||||||
{
|
{
|
||||||
int n;
|
|
||||||
char *buf = PyOS_double_to_string(v, 'g', 17, 0, NULL);
|
char *buf = PyOS_double_to_string(v, 'g', 17, 0, NULL);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
p->error = WFERR_NOMEMORY;
|
p->error = WFERR_NOMEMORY;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
n = (int)strlen(buf);
|
w_short_pstring(buf, strlen(buf), p);
|
||||||
w_byte(n, p);
|
|
||||||
w_string(buf, n, p);
|
|
||||||
PyMem_Free(buf);
|
PyMem_Free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -378,11 +375,10 @@ w_complex_object(PyObject *v, char flag, WFILE *p)
|
||||||
Py_ssize_t i, n;
|
Py_ssize_t i, n;
|
||||||
|
|
||||||
if (PyLong_CheckExact(v)) {
|
if (PyLong_CheckExact(v)) {
|
||||||
long x = PyLong_AsLong(v);
|
int overflow;
|
||||||
if ((x == -1) && PyErr_Occurred()) {
|
long x = PyLong_AsLongAndOverflow(v, &overflow);
|
||||||
PyLongObject *ob = (PyLongObject *)v;
|
if (overflow) {
|
||||||
PyErr_Clear();
|
w_PyLong((PyLongObject *)v, flag, p);
|
||||||
w_PyLong(ob, flag, p);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#if SIZEOF_LONG > 4
|
#if SIZEOF_LONG > 4
|
||||||
|
@ -433,7 +429,7 @@ w_complex_object(PyObject *v, char flag, WFILE *p)
|
||||||
W_TYPE(TYPE_SHORT_ASCII_INTERNED, p);
|
W_TYPE(TYPE_SHORT_ASCII_INTERNED, p);
|
||||||
else
|
else
|
||||||
W_TYPE(TYPE_SHORT_ASCII, p);
|
W_TYPE(TYPE_SHORT_ASCII, p);
|
||||||
w_short_pstring((char *) PyUnicode_1BYTE_DATA(v),
|
w_short_pstring(PyUnicode_1BYTE_DATA(v),
|
||||||
PyUnicode_GET_LENGTH(v), p);
|
PyUnicode_GET_LENGTH(v), p);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -441,7 +437,7 @@ w_complex_object(PyObject *v, char flag, WFILE *p)
|
||||||
W_TYPE(TYPE_ASCII_INTERNED, p);
|
W_TYPE(TYPE_ASCII_INTERNED, p);
|
||||||
else
|
else
|
||||||
W_TYPE(TYPE_ASCII, p);
|
W_TYPE(TYPE_ASCII, p);
|
||||||
w_pstring((char *) PyUnicode_1BYTE_DATA(v),
|
w_pstring(PyUnicode_1BYTE_DATA(v),
|
||||||
PyUnicode_GET_LENGTH(v), p);
|
PyUnicode_GET_LENGTH(v), p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -462,7 +458,7 @@ w_complex_object(PyObject *v, char flag, WFILE *p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (PyTuple_CheckExact(v)) {
|
else if (PyTuple_CheckExact(v)) {
|
||||||
n = PyTuple_Size(v);
|
n = PyTuple_GET_SIZE(v);
|
||||||
if (p->version >= 4 && n < 256) {
|
if (p->version >= 4 && n < 256) {
|
||||||
W_TYPE(TYPE_SMALL_TUPLE, p);
|
W_TYPE(TYPE_SMALL_TUPLE, p);
|
||||||
w_byte((unsigned char)n, p);
|
w_byte((unsigned char)n, p);
|
||||||
|
@ -496,34 +492,18 @@ w_complex_object(PyObject *v, char flag, WFILE *p)
|
||||||
w_object((PyObject *)NULL, p);
|
w_object((PyObject *)NULL, p);
|
||||||
}
|
}
|
||||||
else if (PyAnySet_CheckExact(v)) {
|
else if (PyAnySet_CheckExact(v)) {
|
||||||
PyObject *value, *it;
|
PyObject *value;
|
||||||
|
Py_ssize_t pos = 0;
|
||||||
|
Py_hash_t hash;
|
||||||
|
|
||||||
if (PyObject_TypeCheck(v, &PySet_Type))
|
if (PyFrozenSet_CheckExact(v))
|
||||||
W_TYPE(TYPE_SET, p);
|
|
||||||
else
|
|
||||||
W_TYPE(TYPE_FROZENSET, p);
|
W_TYPE(TYPE_FROZENSET, p);
|
||||||
n = PyObject_Size(v);
|
else
|
||||||
if (n == -1) {
|
W_TYPE(TYPE_SET, p);
|
||||||
p->depth--;
|
n = PySet_GET_SIZE(v);
|
||||||
p->error = WFERR_UNMARSHALLABLE;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
W_SIZE(n, p);
|
W_SIZE(n, p);
|
||||||
it = PyObject_GetIter(v);
|
while (_PySet_NextEntry(v, &pos, &value, &hash)) {
|
||||||
if (it == NULL) {
|
|
||||||
p->depth--;
|
|
||||||
p->error = WFERR_UNMARSHALLABLE;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
while ((value = PyIter_Next(it)) != NULL) {
|
|
||||||
w_object(value, p);
|
w_object(value, p);
|
||||||
Py_DECREF(value);
|
|
||||||
}
|
|
||||||
Py_DECREF(it);
|
|
||||||
if (PyErr_Occurred()) {
|
|
||||||
p->depth--;
|
|
||||||
p->error = WFERR_UNMARSHALLABLE;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (PyCode_Check(v)) {
|
else if (PyCode_Check(v)) {
|
||||||
|
@ -638,8 +618,8 @@ typedef struct {
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
int depth;
|
int depth;
|
||||||
PyObject *readable; /* Stream-like object being read from */
|
PyObject *readable; /* Stream-like object being read from */
|
||||||
char *ptr;
|
const char *ptr;
|
||||||
char *end;
|
const char *end;
|
||||||
char *buf;
|
char *buf;
|
||||||
Py_ssize_t buf_size;
|
Py_ssize_t buf_size;
|
||||||
PyObject *refs; /* a list */
|
PyObject *refs; /* a list */
|
||||||
|
@ -652,7 +632,7 @@ r_string(Py_ssize_t n, RFILE *p)
|
||||||
|
|
||||||
if (p->ptr != NULL) {
|
if (p->ptr != NULL) {
|
||||||
/* Fast path for loads() */
|
/* Fast path for loads() */
|
||||||
char *res = p->ptr;
|
const char *res = p->ptr;
|
||||||
Py_ssize_t left = p->end - p->ptr;
|
Py_ssize_t left = p->end - p->ptr;
|
||||||
if (left < n) {
|
if (left < n) {
|
||||||
PyErr_SetString(PyExc_EOFError,
|
PyErr_SetString(PyExc_EOFError,
|
||||||
|
@ -1564,8 +1544,8 @@ PyMarshal_ReadObjectFromString(const char *str, Py_ssize_t len)
|
||||||
PyObject *result;
|
PyObject *result;
|
||||||
rf.fp = NULL;
|
rf.fp = NULL;
|
||||||
rf.readable = NULL;
|
rf.readable = NULL;
|
||||||
rf.ptr = (char *)str;
|
rf.ptr = str;
|
||||||
rf.end = (char *)str + len;
|
rf.end = str + len;
|
||||||
rf.buf = NULL;
|
rf.buf = NULL;
|
||||||
rf.depth = 0;
|
rf.depth = 0;
|
||||||
rf.refs = PyList_New(0);
|
rf.refs = PyList_New(0);
|
||||||
|
@ -1587,8 +1567,8 @@ PyMarshal_WriteObjectToString(PyObject *x, int version)
|
||||||
wf.str = PyBytes_FromStringAndSize((char *)NULL, 50);
|
wf.str = PyBytes_FromStringAndSize((char *)NULL, 50);
|
||||||
if (wf.str == NULL)
|
if (wf.str == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
wf.ptr = wf.buf = PyBytes_AS_STRING((PyBytesObject *)wf.str);
|
wf.ptr = wf.buf = PyBytes_AS_STRING(wf.str);
|
||||||
wf.end = wf.ptr + PyBytes_Size(wf.str);
|
wf.end = wf.ptr + PyBytes_GET_SIZE(wf.str);
|
||||||
wf.error = WFERR_OK;
|
wf.error = WFERR_OK;
|
||||||
wf.version = version;
|
wf.version = version;
|
||||||
if (w_init_refs(&wf, version)) {
|
if (w_init_refs(&wf, version)) {
|
||||||
|
@ -1598,13 +1578,7 @@ PyMarshal_WriteObjectToString(PyObject *x, int version)
|
||||||
w_object(x, &wf);
|
w_object(x, &wf);
|
||||||
w_clear_refs(&wf);
|
w_clear_refs(&wf);
|
||||||
if (wf.str != NULL) {
|
if (wf.str != NULL) {
|
||||||
char *base = PyBytes_AS_STRING((PyBytesObject *)wf.str);
|
const char *base = PyBytes_AS_STRING(wf.str);
|
||||||
if (wf.ptr - base > PY_SSIZE_T_MAX) {
|
|
||||||
Py_DECREF(wf.str);
|
|
||||||
PyErr_SetString(PyExc_OverflowError,
|
|
||||||
"too much marshal data for a bytes object");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue