Commit 293a2e52b3fbd6dac2c89dfb35a546cdc027eb1b

Authored by Jay Berkenbilt
1 parent 3cfd6546

Disregard appearance state when irrelevant (fixes #949)

If /AP is a dictionary of streams rather than a dictionary of
dictionaries, disregard /AS, which is supposed to point to a subkey of
one of the dictionaries. This fix prevents qpdf's annotation
flattening from discarding some annotations when /AS is erroneously
set.
ChangeLog
... ... @@ -5,6 +5,15 @@
5 5 reserved object fits better in the QPDF API. The old call just
6 6 delegates to the new one.
7 7  
  8 +2023-05-13 Jay Berkenbilt <ejb@ql.org>
  9 +
  10 + * When an annotation dictionary's appearance dictionary (`/AP`)
  11 + has a key that is a stream, disregard `/AS` (which is supposed to
  12 + point to a subkey). This enables qpdf to not ignore annotations
  13 + that have incorrect values for `/AS` when the appearance stream is
  14 + directly in the `/AP` dictionary instead of in a subkey. Fixes
  15 + #949.
  16 +
8 17 2023-04-02 Jay Berkenbilt <ejb@ql.org>
9 18 * Allow QPDFJob's workflow to be split into a reading phase and a
10 19 writing phase to allow the caller to operate on the QPDF object
... ...
libqpdf/QPDFAnnotationObjectHelper.cc
... ... @@ -54,7 +54,14 @@ QPDFAnnotationObjectHelper::getAppearanceStream(
54 54 std::string desired_state = state.empty() ? getAppearanceState() : state;
55 55 if (ap.isDictionary()) {
56 56 QPDFObjectHandle ap_sub = ap.getKey(which);
57   - if (ap_sub.isStream() && desired_state.empty()) {
  57 + if (ap_sub.isStream()) {
  58 + // According to the spec, Appearance State is supposed to
  59 + // refer to a subkey of the appearance stream when /AP is
  60 + // a dictionary, but files have been seen in the wild
  61 + // where Appearance State is `/N` and `/AP` is a stream.
  62 + // Therefore, if `which` points to a stream, disregard
  63 + // state and just use the stream. See qpdf issue #949 for
  64 + // details.
58 65 QTC::TC("qpdf", "QPDFAnnotationObjectHelper AP stream");
59 66 return ap_sub;
60 67 }
... ...
manual/release-notes.rst
... ... @@ -26,6 +26,14 @@ For a detailed list of changes, please see the file
26 26 - Add ``QPDF::newReserved`` as a better alternative to
27 27 ``QPDFObjectHandle::newReserved``.
28 28  
  29 + - Bug fixes
  30 +
  31 + - Ignore an annotation's appearance state when the annotation only
  32 + has one appearance. This prevents qpdf's annotation flattening
  33 + logic from throwing away appearances of annotations whose
  34 + annotation state is set incorrectly, as has been seen in some
  35 + PDF files.
  36 +
29 37 11.3.0: February 25, 2023
30 38 - CLI Enhancements
31 39  
... ...
qpdf/qtest/qpdf/form-form-bad-fields-array.out
... ... @@ -178,7 +178,7 @@ Page: 11 0 R
178 178 Subtype: /Widget
179 179 Rect: [123.4, 692.1, 260.9, 706.7]
180 180 Appearance stream (/N): 14 0 R
181   - Appearance stream (/N, /3): null
  181 + Appearance stream (/N, /3): 14 0 R
182 182 Annotation: 16 0 R
183 183 Field: 16 0 R
184 184 Subtype: /Widget
... ... @@ -249,5 +249,5 @@ Page: 35 0 R
249 249 Subtype: /Widget
250 250 Rect: [113.6, 378.5, 351.3, 396.3]
251 251 Appearance stream (/N): 36 0 R
252   - Appearance stream (/N, /3): null
  252 + Appearance stream (/N, /3): 36 0 R
253 253 test 43 done
... ...
qpdf/qtest/qpdf/form-form-document-defaults.out
... ... @@ -166,7 +166,7 @@ Page: 11 0 R
166 166 Subtype: /Widget
167 167 Rect: [123.4, 692.1, 260.9, 706.7]
168 168 Appearance stream (/N): 14 0 R
169   - Appearance stream (/N, /3): null
  169 + Appearance stream (/N, /3): 14 0 R
170 170 Annotation: 16 0 R
171 171 Field: 16 0 R
172 172 Subtype: /Widget
... ... @@ -237,5 +237,5 @@ Page: 35 0 R
237 237 Subtype: /Widget
238 238 Rect: [113.6, 378.5, 351.3, 396.3]
239 239 Appearance stream (/N): 36 0 R
240   - Appearance stream (/N, /3): null
  240 + Appearance stream (/N, /3): 36 0 R
241 241 test 43 done
... ...
qpdf/qtest/qpdf/form-form-empty-from-odt.out
... ... @@ -166,7 +166,7 @@ Page: 11 0 R
166 166 Subtype: /Widget
167 167 Rect: [123.4, 692.1, 260.9, 706.7]
168 168 Appearance stream (/N): 14 0 R
169   - Appearance stream (/N, /3): null
  169 + Appearance stream (/N, /3): 14 0 R
170 170 Annotation: 16 0 R
171 171 Field: 16 0 R
172 172 Subtype: /Widget
... ... @@ -237,5 +237,5 @@ Page: 35 0 R
237 237 Subtype: /Widget
238 238 Rect: [113.6, 378.5, 351.3, 396.3]
239 239 Appearance stream (/N): 36 0 R
240   - Appearance stream (/N, /3): null
  240 + Appearance stream (/N, /3): 36 0 R
241 241 test 43 done
... ...
qpdf/qtest/qpdf/form-form-errors.out
... ... @@ -171,7 +171,7 @@ Page: 11 0 R
171 171 Subtype: /Widget
172 172 Rect: [123.4, 692.1, 260.9, 706.7]
173 173 Appearance stream (/N): 14 0 R
174   - Appearance stream (/N, /3): null
  174 + Appearance stream (/N, /3): 14 0 R
175 175 Annotation: 16 0 R
176 176 Field: 16 0 R
177 177 Subtype: /Widget
... ... @@ -242,5 +242,5 @@ Page: 35 0 R
242 242 Subtype: /Widget
243 243 Rect: [113.6, 378.5, 351.3, 396.3]
244 244 Appearance stream (/N): 36 0 R
245   - Appearance stream (/N, /3): null
  245 + Appearance stream (/N, /3): 36 0 R
246 246 test 43 done
... ...
qpdf/qtest/qpdf/form-form-mod1.out
... ... @@ -166,7 +166,7 @@ Page: 11 0 R
166 166 Subtype: /Widget
167 167 Rect: [123.4, 692.1, 260.9, 706.7]
168 168 Appearance stream (/N): 14 0 R
169   - Appearance stream (/N, /3): null
  169 + Appearance stream (/N, /3): 14 0 R
170 170 Annotation: 16 0 R
171 171 Field: 16 0 R
172 172 Subtype: /Widget
... ... @@ -237,5 +237,5 @@ Page: 35 0 R
237 237 Subtype: /Widget
238 238 Rect: [113.6, 378.5, 351.3, 396.3]
239 239 Appearance stream (/N): 36 0 R
240   - Appearance stream (/N, /3): null
  240 + Appearance stream (/N, /3): 36 0 R
241 241 test 43 done
... ...