Валидация графа сегментов JBIG2
HotPDF проверяет внедрённые streams изображений JBIG2 и JBIG2Globals до того, как они попадут в native- или внешний декодер
Валидатор выполняет один ограниченный проход по сегментам, за которым следует итеративный обход графа зависимостей, используя индексированный поиск по номерам сегментов вместо повторных сканирований
Валидация перед пользовательской обработкой
Options := DefaultJBIG2SegmentGraphValidationOptions;
Options.MaxSegments := 32768;
Options.MaxTotalReferences := 131072;
Options.MaxReferenceDepth := 512;
Options.MaxSymbols := 500000;
if not HPDFValidateJBIG2SegmentGraph(ImageData, GlobalData,
Options, Info) then
raise Exception.Create(string(
HPDFJBIG2SegmentGraphValidationStatusName(Info.Status)));
TJBIG2SegmentGraphValidationInfo сообщает число сегментов и рёбер, объявленные новые symbol, максимальную глубину зависимостей, а также stream, смещение байта, номер сегмента и номер ссылки, связанные с первым отказом
Бюджеты живут в записи TJBIG2SegmentGraphValidationOptions, чьи поля MaxSegments, MaxReferencesPerSegment, MaxTotalReferences, MaxReferenceDepth и MaxSymbols ограничивают каждый обход
Конечное состояние — это значение TJBIG2SegmentGraphValidationStatus: от «не проверялось» и «корректно» до отказа из-за параметров, сбоев заголовков и ссылок, циклов и нарушений symbol dictionary, а HPDFJBIG2SegmentGraphValidationStatusName превращает его в текст
FailureStreamKind через TJBIG2SegmentStreamKind сообщает, где найден первый отказ — в globals stream (jbsskGlobals) или в image stream (jbsskImage)
THPDFJBIG2Decoder.LastSegmentGraphValidationInfo хранит тот же отчёт после LoadFromByteArray или LoadRegionFromByteArray
Условия отказа
Валидация отклоняет повреждённые или обрезанные заголовки, отдельные file header внутри внедрённых stream, запрещённые короткие и чрезмерно длинные таблицы ссылок, дублирующиеся или отсутствующие идентификаторы сегментов, физически опережающие зависимости, циклы зависимостей, избыточную глубину и превышение настроенных бюджетов на сегменты или рёбра
Сегменты изображений обязаны использовать привязку к странице 1, глобальные сегменты — привязку 0, а глобальный сегмент не может зависеть от сегмента изображения
Внедрённые сегменты end-of-page, end-of-file и палитры цвета отклоняются, как и сегменты region и page-information, предназначенные только для страниц, оказавшиеся внутри JBIG2Globals
Заголовки symbol dictionary проверяются до декодирования, поэтому объявленные счётчики новых и экспортируемых symbol, агрегированные пулы входных symbol и невозможные итоги экспорта приводят к отказу ещё до выделения памяти под bitmap
Граница декодера и кеша globals
THPDFJBIG2Decoder, HPDFJBIG2NativeMMRDecode, HPDFJBIG2NativeRegionDecode и вызовы внедрённого HPDFJBIG2DecDecodeEx разделяют одну и ту же политику
Зарегистрированные native- и внешние backends используют уже проваленные внутренние пути, что избавляет от повторного обхода графа при обычном декодировании
THPDFJBIG2GlobalsPool.Register принимает только корректный stream из одних лишь глобальных сегментов — это не даёт повреждённым общим словарям попасть в повторное использование на уровне документа
Автономные файлы JBIG2, передаваемые с Embedded = False, сохраняют свой отдельный файловый путь декодирования
См. Поддержка сжатия JBIG2, THPDFJBIG2Decoder.LoadFromByteArray и THPDFJBIG2Decoder.LoadRegionFromByteArray