From bd91f3451377929df37fccebe5c45241ce2065e4 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald <jonas.jenwald@gmail.com> Date: Sat, 17 Dec 2016 13:34:18 +0100 Subject: [PATCH] Ensure that we handle indirect objects in all types of `Opt` entries in `ChoiceWidget` annotation dictionaries I haven't got an example where the current code breaks, but given all the previous cases we've seen where PDF generators use indirect objects in Arrays it makes sense to fix this pro-actively. I've modified the relevant unit-tests slightly, and they would *not* pass without the code changes in this patch. *Note:* `Dict_getArray` only dereferences Array elements on the "top-level", to avoid recursion issues. Furthermore if you have to loop through the Array at the call-site anyway, then using `Dict_get` in combination with `XRef_fetchIfRef` is a tiny bit more efficient. --- src/core/annotation.js | 10 ++++++---- test/unit/annotation_layer_spec.js | 19 +++++++++++++++---- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/core/annotation.js b/src/core/annotation.js index 7fb6a13f4..97f728621 100644 --- a/src/core/annotation.js +++ b/src/core/annotation.js @@ -779,14 +779,16 @@ var ChoiceWidgetAnnotation = (function ChoiceWidgetAnnotationClosure() { // it to an array of arrays as well for convenience in the display layer. this.data.options = []; - var options = params.dict.getArray('Opt'); + var options = params.dict.get('Opt'); if (isArray(options)) { + var xref = params.xref; for (var i = 0, ii = options.length; i < ii; i++) { - var option = options[i]; + var option = xref.fetchIfRef(options[i]); + var isOptionArray = isArray(option); this.data.options[i] = { - exportValue: isArray(option) ? option[0] : option, - displayValue: isArray(option) ? option[1] : option, + exportValue: isOptionArray ? xref.fetchIfRef(option[0]) : option, + displayValue: isOptionArray ? xref.fetchIfRef(option[1]) : option, }; } } diff --git a/test/unit/annotation_layer_spec.js b/test/unit/annotation_layer_spec.js index 2e224d1b3..f5f3a1bb4 100644 --- a/test/unit/annotation_layer_spec.js +++ b/test/unit/annotation_layer_spec.js @@ -900,7 +900,12 @@ describe('Annotation layer', function() { }); it('should handle option arrays with array elements', function() { - var options = [['foo_export', 'Foo'], ['bar_export', 'Bar']]; + var optionBarRef = new Ref(20, 0); + var optionBarStr = 'Bar'; + var optionOneRef = new Ref(10, 0); + var optionOneArr = ['bar_export', optionBarRef]; + + var options = [['foo_export', 'Foo'], optionOneRef]; var expected = [ { exportValue: 'foo_export', @@ -916,7 +921,9 @@ describe('Annotation layer', function() { var choiceWidgetRef = new Ref(123, 0); var xref = new XRefMock([ - { ref: choiceWidgetRef, data: choiceWidgetDict, } + { ref: choiceWidgetRef, data: choiceWidgetDict, }, + { ref: optionBarRef, data: optionBarStr, }, + { ref: optionOneRef, data: optionOneArr, }, ]); var choiceWidgetAnnotation = annotationFactory.create(xref, @@ -928,7 +935,10 @@ describe('Annotation layer', function() { }); it('should handle option arrays with string elements', function() { - var options = ['Foo', 'Bar']; + var optionBarRef = new Ref(10, 0); + var optionBarStr = 'Bar'; + + var options = ['Foo', optionBarRef]; var expected = [ { exportValue: 'Foo', @@ -944,7 +954,8 @@ describe('Annotation layer', function() { var choiceWidgetRef = new Ref(981, 0); var xref = new XRefMock([ - { ref: choiceWidgetRef, data: choiceWidgetDict, } + { ref: choiceWidgetRef, data: choiceWidgetDict, }, + { ref: optionBarRef, data: optionBarStr, } ]); var choiceWidgetAnnotation = annotationFactory.create(xref,