Files
pdfcraft/vendor/hayro-syntax
snipeTRandBrandon Thomas 9c2d9c02bf fix(crypt): R2–R4 passwords with non-ASCII characters open (PDFDocEncoding) (#905)
Revisions 2–4 of the standard security handler take the password in
PDFDocEncoding (ISO 32000-2 §7.6.4.3.2, Algorithm 2). PdfCraft authenticates
an encrypted file twice, and neither did that:
- pdfcraft-crypt took Latin-1 and dropped every other character, so "ı"
  (0x9A) and "€" (0xA0) vanished and "ılık€" became "lk";
- the renderer (vendored hayro-syntax, "TODO: Convert to PDFDocEncoding")
  used the UTF-8 bytes, so any non-ASCII password failed, even "Çok güzel",
  which Latin-1 and PDFDocEncoding write alike;
- the engine handed the renderer an owner-recovered user password as Latin-1
  characters, which the renderer then read as UTF-8 again.
Files that qpdf or Acrobat protected with such passwords could not be
opened with the right password.

- pdfcraft-crypt encodes R2–R4 passwords in PDFDocEncoding and, for a
  password with characters PDFDocEncoding lacks (ğ, ş, İ), also tries its
  UTF-8 bytes, which qpdf writes for those. The PDFDocEncoding table moves
  here from pdfcraft-cos (which depends on this crate) and cos uses it.
- hayro-syntax (vendored patch 14) tries an R2–R4 password as given, then
  in PDFDocEncoding.
- The engine passes a recovered user password to the renderer as UTF-8 when
  its bytes are UTF-8 and as PDFDocEncoding otherwise, so the renderer gets
  exactly those bytes back.

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-10 17:10:39 -04:00
..

hayro-syntax

Crates.io Documentation

A low-level library for reading PDF files.

This crate implements the Syntax chapter of the PDF reference, and therefore serves as a very good basis for building various abstractions on top of it, without having to reimplement the PDF parsing logic.

This crate does not provide more high-level functionality, such as parsing fonts or color spaces. Such functionality is out-of-scope for hayro-syntax, since this crate is supposed to be as light-weight and application-agnostic as possible.

Functionality-wise, this crate is therefore close to feature-complete. The main missing feature is support for password-protected documents. In addition to that, more low-level APIs might be added in the future.

The crate is no_std compatible but requires an allocator to be available.

Example

This short example shows you how to load a PDF file and iterate over the content streams of all pages.

use hayro_syntax::Pdf;
use std::path::PathBuf;

// First load the data that constitutes the PDF file.
let data = std::fs::read(
    PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../hayro-tests/pdfs/custom/text_with_rise.pdf"),
)
.unwrap();

// Then create a new PDF file from it.
//
// Here we are just unwrapping in case reading the file failed, but you
// might instead want to apply proper error handling.
let pdf = Pdf::new(data).unwrap();

// First access all pages, and then iterate over the operators of each page's
// content stream and print them.
let pages = pdf.pages();
for page in pages.iter() {
    let mut ops = page.typed_operations();

    while let Some(op) = ops.next() {
        println!("{op:?}");
    }
}

Safety

When the unsafe feature is disabled, there is only use of unsafe in hayro-syntax. We also unconditionally use the smallvec crate which uses unsafe internally, but that's it.

For better performance, it is strongly recommended to enable the unsafe feature, which does result in slightly more unsafe code being, but does give better performance:

  • We will use the flate2 crate for decoding flate streams.
  • SIMD will be enabled to accelerate decoding of images.
  • memchr will be used to accelerate some of the fallback parsing code.

Features

The supported features include:

  • Parsing xref tables in all its possible formats, including xref streams.
  • Best-effort attempt at repairing PDF files with broken xref tables.
  • Parsing of all objects types (also in object streams).
  • Parsing and decoding PDF streams.
  • Iterating over pages as well as their content streams in a typed or untyped fashion.
  • The crate is very lightweight, especially in comparison to other PDF crates.

Limitations

  • There are still a few features missing, for example, support for password-protected PDFs. In addition to that, many properties (like page annotations) are currently not exposed.
  • This crate is for read-only processing, you cannot directly use it to manipulate PDF files. If you need to do that, there are other crates in the Rust ecosystem that are suitable for this.

License

Licensed under either of

at your option.