You need to sign in before continuing.

Commit 8b1e307741d52a0c401296eaf790b18f98d67b6a

Authored by Jay Berkenbilt
1 parent 5ce287d6

Warn for duplicated dictionary keys (fixes #345)

ChangeLog
  1 +2019-09-19 Jay Berkenbilt <ejb@ql.org>
  2 +
  3 + * Warn when duplicated dictionary keys are found during parsing.
  4 + The behavior remains as before: later keys override earlier ones.
  5 + However, this generates a warning now rather than being silently
  6 + ignored. Fixes #345.
  7 +
1 2019-09-17 Jay Berkenbilt <ejb@ql.org> 8 2019-09-17 Jay Berkenbilt <ejb@ql.org>
2 9
3 * QIntC tests: don't assume char is signed. Fixes #361. 10 * QIntC tests: don't assume char is signed. Fixes #361.
libqpdf/QPDFObjectHandle.cc
@@ -2135,7 +2135,18 @@ QPDFObjectHandle::parseInternal(PointerHolder&lt;InputSource&gt; input, @@ -2135,7 +2135,18 @@ QPDFObjectHandle::parseInternal(PointerHolder&lt;InputSource&gt; input,
2135 { 2135 {
2136 val = olist.at(++i); 2136 val = olist.at(++i);
2137 } 2137 }
2138 - dict[key_obj.getName()] = val; 2138 + std::string key = key_obj.getName();
  2139 + if (dict.count(key) > 0)
  2140 + {
  2141 + QTC::TC("qpdf", "QPDFObjectHandle duplicate dict key");
  2142 + warn(context,
  2143 + QPDFExc(
  2144 + qpdf_e_damaged_pdf,
  2145 + input->getName(), object_description, offset,
  2146 + "dictionary has duplicated key " + key +
  2147 + "; last occurrence overrides earlier ones"));
  2148 + }
  2149 + dict[key] = val;
2139 } 2150 }
2140 object = newDictionary(dict); 2151 object = newDictionary(dict);
2141 setObjectDescriptionFromInput( 2152 setObjectDescriptionFromInput(
qpdf/qpdf.testcov
@@ -445,3 +445,4 @@ QPDF eof skipping spaces before xref 1 @@ -445,3 +445,4 @@ QPDF eof skipping spaces before xref 1
445 QPDF_encryption user matches owner V < 5 0 445 QPDF_encryption user matches owner V < 5 0
446 QPDF_encryption same password 1 446 QPDF_encryption same password 1
447 QPDFWriter stream in ostream 0 447 QPDFWriter stream in ostream 0
  448 +QPDFObjectHandle duplicate dict key 0
qpdf/qtest/qpdf.test
@@ -2314,7 +2314,7 @@ my @badfiles = (&quot;not a PDF file&quot;, # 1 @@ -2314,7 +2314,7 @@ my @badfiles = (&quot;not a PDF file&quot;, # 1
2314 "bad }", # 14 2314 "bad }", # 14
2315 "bad ]", # 15 2315 "bad ]", # 15
2316 "bad >>", # 16 2316 "bad >>", # 16
2317 - "odd number of dictionary items", # 17 2317 + "dictionary errors", # 17
2318 "bad )", # 18 2318 "bad )", # 18
2319 "bad >", # 19 2319 "bad >", # 19
2320 "invalid hexstring character", # 20 2320 "invalid hexstring character", # 20
qpdf/qtest/qpdf/bad17-recover.out
  1 +WARNING: bad17.pdf (trailer, offset 715): dictionary has duplicated key /K; last occurrence overrides earlier ones
1 WARNING: bad17.pdf (trailer, offset 715): dictionary ended prematurely; using null as value for last key 2 WARNING: bad17.pdf (trailer, offset 715): dictionary ended prematurely; using null as value for last key
2 /QTest is implicit 3 /QTest is implicit
3 /QTest is direct and has type null (2) 4 /QTest is direct and has type null (2)
qpdf/qtest/qpdf/bad17.out
  1 +WARNING: bad17.pdf (trailer, offset 715): dictionary has duplicated key /K; last occurrence overrides earlier ones
1 WARNING: bad17.pdf (trailer, offset 715): dictionary ended prematurely; using null as value for last key 2 WARNING: bad17.pdf (trailer, offset 715): dictionary ended prematurely; using null as value for last key
2 /QTest is implicit 3 /QTest is implicit
3 /QTest is direct and has type null (2) 4 /QTest is direct and has type null (2)
qpdf/qtest/qpdf/bad17.pdf
@@ -73,6 +73,8 @@ xref @@ -73,6 +73,8 @@ xref
73 trailer << 73 trailer <<
74 /Size 7 74 /Size 7
75 /Root 1 0 R 75 /Root 1 0 R
  76 + /K 1
  77 + /K 2
76 /Something 78 /Something
77 >> 79 >>
78 startxref 80 startxref
qpdf/qtest/qpdf/issue-51.out
1 WARNING: issue-51.pdf: can't find PDF header 1 WARNING: issue-51.pdf: can't find PDF header
2 WARNING: issue-51.pdf: reported number of objects (0) is not one plus the highest object number (8) 2 WARNING: issue-51.pdf: reported number of objects (0) is not one plus the highest object number (8)
  3 +WARNING: issue-51.pdf (object 7 0, offset 476): dictionary has duplicated key /0000; last occurrence overrides earlier ones
3 WARNING: issue-51.pdf (object 7 0, offset 553): expected endobj 4 WARNING: issue-51.pdf (object 7 0, offset 553): expected endobj
  5 +WARNING: issue-51.pdf (object 1 0, offset 236): dictionary has duplicated key /00000000; last occurrence overrides earlier ones
4 WARNING: issue-51.pdf (object 1 0, offset 359): expected endobj 6 WARNING: issue-51.pdf (object 1 0, offset 359): expected endobj
5 WARNING: issue-51.pdf (offset 70): loop detected resolving object 2 0 7 WARNING: issue-51.pdf (offset 70): loop detected resolving object 2 0
6 WARNING: issue-51.pdf (object 2 0, offset 26): /Length key in stream dictionary is not an integer 8 WARNING: issue-51.pdf (object 2 0, offset 26): /Length key in stream dictionary is not an integer