Skip to content

Commit 2c003ef

Browse files
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.
1 parent a9f9687 commit 2c003ef

File tree

1 file changed

+31
-57
lines changed

1 file changed

+31
-57
lines changed

Python/marshal.c

Lines changed: 31 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ typedef struct {
8383
int depth;
8484
PyObject *str;
8585
char *ptr;
86-
char *end;
86+
const char *end;
8787
char *buf;
8888
_Py_hashtable_t *hashtable;
8989
int version;
@@ -114,7 +114,7 @@ w_reserve(WFILE *p, Py_ssize_t needed)
114114
}
115115
assert(p->str != NULL);
116116
pos = p->ptr - p->buf;
117-
size = PyBytes_Size(p->str);
117+
size = PyBytes_GET_SIZE(p->str);
118118
if (size > 16*1024*1024)
119119
delta = (size >> 3); /* 12.5% overallocation */
120120
else
@@ -126,7 +126,7 @@ w_reserve(WFILE *p, Py_ssize_t needed)
126126
}
127127
size += delta;
128128
if (_PyBytes_Resize(&p->str, size) != 0) {
129-
p->ptr = p->buf = p->end = NULL;
129+
p->end = p->ptr = p->buf = NULL;
130130
return 0;
131131
}
132132
else {
@@ -138,7 +138,7 @@ w_reserve(WFILE *p, Py_ssize_t needed)
138138
}
139139

140140
static void
141-
w_string(const char *s, Py_ssize_t n, WFILE *p)
141+
w_string(const void *s, Py_ssize_t n, WFILE *p)
142142
{
143143
Py_ssize_t m;
144144
if (!n || p->ptr == NULL)
@@ -194,14 +194,14 @@ w_long(long x, WFILE *p)
194194
#endif
195195

196196
static void
197-
w_pstring(const char *s, Py_ssize_t n, WFILE *p)
197+
w_pstring(const void *s, Py_ssize_t n, WFILE *p)
198198
{
199199
W_SIZE(n, p);
200200
w_string(s, n, p);
201201
}
202202

203203
static void
204-
w_short_pstring(const char *s, Py_ssize_t n, WFILE *p)
204+
w_short_pstring(const void *s, Py_ssize_t n, WFILE *p)
205205
{
206206
w_byte(Py_SAFE_DOWNCAST(n, Py_ssize_t, unsigned char), p);
207207
w_string(s, n, p);
@@ -274,21 +274,18 @@ w_float_bin(double v, WFILE *p)
274274
p->error = WFERR_UNMARSHALLABLE;
275275
return;
276276
}
277-
w_string((const char *)buf, 8, p);
277+
w_string(buf, 8, p);
278278
}
279279

280280
static void
281281
w_float_str(double v, WFILE *p)
282282
{
283-
int n;
284283
char *buf = PyOS_double_to_string(v, 'g', 17, 0, NULL);
285284
if (!buf) {
286285
p->error = WFERR_NOMEMORY;
287286
return;
288287
}
289-
n = (int)strlen(buf);
290-
w_byte(n, p);
291-
w_string(buf, n, p);
288+
w_short_pstring(buf, strlen(buf), p);
292289
PyMem_Free(buf);
293290
}
294291

@@ -378,11 +375,10 @@ w_complex_object(PyObject *v, char flag, WFILE *p)
378375
Py_ssize_t i, n;
379376

380377
if (PyLong_CheckExact(v)) {
381-
long x = PyLong_AsLong(v);
382-
if ((x == -1) && PyErr_Occurred()) {
383-
PyLongObject *ob = (PyLongObject *)v;
384-
PyErr_Clear();
385-
w_PyLong(ob, flag, p);
378+
int overflow;
379+
long x = PyLong_AsLongAndOverflow(v, &overflow);
380+
if (overflow) {
381+
w_PyLong((PyLongObject *)v, flag, p);
386382
}
387383
else {
388384
#if SIZEOF_LONG > 4
@@ -433,15 +429,15 @@ w_complex_object(PyObject *v, char flag, WFILE *p)
433429
W_TYPE(TYPE_SHORT_ASCII_INTERNED, p);
434430
else
435431
W_TYPE(TYPE_SHORT_ASCII, p);
436-
w_short_pstring((char *) PyUnicode_1BYTE_DATA(v),
432+
w_short_pstring(PyUnicode_1BYTE_DATA(v),
437433
PyUnicode_GET_LENGTH(v), p);
438434
}
439435
else {
440436
if (PyUnicode_CHECK_INTERNED(v))
441437
W_TYPE(TYPE_ASCII_INTERNED, p);
442438
else
443439
W_TYPE(TYPE_ASCII, p);
444-
w_pstring((char *) PyUnicode_1BYTE_DATA(v),
440+
w_pstring(PyUnicode_1BYTE_DATA(v),
445441
PyUnicode_GET_LENGTH(v), p);
446442
}
447443
}
@@ -462,7 +458,7 @@ w_complex_object(PyObject *v, char flag, WFILE *p)
462458
}
463459
}
464460
else if (PyTuple_CheckExact(v)) {
465-
n = PyTuple_Size(v);
461+
n = PyTuple_GET_SIZE(v);
466462
if (p->version >= 4 && n < 256) {
467463
W_TYPE(TYPE_SMALL_TUPLE, p);
468464
w_byte((unsigned char)n, p);
@@ -496,34 +492,18 @@ w_complex_object(PyObject *v, char flag, WFILE *p)
496492
w_object((PyObject *)NULL, p);
497493
}
498494
else if (PyAnySet_CheckExact(v)) {
499-
PyObject *value, *it;
495+
PyObject *value;
496+
Py_ssize_t pos = 0;
497+
Py_hash_t hash;
500498

501-
if (PyObject_TypeCheck(v, &PySet_Type))
502-
W_TYPE(TYPE_SET, p);
503-
else
499+
if (PyFrozenSet_CheckExact(v))
504500
W_TYPE(TYPE_FROZENSET, p);
505-
n = PyObject_Size(v);
506-
if (n == -1) {
507-
p->depth--;
508-
p->error = WFERR_UNMARSHALLABLE;
509-
return;
510-
}
501+
else
502+
W_TYPE(TYPE_SET, p);
503+
n = PySet_GET_SIZE(v);
511504
W_SIZE(n, p);
512-
it = PyObject_GetIter(v);
513-
if (it == NULL) {
514-
p->depth--;
515-
p->error = WFERR_UNMARSHALLABLE;
516-
return;
517-
}
518-
while ((value = PyIter_Next(it)) != NULL) {
505+
while (_PySet_NextEntry(v, &pos, &value, &hash)) {
519506
w_object(value, p);
520-
Py_DECREF(value);
521-
}
522-
Py_DECREF(it);
523-
if (PyErr_Occurred()) {
524-
p->depth--;
525-
p->error = WFERR_UNMARSHALLABLE;
526-
return;
527507
}
528508
}
529509
else if (PyCode_Check(v)) {
@@ -638,8 +618,8 @@ typedef struct {
638618
FILE *fp;
639619
int depth;
640620
PyObject *readable; /* Stream-like object being read from */
641-
char *ptr;
642-
char *end;
621+
const char *ptr;
622+
const char *end;
643623
char *buf;
644624
Py_ssize_t buf_size;
645625
PyObject *refs; /* a list */
@@ -652,7 +632,7 @@ r_string(Py_ssize_t n, RFILE *p)
652632

653633
if (p->ptr != NULL) {
654634
/* Fast path for loads() */
655-
char *res = p->ptr;
635+
const char *res = p->ptr;
656636
Py_ssize_t left = p->end - p->ptr;
657637
if (left < n) {
658638
PyErr_SetString(PyExc_EOFError,
@@ -1564,8 +1544,8 @@ PyMarshal_ReadObjectFromString(const char *str, Py_ssize_t len)
15641544
PyObject *result;
15651545
rf.fp = NULL;
15661546
rf.readable = NULL;
1567-
rf.ptr = (char *)str;
1568-
rf.end = (char *)str + len;
1547+
rf.ptr = str;
1548+
rf.end = str + len;
15691549
rf.buf = NULL;
15701550
rf.depth = 0;
15711551
rf.refs = PyList_New(0);
@@ -1587,8 +1567,8 @@ PyMarshal_WriteObjectToString(PyObject *x, int version)
15871567
wf.str = PyBytes_FromStringAndSize((char *)NULL, 50);
15881568
if (wf.str == NULL)
15891569
return NULL;
1590-
wf.ptr = wf.buf = PyBytes_AS_STRING((PyBytesObject *)wf.str);
1591-
wf.end = wf.ptr + PyBytes_Size(wf.str);
1570+
wf.ptr = wf.buf = PyBytes_AS_STRING(wf.str);
1571+
wf.end = wf.ptr + PyBytes_GET_SIZE(wf.str);
15921572
wf.error = WFERR_OK;
15931573
wf.version = version;
15941574
if (w_init_refs(&wf, version)) {
@@ -1598,13 +1578,7 @@ PyMarshal_WriteObjectToString(PyObject *x, int version)
15981578
w_object(x, &wf);
15991579
w_clear_refs(&wf);
16001580
if (wf.str != NULL) {
1601-
char *base = PyBytes_AS_STRING((PyBytesObject *)wf.str);
1602-
if (wf.ptr - base > PY_SSIZE_T_MAX) {
1603-
Py_DECREF(wf.str);
1604-
PyErr_SetString(PyExc_OverflowError,
1605-
"too much marshal data for a bytes object");
1606-
return NULL;
1607-
}
1581+
const char *base = PyBytes_AS_STRING(wf.str);
16081582
if (_PyBytes_Resize(&wf.str, (Py_ssize_t)(wf.ptr - base)) < 0)
16091583
return NULL;
16101584
}

0 commit comments

Comments
 (0)