Bug report
The marshal writer does not raise an exception where the error occurs: it records an error code in WFILE.error and converts it into an exception at the end, in w_set_exception(). If an exception was already raised, it is replaced with a generic one, and not even chained:
>>> t = ([],)
>>> t[0].append(t)
>>> marshal.dumps(t)
ValueError: unmarshallable object
The message raised in w_ref() is cannot marshal recursion tuple objects. Also lost are BufferError for a non-contiguous buffer, the exception raised while marshalling a set item, and MemoryError from PyUnicode_AsEncodedString() or PyLong_Export(). A failure of PyList_Sort(), which sorts set items, is reported as MemoryError, although the sorting fails with TypeError.
Finally, ValueError("unmarshallable object") is used for all unsupported values, including those which are only unsupported in the requested version.
I propose to raise the exception where the error is detected, and keep in WFILE only a flag saying that an exception has been raised. This removes w_set_exception() and all error codes except one, propagates the original exception, and allows more specific messages:
>>> marshal.dumps(marshal)
ValueError: cannot marshal module objects
>>> marshal.dumps(slice(1), 4)
ValueError: marshalling slice objects requires version 5 or higher
Values which are too large get object too large to marshal and int too large to marshal. "unmarshallable object" disappears, so the code which matches it needs to be updated.
Linked PRs
Bug report
The marshal writer does not raise an exception where the error occurs: it records an error code in
WFILE.errorand converts it into an exception at the end, inw_set_exception(). If an exception was already raised, it is replaced with a generic one, and not even chained:The message raised in
w_ref()iscannot marshal recursion tuple objects. Also lost areBufferErrorfor a non-contiguous buffer, the exception raised while marshalling a set item, andMemoryErrorfromPyUnicode_AsEncodedString()orPyLong_Export(). A failure ofPyList_Sort(), which sorts set items, is reported asMemoryError, although the sorting fails withTypeError.Finally,
ValueError("unmarshallable object")is used for all unsupported values, including those which are only unsupported in the requested version.I propose to raise the exception where the error is detected, and keep in
WFILEonly a flag saying that an exception has been raised. This removesw_set_exception()and all error codes except one, propagates the original exception, and allows more specific messages:Values which are too large get
object too large to marshalandint too large to marshal."unmarshallable object"disappears, so the code which matches it needs to be updated.Linked PRs