Skip to content

Commit

Permalink
Change ByteRange placeholder to allow bigger input
Browse files Browse the repository at this point in the history
Fixes #336
  • Loading branch information
MatthiasValvekens committed Nov 2, 2023
1 parent 99ab33b commit f4ac1d5
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 8 deletions.
29 changes: 21 additions & 8 deletions pyhanko/sign/signers/pdf_byterange.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
]


BYTE_RANGE_ARR_PLACE_HOLDER_LENGTH = 60


class SigByteRangeObject(generic.PdfObject):
"""
Internal class to handle the ``/ByteRange`` arrays themselves.
Expand Down Expand Up @@ -62,21 +65,31 @@ def fill_offsets(self, stream, sig_start, sig_end, eof):
# so we can just write over it

stream.seek(self._range_object_offset)
self._filled = True
self.write_to_stream(stream, None)

stream.seek(old_seek)
self._filled = True

def write_to_stream(self, stream, handler=None, container_ref=None):
if self._range_object_offset is None:
self._range_object_offset = stream.tell()
string_repr = "[ %08d %08d %08d %08d ]" % (
0,
self.first_region_len,
self.second_region_offset,
self.second_region_len,
)
stream.write(string_repr.encode('ascii'))
if self._filled:
string_repr = "[%d %d %d %d]" % (
0,
self.first_region_len,
self.second_region_offset,
self.second_region_len,
)
buffer_remaining = (
BYTE_RANGE_ARR_PLACE_HOLDER_LENGTH + 2 - len(string_repr)
)
assert buffer_remaining >= 0
stream.write(string_repr.encode('ascii'))
stream.write(b" " * buffer_remaining)
else:
stream.write(b"[")
stream.write(b" " * BYTE_RANGE_ARR_PLACE_HOLDER_LENGTH)
stream.write(b"]")


class DERPlaceholder(generic.PdfObject):
Expand Down
19 changes: 19 additions & 0 deletions pyhanko_tests/test_signing.py
Original file line number Diff line number Diff line change
Expand Up @@ -1628,3 +1628,22 @@ def test_sign_with_build_props_versioned_app_name():
build_prop_dict = s.sig_object['/Prop_Build']['/App']
assert build_prop_dict['/Name'] == '/Test Application'
assert build_prop_dict['/REx'] == '1.2.3'


def test_sign_120mb_file():
# put this in a function to avoid putting multiple copies
# of a huge buffer in locals
def _gen_signed():
w = IncrementalPdfFileWriter(BytesIO(MINIMAL))
w.root['/YugeObject'] = w.add_object(
generic.StreamObject(stream_data=bytes(120 * 1024 * 1024))
)
w.update_root()

meta = signers.PdfSignatureMetadata(field_name='Sig1')
return signers.sign_pdf(w, meta, signer=SELF_SIGN)

r = PdfFileReader(_gen_signed())
emb = r.embedded_signatures[0]
assert emb.field_name == 'Sig1'
val_untrusted(emb)

0 comments on commit f4ac1d5

Please sign in to comment.