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

Skip to content

Commit d9b9ac8

Browse files
committed
It's unclear whether PyMarshal_XXX() are part of the public or private API.
They're named as if public, so I did a Bad Thing by changing PyMarshal_ReadObjectFromFile() to suck up the remainder of the file in one gulp: anyone who counted on that leaving the file pointer merely at the end of the next object would be screwed. So restored PyMarshal_ReadObjectFromFile() to its earlier state, renamed the new greedy code to PyMarshal_ReadLastObjectFromFile(), and changed Python internals to call the latter instead.
1 parent 09ac1fd commit d9b9ac8

4 files changed

Lines changed: 52 additions & 35 deletions

File tree

Include/marshal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ DL_IMPORT(PyObject *) PyMarshal_WriteObjectToString(PyObject *);
1515
DL_IMPORT(long) PyMarshal_ReadLongFromFile(FILE *);
1616
DL_IMPORT(int) PyMarshal_ReadShortFromFile(FILE *);
1717
DL_IMPORT(PyObject *) PyMarshal_ReadObjectFromFile(FILE *);
18+
DL_IMPORT(PyObject *) PyMarshal_ReadLastObjectFromFile(FILE *);
1819
DL_IMPORT(PyObject *) PyMarshal_ReadObjectFromString(char *, int);
1920

2021
#ifdef __cplusplus

Python/import.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,7 @@ read_compiled_module(char *cpathname, FILE *fp)
555555
{
556556
PyObject *co;
557557

558-
co = PyMarshal_ReadObjectFromFile(fp);
558+
co = PyMarshal_ReadLastObjectFromFile(fp);
559559
/* Ugly: rd_object() may return NULL with or without error */
560560
if (co == NULL || !PyCode_Check(co)) {
561561
if (!PyErr_Occurred())

Python/marshal.c

Lines changed: 49 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,10 @@ w_object(PyObject *v, WFILE *p)
110110
PyBufferProcs *pb;
111111

112112
p->depth++;
113-
113+
114114
if (p->depth > MAX_MARSHAL_STACK_DEPTH) {
115115
p->error = 2;
116-
}
116+
}
117117
else if (v == NULL) {
118118
w_byte(TYPE_NULL, p);
119119
}
@@ -363,31 +363,31 @@ r_object(RFILE *p)
363363
PyObject *v, *v2;
364364
long i, n;
365365
int type = r_byte(p);
366-
366+
367367
switch (type) {
368-
368+
369369
case EOF:
370370
PyErr_SetString(PyExc_EOFError,
371371
"EOF read where object expected");
372372
return NULL;
373-
373+
374374
case TYPE_NULL:
375375
return NULL;
376-
376+
377377
case TYPE_NONE:
378378
Py_INCREF(Py_None);
379379
return Py_None;
380-
380+
381381
case TYPE_ELLIPSIS:
382382
Py_INCREF(Py_Ellipsis);
383383
return Py_Ellipsis;
384-
384+
385385
case TYPE_INT:
386386
return PyInt_FromLong(r_long(p));
387-
387+
388388
case TYPE_INT64:
389389
return PyInt_FromLong(r_long64(p));
390-
390+
391391
case TYPE_LONG:
392392
{
393393
int size;
@@ -402,7 +402,7 @@ r_object(RFILE *p)
402402
ob->ob_digit[i] = r_short(p);
403403
return (PyObject *)ob;
404404
}
405-
405+
406406
case TYPE_FLOAT:
407407
{
408408
char buf[256];
@@ -419,7 +419,7 @@ r_object(RFILE *p)
419419
PyFPE_END_PROTECT(dx)
420420
return PyFloat_FromDouble(dx);
421421
}
422-
422+
423423
#ifndef WITHOUT_COMPLEX
424424
case TYPE_COMPLEX:
425425
{
@@ -448,7 +448,7 @@ r_object(RFILE *p)
448448
return PyComplex_FromCComplex(c);
449449
}
450450
#endif
451-
451+
452452
case TYPE_STRING:
453453
n = r_long(p);
454454
if (n < 0) {
@@ -465,7 +465,7 @@ r_object(RFILE *p)
465465
}
466466
}
467467
return v;
468-
468+
469469
case TYPE_UNICODE:
470470
{
471471
char *buffer;
@@ -488,7 +488,7 @@ r_object(RFILE *p)
488488
PyMem_DEL(buffer);
489489
return v;
490490
}
491-
491+
492492
case TYPE_TUPLE:
493493
n = r_long(p);
494494
if (n < 0) {
@@ -508,7 +508,7 @@ r_object(RFILE *p)
508508
PyTuple_SET_ITEM(v, (int)i, v2);
509509
}
510510
return v;
511-
511+
512512
case TYPE_LIST:
513513
n = r_long(p);
514514
if (n < 0) {
@@ -528,7 +528,7 @@ r_object(RFILE *p)
528528
PyList_SetItem(v, (int)i, v2);
529529
}
530530
return v;
531-
531+
532532
case TYPE_DICT:
533533
v = PyDict_New();
534534
if (v == NULL)
@@ -545,7 +545,7 @@ r_object(RFILE *p)
545545
Py_XDECREF(val);
546546
}
547547
return v;
548-
548+
549549
case TYPE_CODE:
550550
{
551551
int argcount = r_short(p);
@@ -562,7 +562,7 @@ r_object(RFILE *p)
562562
PyObject *name = NULL;
563563
int firstlineno = 0;
564564
PyObject *lnotab = NULL;
565-
565+
566566
code = r_object(p);
567567
if (code) consts = r_object(p);
568568
if (consts) names = r_object(p);
@@ -575,13 +575,13 @@ r_object(RFILE *p)
575575
firstlineno = r_short(p);
576576
lnotab = r_object(p);
577577
}
578-
578+
579579
if (!PyErr_Occurred()) {
580580
v = (PyObject *) PyCode_New(
581-
argcount, nlocals, stacksize, flags,
581+
argcount, nlocals, stacksize, flags,
582582
code, consts, names, varnames,
583-
freevars, cellvars, filename, name,
584-
firstlineno, lnotab);
583+
freevars, cellvars, filename, name,
584+
firstlineno, lnotab);
585585
}
586586
else
587587
v = NULL;
@@ -597,13 +597,13 @@ r_object(RFILE *p)
597597

598598
}
599599
return v;
600-
600+
601601
default:
602602
/* Bogus data got written, which isn't ideal.
603603
This will let you keep working and recover. */
604604
PyErr_SetString(PyExc_ValueError, "bad marshal data");
605605
return NULL;
606-
606+
607607
}
608608
}
609609

@@ -627,20 +627,21 @@ getfilesize(FILE *fp)
627627
return st.st_size;
628628
}
629629
#endif
630-
630+
631631
/* If we can get the size of the file up-front, and it's reasonably small,
632632
* read it in one gulp and delegate to ...FromString() instead. Much quicker
633633
* than reading a byte at a time from file; speeds .pyc imports.
634+
* CAUTION: since this may read the entire remainder of the file, don't
635+
* call it unless you know you're done with the file.
634636
*/
635637
PyObject *
636-
PyMarshal_ReadObjectFromFile(FILE *fp)
638+
PyMarshal_ReadLastObjectFromFile(FILE *fp)
637639
{
638640
/* 75% of 2.1's .pyc files can exploit SMALL_FILE_LIMIT.
639641
* REASONABLE_FILE_LIMIT is by defn something big enough for Tkinter.pyc.
640642
*/
641643
#define SMALL_FILE_LIMIT (1L << 14)
642644
#define REASONABLE_FILE_LIMIT (1L << 18)
643-
RFILE rf;
644645
#ifdef HAVE_FSTAT
645646
off_t filesize;
646647
#endif
@@ -665,15 +666,30 @@ PyMarshal_ReadObjectFromFile(FILE *fp)
665666
PyMem_FREE(pBuf);
666667
return v;
667668
}
668-
669+
669670
}
670671
#endif
671-
rf.fp = fp;
672-
return r_object(&rf);
672+
/* We don't have fstat, or we do but the file is larger than
673+
* REASONABLE_FILE_LIMIT or malloc failed -- read a byte at a time.
674+
*/
675+
return PyMarshal_ReadObjectFromFile(fp);
676+
673677
#undef SMALL_FILE_LIMIT
674678
#undef REASONABLE_FILE_LIMIT
675679
}
676680

681+
PyObject *
682+
PyMarshal_ReadObjectFromFile(FILE *fp)
683+
{
684+
RFILE rf;
685+
if (PyErr_Occurred()) {
686+
fprintf(stderr, "XXX rd_object called with exception set\n");
687+
return NULL;
688+
}
689+
rf.fp = fp;
690+
return r_object(&rf);
691+
}
692+
677693
PyObject *
678694
PyMarshal_ReadObjectFromString(char *str, int len)
679695
{
@@ -708,7 +724,7 @@ PyMarshal_WriteObjectToString(PyObject *x) /* wrs_object() */
708724
PyString_AS_STRING((PyStringObject *)wf.str)));
709725
if (wf.error) {
710726
Py_XDECREF(wf.str);
711-
PyErr_SetString(PyExc_ValueError,
727+
PyErr_SetString(PyExc_ValueError,
712728
(wf.error==1)?"unmarshallable object"
713729
:"object too deeply nested to marshal");
714730
return NULL;
@@ -738,7 +754,7 @@ marshal_dump(PyObject *self, PyObject *args)
738754
wf.depth = 0;
739755
w_object(x, &wf);
740756
if (wf.error) {
741-
PyErr_SetString(PyExc_ValueError,
757+
PyErr_SetString(PyExc_ValueError,
742758
(wf.error==1)?"unmarshallable object"
743759
:"object too deeply nested to marshal");
744760
return NULL;

Python/pythonrun.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -936,7 +936,7 @@ run_pyc_file(FILE *fp, char *filename, PyObject *globals, PyObject *locals)
936936
return NULL;
937937
}
938938
(void) PyMarshal_ReadLongFromFile(fp);
939-
v = PyMarshal_ReadObjectFromFile(fp);
939+
v = PyMarshal_ReadLastObjectFromFile(fp);
940940
fclose(fp);
941941
if (v == NULL || !PyCode_Check(v)) {
942942
Py_XDECREF(v);

0 commit comments

Comments
 (0)