68 lines
2.7 KiB
C++
68 lines
2.7 KiB
C++
// Resource limits for hardening against malicious / malformed PDFs.
|
||
//
|
||
// These guard the allocation-sizing arithmetic in the load and render paths
|
||
// against integer overflow and pathological out-of-memory inputs (a 2-billion-pt
|
||
// page, a million-page document, a multi-gigabyte raster). The ceilings are set
|
||
// far above anything a legitimate document needs, so enforcing them never
|
||
// rejects real files — they exist purely to turn "crash / OOM" into a clean,
|
||
// recoverable error, which is exactly what a fuzzer needs to make progress.
|
||
//
|
||
// Header-only and dependency-free so the fuzz harness and the engine share one
|
||
// source of truth.
|
||
|
||
#ifndef PDFENGINE_HARDENED_LIMITS_H
|
||
#define PDFENGINE_HARDENED_LIMITS_H
|
||
|
||
#include <cstdint>
|
||
|
||
namespace pdfengine::limits {
|
||
|
||
// Largest input document we will even attempt to parse (1 GiB).
|
||
inline constexpr std::uint64_t kMaxDocumentBytes = 1ull << 30;
|
||
|
||
// PDF hard-caps a page at 14,400 user units (200 in) per side; allow a very
|
||
// generous multiple of that to tolerate odd-but-real documents.
|
||
inline constexpr double kMaxPageDimensionPt = 200'000.0; // ~2,777 inches
|
||
|
||
// No legitimate document has this many pages; stops runaway iteration.
|
||
inline constexpr int kMaxPageCount = 100'000;
|
||
|
||
// MAX_OBJECTS: ceiling on the number of content objects on a single page. Guards
|
||
// against content-stream "object bombs" that would explode parsing/rendering
|
||
// time and memory. No real page comes near this.
|
||
inline constexpr int kMaxObjects = 5'000'000;
|
||
|
||
// Cap a single rasterised page at ~256 megapixels (≈1 GiB at 4 bytes/px). At
|
||
// 96 dpi that is roughly a 16k × 16k page — well beyond any real render.
|
||
inline constexpr std::int64_t kMaxRasterPixels = 256ll * 1024 * 1024;
|
||
|
||
// True if a raw page size (in points) is sane to render.
|
||
inline constexpr bool pageDimensionsOk(double widthPt, double heightPt) noexcept {
|
||
return widthPt > 0.0 && heightPt > 0.0 && widthPt <= kMaxPageDimensionPt &&
|
||
heightPt <= kMaxPageDimensionPt;
|
||
}
|
||
|
||
// True if a target raster (in pixels) fits the pixel budget without overflowing
|
||
// the width*height*4 byte computation.
|
||
inline constexpr bool rasterSizeOk(std::int64_t widthPx, std::int64_t heightPx) noexcept {
|
||
if (widthPx <= 0 || heightPx <= 0) return false;
|
||
if (widthPx > kMaxRasterPixels || heightPx > kMaxRasterPixels) return false;
|
||
return widthPx * heightPx <= kMaxRasterPixels;
|
||
}
|
||
|
||
inline constexpr bool documentSizeOk(std::uint64_t bytes) noexcept {
|
||
return bytes > 0 && bytes <= kMaxDocumentBytes;
|
||
}
|
||
|
||
inline constexpr bool pageCountOk(int pages) noexcept {
|
||
return pages >= 0 && pages <= kMaxPageCount;
|
||
}
|
||
|
||
inline constexpr bool objectCountOk(int objects) noexcept {
|
||
return objects >= 0 && objects <= kMaxObjects;
|
||
}
|
||
|
||
} // namespace pdfengine::limits
|
||
|
||
#endif // PDFENGINE_HARDENED_LIMITS_H
|