This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pdfbox-jbig2.git
The following commit(s) were added to refs/heads/master by this push:
new 44fe469 PDFBOX-6155: Fix JBIG2 symbol dictionary coding context reuse
(§7.4.2.2 steps 3–4)
44fe469 is described below
commit 44fe469f741f128ecf8847d87030bbd398654adb
Author: Maruan Sahyoun <[email protected]>
AuthorDate: Sun Apr 19 18:14:40 2026 +0200
PDFBOX-6155: Fix JBIG2 symbol dictionary coding context reuse (§7.4.2.2
steps 3–4)
---
.../pdfbox/jbig2/segments/SymbolDictionary.java | 67 +++++++++++++++++-----
1 file changed, 53 insertions(+), 14 deletions(-)
diff --git
a/src/main/java/org/apache/pdfbox/jbig2/segments/SymbolDictionary.java
b/src/main/java/org/apache/pdfbox/jbig2/segments/SymbolDictionary.java
index 3803414..dd6cf1d 100644
--- a/src/main/java/org/apache/pdfbox/jbig2/segments/SymbolDictionary.java
+++ b/src/main/java/org/apache/pdfbox/jbig2/segments/SymbolDictionary.java
@@ -128,28 +128,41 @@ public class SymbolDictionary implements Dictionary
readAmountOfNewSymbols();
setInSyms();
- if (isCodingContextUsed)
- {
- SegmentHeader[] rtSegments = segmentHeader.getRtSegments();
+ boolean isContextAdopted = false;
+ SymbolDictionary lastSymbolDictionary = null;
+
+ SegmentHeader[] rtSegments = segmentHeader.getRtSegments();
+ if (rtSegments != null)
+ {
for (int i = rtSegments.length - 1; i >= 0; i--)
{
if (rtSegments[i].getSegmentType() == 0)
{
- SymbolDictionary symbolDictionary = (SymbolDictionary)
rtSegments[i]
- .getSegmentData();
+ lastSymbolDictionary = (SymbolDictionary) rtSegments[i]
+ .getSegmentData();
- if (symbolDictionary.isCodingContextRetained)
+ if (isCodingContextUsed &&
lastSymbolDictionary.isCodingContextRetained)
{
/* 7.4.2.2 3) */
- setRetainedCodingContexts(symbolDictionary);
+ adoptRetainedCodingContexts(lastSymbolDictionary);
+ isContextAdopted = true;
}
break;
}
}
}
+ if (isCodingContextUsed && !isContextAdopted)
+ {
+ throw new InvalidHeaderValueException(
+ lastSymbolDictionary == null
+ ? "Coding context reuse requested, but no referred symbol
dictionary found"
+ : "Coding context reuse requested, but last referred
symbol dictionary does not retain coding context"
+ );
+ }
+
this.checkInput();
}
@@ -271,16 +284,42 @@ public class SymbolDictionary implements Dictionary
}
}
- private void setRetainedCodingContexts(final SymbolDictionary sd)
+ /**
+ * Adopt retained arithmetic coding context from another symbol dictionary.
+ *
+ * Per spec §7.4.2.2:
+ * - Configuration MUST match (validated here)
+ * - Only bitmap coding statistics (CX) are reused
+ * - ArithmeticDecoder MUST NOT be reused (stream-bound)
+ * @throws InvalidHeaderValueException
+ */
+ private void adoptRetainedCodingContexts(final SymbolDictionary sd) throws
InvalidHeaderValueException
{
- this.sdTemplate = sd.sdTemplate;
- this.sdrTemplate = sd.sdrTemplate;
- this.sdATX = sd.sdATX;
- this.sdATY = sd.sdATY;
- this.sdrATX = sd.sdrATX;
- this.sdrATY = sd.sdrATY;
+ validateContextValues(sd);
this.cx = sd.cx;
}
+
+ /**
+ * The values of SDHUFF, SDREFAGG, SDTEMPLATE, SDRTEMPLATE, and all of the
AT locations
+ * (both direct and refinement) for this symbol dictionary must match the
corresponding
+ * values from the symbol dictionary whose context values are being used.
+ * @param sd
+ * @throws InvalidHeaderValueException
+ */
+ private void validateContextValues(final SymbolDictionary sd) throws
InvalidHeaderValueException
+ {
+ if ( this.isHuffmanEncoded != sd.isHuffmanEncoded
+ || this.useRefinementAggregation != sd.useRefinementAggregation
+ || this.sdTemplate != sd.sdTemplate
+ || this.sdrTemplate != sd.sdrTemplate
+ || !java.util.Arrays.equals(this.sdATX, sd.sdATX)
+ || !java.util.Arrays.equals(this.sdATY, sd.sdATY)
+ || !java.util.Arrays.equals(this.sdrATX, sd.sdrATX)
+ || !java.util.Arrays.equals(this.sdrATY, sd.sdrATY))
+ {
+ throw new InvalidHeaderValueException("SymbolDictionary reuse
values don't match");
+ }
+ }
private void checkInput() throws InvalidHeaderValueException
{