@@ -106,6 +106,7 @@ module marshal
106106#define WFERR_NESTEDTOODEEP 2
107107#define WFERR_NOMEMORY 3
108108#define WFERR_CODE_NOT_ALLOWED 4
109+ #define WFERR_EXCEPTION_SET 5 /* An exception has already been raised. */
109110
110111typedef struct {
111112 FILE * fp ;
@@ -125,11 +126,32 @@ typedef struct {
125126 *(p)->ptr++ = (c); \
126127 } while(0)
127128
129+ /* Report a failure of the underlying file. An earlier error is not
130+ overwritten. */
131+ static void
132+ w_file_error (WFILE * p )
133+ {
134+ int saved_errno = errno ;
135+ if (p -> error != WFERR_OK ) {
136+ return ;
137+ }
138+ p -> error = WFERR_EXCEPTION_SET ;
139+ if (PyErr_CheckSignals ()) {
140+ /* The signal handler has raised an exception. */
141+ return ;
142+ }
143+ errno = saved_errno ;
144+ PyErr_SetFromErrno (PyExc_OSError );
145+ }
146+
128147static void
129148w_flush (WFILE * p )
130149{
131150 assert (p -> fp != NULL );
132- fwrite (p -> buf , 1 , p -> ptr - p -> buf , p -> fp );
151+ size_t n = (size_t )(p -> ptr - p -> buf );
152+ if (fwrite (p -> buf , 1 , n , p -> fp ) != n ) {
153+ w_file_error (p );
154+ }
133155 p -> ptr = p -> buf ;
134156}
135157
@@ -182,7 +204,9 @@ w_string(const void *s, Py_ssize_t n, WFILE *p)
182204 }
183205 else {
184206 w_flush (p );
185- fwrite (s , 1 , n , p -> fp );
207+ if (fwrite (s , 1 , n , p -> fp ) != (size_t )n ) {
208+ w_file_error (p );
209+ }
186210 }
187211 }
188212 else {
@@ -782,11 +806,36 @@ w_clear_refs(WFILE *wf)
782806 }
783807}
784808
809+ /* Set the exception indicator according to the recorded error. */
810+ static void
811+ w_set_exception (WFILE * p )
812+ {
813+ assert (p -> error != WFERR_OK );
814+ switch (p -> error ) {
815+ case WFERR_NOMEMORY :
816+ PyErr_NoMemory ();
817+ break ;
818+ case WFERR_NESTEDTOODEEP :
819+ PyErr_SetString (PyExc_ValueError ,
820+ "object too deeply nested to marshal" );
821+ break ;
822+ case WFERR_CODE_NOT_ALLOWED :
823+ PyErr_SetString (PyExc_ValueError ,
824+ "marshalling code objects is disallowed" );
825+ break ;
826+ case WFERR_EXCEPTION_SET :
827+ /* An exception has already been raised. */
828+ assert (PyErr_Occurred ());
829+ break ;
830+ default :
831+ case WFERR_UNMARSHALLABLE :
832+ PyErr_SetString (PyExc_ValueError ,
833+ "unmarshallable object" );
834+ break ;
835+ }
836+ }
837+
785838/* version currently has no effect for writing ints. */
786- /* Note that while the documentation states that this function
787- * can error, currently it never does. Setting an exception in
788- * this function should be regarded as an API-breaking change.
789- */
790839void
791840PyMarshal_WriteLongToFile (long x , FILE * fp , int version )
792841{
@@ -800,6 +849,9 @@ PyMarshal_WriteLongToFile(long x, FILE *fp, int version)
800849 wf .version = version ;
801850 w_long (x , & wf );
802851 w_flush (& wf );
852+ if (wf .error != WFERR_OK ) {
853+ w_set_exception (& wf );
854+ }
803855}
804856
805857void
@@ -823,6 +875,9 @@ PyMarshal_WriteObjectToFile(PyObject *x, FILE *fp, int version)
823875 w_object (x , & wf );
824876 w_clear_refs (& wf );
825877 w_flush (& wf );
878+ if (wf .error != WFERR_OK ) {
879+ w_set_exception (& wf );
880+ }
826881}
827882
828883typedef struct {
@@ -875,6 +930,14 @@ r_string(Py_ssize_t n, RFILE *p)
875930 if (!p -> readable ) {
876931 assert (p -> fp != NULL );
877932 read = fread (p -> buf , 1 , n , p -> fp );
933+ if (read != n ) {
934+ assert (read < n );
935+ int saved_errno = errno ;
936+ if (!PyErr_CheckSignals () && ferror (p -> fp )) {
937+ errno = saved_errno ;
938+ PyErr_SetFromErrno (PyExc_OSError );
939+ }
940+ }
878941 }
879942 else {
880943 PyObject * res , * mview ;
@@ -887,21 +950,26 @@ r_string(Py_ssize_t n, RFILE *p)
887950 return NULL ;
888951
889952 res = _PyObject_CallMethod (p -> readable , & _Py_ID (readinto ), "N" , mview );
890- if (res != NULL ) {
891- read = PyNumber_AsSsize_t (res , PyExc_ValueError );
892- Py_DECREF (res );
953+ if (res == NULL ) {
954+ return NULL ;
955+ }
956+ read = PyNumber_AsSsize_t (res , PyExc_ValueError );
957+ Py_DECREF (res );
958+ if (read == -1 && PyErr_Occurred ()) {
959+ return NULL ;
960+ }
961+ if (read > n ) {
962+ PyErr_Format (PyExc_ValueError ,
963+ "read() returned too much data: "
964+ "%zd bytes requested, %zd returned" ,
965+ n , read );
966+ return NULL ;
893967 }
894968 }
895969 if (read != n ) {
896970 if (!PyErr_Occurred ()) {
897- if (read > n )
898- PyErr_Format (PyExc_ValueError ,
899- "read() returned too much data: "
900- "%zd bytes requested, %zd returned" ,
901- n , read );
902- else
903- PyErr_SetString (PyExc_EOFError ,
904- "EOF read where not expected" );
971+ PyErr_SetString (PyExc_EOFError ,
972+ "EOF read where not expected" );
905973 }
906974 return NULL ;
907975 }
@@ -922,6 +990,15 @@ r_byte(RFILE *p)
922990 if (c != EOF ) {
923991 return c ;
924992 }
993+ int saved_errno = errno ;
994+ if (PyErr_CheckSignals ()) {
995+ return EOF ;
996+ }
997+ if (ferror (p -> fp )) {
998+ errno = saved_errno ;
999+ PyErr_SetFromErrno (PyExc_OSError );
1000+ return EOF ;
1001+ }
9251002 }
9261003 else {
9271004 const char * ptr = r_string (1 , p );
@@ -1850,8 +1927,18 @@ PyMarshal_ReadLastObjectFromFile(FILE *fp)
18501927 if (filesize > 0 && filesize <= REASONABLE_FILE_LIMIT ) {
18511928 char * pBuf = (char * )PyMem_Malloc (filesize );
18521929 if (pBuf != NULL ) {
1930+ PyObject * v = NULL ;
18531931 size_t n = fread (pBuf , 1 , (size_t )filesize , fp );
1854- PyObject * v = PyMarshal_ReadObjectFromString (pBuf , n );
1932+ int saved_errno = errno ;
1933+ if (!PyErr_CheckSignals ()) {
1934+ if (ferror (fp )) {
1935+ errno = saved_errno ;
1936+ PyErr_SetFromErrno (PyExc_OSError );
1937+ }
1938+ else {
1939+ v = PyMarshal_ReadObjectFromString (pBuf , n );
1940+ }
1941+ }
18551942 PyMem_Free (pBuf );
18561943 return v ;
18571944 }
@@ -1938,24 +2025,7 @@ _PyMarshal_WriteObjectToString(PyObject *x, int version, int allow_code)
19382025 }
19392026 if (wf .error != WFERR_OK ) {
19402027 Py_XDECREF (wf .str );
1941- switch (wf .error ) {
1942- case WFERR_NOMEMORY :
1943- PyErr_NoMemory ();
1944- break ;
1945- case WFERR_NESTEDTOODEEP :
1946- PyErr_SetString (PyExc_ValueError ,
1947- "object too deeply nested to marshal" );
1948- break ;
1949- case WFERR_CODE_NOT_ALLOWED :
1950- PyErr_SetString (PyExc_ValueError ,
1951- "marshalling code objects is disallowed" );
1952- break ;
1953- default :
1954- case WFERR_UNMARSHALLABLE :
1955- PyErr_SetString (PyExc_ValueError ,
1956- "unmarshallable object" );
1957- break ;
1958- }
2028+ w_set_exception (& wf );
19592029 return NULL ;
19602030 }
19612031 return wf .str ;
0 commit comments