summaryrefslogtreecommitdiff
path: root/pdf/pdf_nametree.c
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2012-01-06 11:38:43 +0000
committerRobin Watts <robin@ghostscript.com>2012-01-06 13:49:24 +0000
commit09f1a3d3d863099c103100ed10c8cec82ea7aed3 (patch)
treee5eaa31b5b2efc0c9e9537649e7e681ed428e8c0 /pdf/pdf_nametree.c
parenta0203aeba59a207db78a312b9b3aacf97b2802f5 (diff)
downloadmupdf-09f1a3d3d863099c103100ed10c8cec82ea7aed3.tar.xz
Add 'marking' functions for dictionaries.
In various places in the code, we add markers (".seen") to dictionaries as we traverse them to ensure that we don't go into infinite loops. Adding a dictionary entry is bad as it's a) an expensive operation, b) a potentially destructive one, and c) produces another possible point of failure (as mallocs can fail). Instead, add a flag to each dict to allow them to be marked/unmarked and use that instead. Thanks to Zeniko for pointing out various places that could usefully be protected against infinite recursion.
Diffstat (limited to 'pdf/pdf_nametree.c')
-rw-r--r--pdf/pdf_nametree.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/pdf/pdf_nametree.c b/pdf/pdf_nametree.c
index d84f2e8b..bbb956f1 100644
--- a/pdf/pdf_nametree.c
+++ b/pdf/pdf_nametree.c
@@ -25,7 +25,15 @@ pdf_lookup_name_imp(fz_context *ctx, fz_obj *node, fz_obj *needle)
else if (fz_objcmp(needle, last) > 0)
l = m + 1;
else
- return pdf_lookup_name_imp(ctx, kid, needle);
+ {
+ fz_obj *obj;
+
+ if (fz_dict_mark(node))
+ break;
+ obj = pdf_lookup_name_imp(ctx, kid, needle);
+ fz_dict_unmark(node);
+ return obj;
+ }
}
}
@@ -49,6 +57,14 @@ pdf_lookup_name_imp(fz_context *ctx, fz_obj *node, fz_obj *needle)
else
return val;
}
+
+ /* Spec says names should be sorted (hence the binary search,
+ * above), but Acrobat copes with non-sorted. Drop back to a
+ * simple search if the binary search fails. */
+ r = fz_array_len(names)/2;
+ for (l = 0; l < r; l++)
+ if (!fz_objcmp(needle, fz_array_get(names, l * 2)))
+ return fz_array_get(names, l * 2 + 1);
}
return NULL;
@@ -102,10 +118,11 @@ pdf_load_name_tree_imp(fz_obj *dict, pdf_xref *xref, fz_obj *node)
fz_obj *names = fz_dict_gets(node, "Names");
int i;
- if (kids)
+ if (kids && !fz_dict_mark(node))
{
for (i = 0; i < fz_array_len(kids); i++)
pdf_load_name_tree_imp(dict, xref, fz_array_get(kids, i));
+ fz_dict_unmark(node);
}
if (names)