Skip to content

Commit 80c3939

Browse files
ROB: Soft failure for flate encode image mode 1 with wrong LUT size (#2900)
Closes #2889.
1 parent 7044454 commit 80c3939

File tree

2 files changed

+52
-44
lines changed

2 files changed

+52
-44
lines changed

pypdf/_xobj_image_helpers.py

+11-7
Original file line numberDiff line numberDiff line change
@@ -209,14 +209,18 @@ def _handle_flate(
209209
if img.mode == "1":
210210
# Two values ("high" and "low").
211211
expected_count = 2 * nb
212-
if len(lookup) != expected_count:
213-
if len(lookup) < expected_count:
214-
raise PdfReadError(
215-
f"Not enough lookup values: Expected {expected_count}, got {len(lookup)}."
212+
actual_count = len(lookup)
213+
if actual_count != expected_count:
214+
if actual_count < expected_count:
215+
logger_warning(
216+
f"Not enough lookup values: Expected {expected_count}, got {actual_count}.",
217+
__name__
216218
)
217-
if not check_if_whitespace_only(lookup[expected_count:]):
218-
raise PdfReadError(
219-
f"Too many lookup values: Expected {expected_count}, got {len(lookup)}."
219+
lookup += bytes([0] * (expected_count - actual_count))
220+
elif not check_if_whitespace_only(lookup[expected_count:]):
221+
logger_warning(
222+
f"Too many lookup values: Expected {expected_count}, got {actual_count}.",
223+
__name__
220224
)
221225
lookup = lookup[:expected_count]
222226
colors_arr = [lookup[:nb], lookup[nb:]]

tests/test_xobject_image_helpers.py

+41-37
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def test_get_imagemode_recursion_depth():
2929
reader.pages[0].images[0]
3030

3131

32-
def test_handle_flate__image_mode_1():
32+
def test_handle_flate__image_mode_1(caplog):
3333
data = b"\x00\xe0\x00"
3434
lookup = DecodedStreamObject()
3535
expected_data = [
@@ -57,6 +57,7 @@ def test_handle_flate__image_mode_1():
5757
obj_as_text="dummy",
5858
)
5959
assert expected_data == list(result[0].getdata())
60+
assert not caplog.text
6061

6162
# Trailing whitespace.
6263
lookup.set_data(b"\x42\x42\x42\x00\x13\x37 \x0a")
@@ -71,48 +72,51 @@ def test_handle_flate__image_mode_1():
7172
obj_as_text="dummy",
7273
)
7374
assert expected_data == list(result[0].getdata())
75+
assert not caplog.text
7476

7577
# Trailing non-whitespace character.
7678
lookup.set_data(b"\x42\x42\x42\x00\x13\x37\x12")
77-
with pytest.raises(
78-
PdfReadError, match=r"^Too many lookup values: Expected 6, got 7\.$"
79-
):
80-
_handle_flate(
81-
size=(3, 3),
82-
data=data,
83-
mode="1",
84-
color_space=ArrayObject(
85-
[
86-
NameObject("/Indexed"),
87-
NameObject("/DeviceRGB"),
88-
NumberObject(1),
89-
lookup,
90-
]
91-
),
92-
colors=2,
93-
obj_as_text="dummy",
94-
)
79+
result = _handle_flate(
80+
size=(3, 3),
81+
data=data,
82+
mode="1",
83+
color_space=ArrayObject(
84+
[
85+
NameObject("/Indexed"),
86+
NameObject("/DeviceRGB"),
87+
NumberObject(1),
88+
lookup,
89+
]
90+
),
91+
colors=2,
92+
obj_as_text="dummy",
93+
)
94+
assert expected_data == list(result[0].getdata())
95+
assert "Too many lookup values: Expected 6, got 7." in caplog.text
9596

9697
# Not enough lookup data.
98+
# `\xe0` of the original input (the middle part) does not use `0x37 = 55` for the lookup
99+
# here, but received a custom padding of `0`.
97100
lookup.set_data(b"\x42\x42\x42\x00\x13")
98-
with pytest.raises(
99-
PdfReadError, match=r"^Not enough lookup values: Expected 6, got 5\.$"
100-
):
101-
_handle_flate(
102-
size=(3, 3),
103-
data=data,
104-
mode="1",
105-
color_space=ArrayObject(
106-
[
107-
NameObject("/Indexed"),
108-
NameObject("/DeviceRGB"),
109-
NumberObject(1),
110-
lookup,
111-
]
112-
),
113-
colors=2,
114-
obj_as_text="dummy",
115-
)
101+
caplog.clear()
102+
expected_short_data = [entry if entry[0] == 66 else (0, 19, 0) for entry in expected_data]
103+
result = _handle_flate(
104+
size=(3, 3),
105+
data=data,
106+
mode="1",
107+
color_space=ArrayObject(
108+
[
109+
NameObject("/Indexed"),
110+
NameObject("/DeviceRGB"),
111+
NumberObject(1),
112+
lookup,
113+
]
114+
),
115+
colors=2,
116+
obj_as_text="dummy",
117+
)
118+
assert expected_short_data == list(result[0].getdata())
119+
assert "Not enough lookup values: Expected 6, got 5." in caplog.text
116120

117121

118122
def test_extended_image_frombytes_zero_data():

0 commit comments

Comments
 (0)