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

Issues reading cross-reference stream with incorrect /Size #160

Open
divergentdave opened this issue Jan 16, 2023 · 1 comment
Open

Issues reading cross-reference stream with incorrect /Size #160

divergentdave opened this issue Jan 16, 2023 · 1 comment

Comments

@divergentdave
Copy link
Contributor

I used origami to create a password-encrypted PDF to attempt to reproduce #159, and I found that pdf-rs is intolerant of files where the /Size of a cross-reference stream is too small for its contents.

I produced this file with the following script, from the existing pdf-sample.pdf.

#!/usr/bin/env ruby
require 'origami'

[
  ['RC4', 40, false, 'pdf-sample_rc4_rev2.pdf'],
  ['RC4', 64, false, 'pdf-sample_rc4_rev3.pdf'],
  ['AES', 128, false, 'pdf-sample_aes_128.pdf'],
  ['AES', 256, false, 'pdf-sample_aes_256.pdf'],
  ['AES', 256, true, 'pdf-sample_aes_256_hardened.pdf'],
].each do |(cipher, key_size, hardened, file_name)|
  pdf = Origami::PDF.read('../pdf-sample.pdf')
  pdf.encrypt(
    user_passwd: 'userpassword',
    owner_passwd: 'ownerpassword',
    cipher: cipher,
    key_size: key_size,
    hardened: hardened,
  )
  pdf.save(file_name, noindent: true)
end

By inspection, it's clear that the modifications origami made to the trailer's dictionary are inconsistent. The /Index ends with "28 2", yet the /Size is only 27. When this file is loaded, the last subsection of the cross reference stream is successfully parsed, but then XRefTable::add_entries_from() discards both entries in the subsection (with IDs 28 and 29) because they don't fit in the vector. Thus, future indirect references to the objects fail to resolve. (Soon after, opening the file fails with "Entry 28 in xref table unspecified")

Should Backend::read_xref_table_and_trailer() scan the /Index array and update the table's size if necessary?

@s3bk
Copy link
Contributor

s3bk commented Jan 16, 2023

I think there needs to be a fallback that reads the entire file and rebuilds the xref table.
What you proposed can be implemented as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants