summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2014-01-21 18:28:21 +0000
committerRobin Watts <robin.watts@artifex.com>2014-01-21 18:34:53 +0000
commitd695605c5d91b951a9c37f64a843e92caaa178e9 (patch)
tree3aff3bb5d759f8cebfb6649628dc019da93c013c /source
parent3f766db16a6fea2a0b8c568ba9475a54a8a1a023 (diff)
downloadmupdf-d695605c5d91b951a9c37f64a843e92caaa178e9.tar.xz
Bug 694900: Avoid valgrind problems when cmap tables fill up.
The test file on this bug: de53b4bd41191f02d01a3c39b4880fa8_asan_heap-oob_caba3c_9561_7427.pdf includes a corrupt CMAP. When this is read into memory it produces a CMAP where the table gets too large. This produces lots of warnings from 'add_table', but the calls to add_table all assume that the process completed fine, resulting in range entries being added that point to nonexistent values. The fix is to make add_table return a bool to indicate success or failure, and to only add range entries if the add_table succeeds. Thanks to Mateusz Jurczyk and Gynvael Coldwind of the Google Security Team for providing the example files.
Diffstat (limited to 'source')
-rw-r--r--source/pdf/pdf-cmap.c56
1 files changed, 40 insertions, 16 deletions
diff --git a/source/pdf/pdf-cmap.c b/source/pdf/pdf-cmap.c
index a1f0b0b0..025d4659 100644
--- a/source/pdf/pdf-cmap.c
+++ b/source/pdf/pdf-cmap.c
@@ -180,13 +180,13 @@ pdf_add_codespace(fz_context *ctx, pdf_cmap *cmap, int low, int high, int n)
/*
* Add an integer to the table.
*/
-static void
+static int
add_table(fz_context *ctx, pdf_cmap *cmap, int value)
{
if (cmap->tlen >= USHRT_MAX + 1)
{
fz_warn(ctx, "cmap table is full; ignoring additional entries");
- return;
+ return 1;
}
if (cmap->tlen + 1 > cmap->tcap)
{
@@ -195,6 +195,7 @@ add_table(fz_context *ctx, pdf_cmap *cmap, int value)
cmap->tcap = new_cap;
}
cmap->table[cmap->tlen++] = value;
+ return 0;
}
/*
@@ -242,9 +243,13 @@ pdf_map_range_to_table(fz_context *ctx, pdf_cmap *cmap, int low, int *table, int
fz_warn(ctx, "cannot map range to table; table is full");
else
{
+ int fail = 0;
for (i = 0; i < len; i++)
- add_table(ctx, cmap, table[i]);
- add_range(ctx, cmap, low, high, PDF_CMAP_TABLE, offset);
+ fail |= add_table(ctx, cmap, table[i]);
+ if (!fail)
+ add_range(ctx, cmap, low, high, PDF_CMAP_TABLE, offset);
+ else
+ cmap->tlen = offset;
}
}
@@ -289,11 +294,15 @@ pdf_map_one_to_many(fz_context *ctx, pdf_cmap *cmap, int low, int *values, int l
fz_warn(ctx, "cannot map one to many; table is full");
else
{
+ int fail;
offset = cmap->tlen;
- add_table(ctx, cmap, len);
+ fail = add_table(ctx, cmap, len);
for (i = 0; i < len; i++)
- add_table(ctx, cmap, values[i]);
- add_range(ctx, cmap, low, low, PDF_CMAP_MULTI, offset);
+ fail |= add_table(ctx, cmap, values[i]);
+ if (!fail)
+ add_range(ctx, cmap, low, low, PDF_CMAP_MULTI, offset);
+ else
+ cmap->tlen = offset;
}
}
@@ -352,8 +361,10 @@ pdf_sort_cmap(fz_context *ctx, pdf_cmap *cmap)
/* LS -> L */
else if (pdf_range_flags(a) == PDF_CMAP_TABLE && pdf_range_flags(b) == PDF_CMAP_SINGLE && (pdf_range_high(b) - a->low <= 0x3fff))
{
- pdf_range_set_high(a, pdf_range_high(b));
- add_table(ctx, cmap, b->offset);
+ if (!add_table(ctx, cmap, b->offset))
+ pdf_range_set_high(a, pdf_range_high(b));
+ else
+ *(++a) = *b;
}
/* LR -> LR */
@@ -375,18 +386,31 @@ pdf_sort_cmap(fz_context *ctx, pdf_cmap *cmap)
/* SS -> L */
if (pdf_range_flags(a) == PDF_CMAP_SINGLE && pdf_range_flags(b) == PDF_CMAP_SINGLE)
{
- pdf_range_set_flags(a, PDF_CMAP_TABLE);
- pdf_range_set_high(a, pdf_range_high(b));
- add_table(ctx, cmap, a->offset);
- add_table(ctx, cmap, b->offset);
- a->offset = cmap->tlen - 2;
+ int offset = cmap->tlen;
+ int fail = add_table(ctx, cmap, a->offset);
+ fail |= add_table(ctx, cmap, b->offset);
+ if (!fail)
+ {
+ pdf_range_set_flags(a, PDF_CMAP_TABLE);
+ pdf_range_set_high(a, pdf_range_high(b));
+ a->offset = cmap->tlen - 2;
+ } else {
+ cmap->tlen = offset;
+ *(++a) = *b;
+ }
}
/* LS -> L */
else if (pdf_range_flags(a) == PDF_CMAP_TABLE && pdf_range_flags(b) == PDF_CMAP_SINGLE && (pdf_range_high(b) - a->low <= 0x3fff))
{
- pdf_range_set_high(a, pdf_range_high(b));
- add_table(ctx, cmap, b->offset);
+ if (!add_table(ctx, cmap, b->offset))
+ {
+ pdf_range_set_high(a, pdf_range_high(b));
+ }
+ else
+ {
+ *(++a) = *b;
+ }
}
/* XX -> XX */