Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions pypdf/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -832,7 +832,9 @@ def decode_stream_data(stream: StreamObject) -> bytes:
if not isinstance(filters, ArrayObject):
# We have a single filter instance
filters = (filters,)
decode_parms = stream.get(StreamAttributes.DECODE_PARMS, ({},) * len(filters))
# The decoders are typed for a DictionaryObject, so the default has to be
Comment thread
stefan6419846 marked this conversation as resolved.
Resolved
# one too -- a plain {} is not an instance of it.
decode_parms = stream.get(StreamAttributes.DECODE_PARMS, (DictionaryObject(),) * len(filters))
if not isinstance(decode_parms, (list, tuple)):
decode_parms = (decode_parms,)
data: bytes = stream._data
Expand All @@ -841,7 +843,9 @@ def decode_stream_data(stream: StreamObject) -> bytes:
return data
for filter_name, params in zip(filters, decode_parms):
if isinstance(params, NullObject):
params = {}
# The decoders are typed for a DictionaryObject; a plain {} is not
# one, so a null /DecodeParms entry would hand them the wrong type.
params = DictionaryObject()
if filter_name in (FT.ASCII_HEX_DECODE, FTA.AHx):
_deprecate_inline_image_filters(filter_name=filter_name, old_name=FTA.AHx, new_name=FT.ASCII_HEX_DECODE)
data = ASCIIHexDecode.decode(data)
Expand Down
26 changes: 26 additions & 0 deletions tests/test_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -1069,6 +1069,32 @@ def test_deprecate_inline_image_filters():
assert decode_stream_data(stream).startswith(b"II*")


def test_decode_stream_data__default_parms_are_dictionary_objects():
Comment thread
stefan6419846 marked this conversation as resolved.
Resolved
"""
A stream without /DecodeParms still has to hand the decoders a
DictionaryObject; a plain {} is not an instance of one.
"""
captured = []

class RecordingFlate(FlateDecode):
@staticmethod
def decode(data, decode_parms=None, **kwargs) -> bytes: # noqa: ANN003
captured.append(decode_parms)
return FlateDecode.decode(data, decode_parms, **kwargs)

stream = DecodedStreamObject()
stream.set_data(b"hello")
stream[NameObject("/Filter")] = NameObject("/FlateDecode")
encoded = zlib.compress(b"hello")
stream._data = encoded

with mock.patch("pypdf.filters.FlateDecode", RecordingFlate):
Comment thread
stefan6419846 marked this conversation as resolved.
Resolved
assert decode_stream_data(stream) == b"hello"

assert captured, "the filter should have been invoked"
assert isinstance(captured[0], DictionaryObject)


def test_flatedecode__columns_is_zero():
data = b"Hello World!"
parameters = DictionaryObject({
Expand Down
Loading