Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved performance and security for ContentStream_readInlineImage. #740

Merged
merged 4 commits into from Apr 15, 2022
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
34 changes: 24 additions & 10 deletions PyPDF2/pdf.py
Expand Up @@ -2817,11 +2817,27 @@ def _readInlineImage(self, stream):
# left at beginning of ID
tmp = stream.read(3)
assert tmp[:2] == b_("ID")
data = b_("")
data = BytesIO()
# Read the inline image, while checking for EI (End Image) operator.
while True:
# Read the inline image, while checking for EI (End Image) operator.
tok = stream.read(1)
if tok == b_("E"):
# Read 8 kB at a time and check if the chunk contains the E operator.
buf = stream.read(8192)

MartinThoma marked this conversation as resolved.
Show resolved Hide resolved
# We have reached the end of the stream, but haven't found the EI operator.
if not buf:
raise utils.PdfReadError("Unexpected end of stream")

MartinThoma marked this conversation as resolved.
Show resolved Hide resolved
loc = buf.find(b_("E"))

if loc == -1:
data.write(buf)
else:
# Write out everything before the E.
data.write(buf[0:loc])

# Seek back in the stream to read the E next.
stream.seek(loc - len(buf), 1)
tok = stream.read(1)
# Check for End Image
tok2 = stream.read(1)
if tok2 == b_("I"):
Expand All @@ -2838,14 +2854,12 @@ def _readInlineImage(self, stream):
stream.seek(-1, 1)
break
else:
stream.seek(-1,1)
data += info
stream.seek(-1, 1)
data.write(info)
else:
stream.seek(-1, 1)
data += tok
else:
data += tok
return {"settings": settings, "data": data}
data.write(tok)
return {"settings": settings, "data": data.getvalue()}

def _getData(self):
newdata = BytesIO()
Expand Down