39df253e2b
The fix from upstream did not apply cleanly due to many context changes.
This was adapted by cloning mupdf 1.9a from git and fixing conflicts
after applying our patches and cherry-picking upstream commit 1e03c06.
This is a follow-up to 47a04fca99
.
* gnu/packages/patches/mupdf-CVE-2016-8674.patch: Adapt to 1.9a.
165 lines
4.8 KiB
Diff
165 lines
4.8 KiB
Diff
Fix CVE-2016-8674 (use-after-free in pdf_to_num()).
|
|
|
|
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-8674
|
|
https://security-tracker.debian.org/tracker/CVE-2016-8674
|
|
|
|
Patch adapted from upstream source repository:
|
|
http://git.ghostscript.com/?p=mupdf.git;h=1e03c06456d997435019fb3526fa2d4be7dbc6ec
|
|
|
|
diff --git a/include/mupdf/pdf/document.h b/include/mupdf/pdf/document.h
|
|
index f8ef0cd..e8345b7 100644
|
|
--- a/include/mupdf/pdf/document.h
|
|
+++ b/include/mupdf/pdf/document.h
|
|
@@ -258,6 +258,10 @@ struct pdf_document_s
|
|
fz_font **type3_fonts;
|
|
|
|
pdf_resource_tables *resources;
|
|
+
|
|
+ int orphans_max;
|
|
+ int orphans_count;
|
|
+ pdf_obj **orphans;
|
|
};
|
|
|
|
/*
|
|
diff --git a/include/mupdf/pdf/object.h b/include/mupdf/pdf/object.h
|
|
index 346a2f1..02d4119 100644
|
|
--- a/include/mupdf/pdf/object.h
|
|
+++ b/include/mupdf/pdf/object.h
|
|
@@ -109,6 +109,7 @@ pdf_obj *pdf_dict_gets(fz_context *ctx, pdf_obj *dict, const char *key);
|
|
pdf_obj *pdf_dict_getsa(fz_context *ctx, pdf_obj *dict, const char *key, const char *abbrev);
|
|
void pdf_dict_put(fz_context *ctx, pdf_obj *dict, pdf_obj *key, pdf_obj *val);
|
|
void pdf_dict_put_drop(fz_context *ctx, pdf_obj *dict, pdf_obj *key, pdf_obj *val);
|
|
+void pdf_dict_get_put_drop(fz_context *ctx, pdf_obj *dict, pdf_obj *key, pdf_obj *val, pdf_obj **old_val);
|
|
void pdf_dict_puts(fz_context *ctx, pdf_obj *dict, const char *key, pdf_obj *val);
|
|
void pdf_dict_puts_drop(fz_context *ctx, pdf_obj *dict, const char *key, pdf_obj *val);
|
|
void pdf_dict_putp(fz_context *ctx, pdf_obj *dict, const char *path, pdf_obj *val);
|
|
diff --git a/source/pdf/pdf-object.c b/source/pdf/pdf-object.c
|
|
index f2e4551..a0d0d8e 100644
|
|
--- a/source/pdf/pdf-object.c
|
|
+++ b/source/pdf/pdf-object.c
|
|
@@ -1240,9 +1240,13 @@ pdf_dict_geta(fz_context *ctx, pdf_obj *obj, pdf_obj *key, pdf_obj *abbrev)
|
|
return pdf_dict_get(ctx, obj, abbrev);
|
|
}
|
|
|
|
-void
|
|
-pdf_dict_put(fz_context *ctx, pdf_obj *obj, pdf_obj *key, pdf_obj *val)
|
|
+static void
|
|
+pdf_dict_get_put(fz_context *ctx, pdf_obj *obj, pdf_obj *key, pdf_obj *val, pdf_obj **old_val)
|
|
{
|
|
+
|
|
+ if (old_val)
|
|
+ *old_val = NULL;
|
|
+
|
|
RESOLVE(obj);
|
|
if (obj >= PDF_OBJ__LIMIT)
|
|
{
|
|
@@ -1282,7 +1286,10 @@ pdf_dict_put(fz_context *ctx, pdf_obj *obj, pdf_obj *key, pdf_obj *val)
|
|
{
|
|
pdf_obj *d = DICT(obj)->items[i].v;
|
|
DICT(obj)->items[i].v = pdf_keep_obj(ctx, val);
|
|
- pdf_drop_obj(ctx, d);
|
|
+ if (old_val)
|
|
+ *old_val = d;
|
|
+ else
|
|
+ pdf_drop_obj(ctx, d);
|
|
}
|
|
}
|
|
else
|
|
@@ -1305,10 +1312,27 @@ pdf_dict_put(fz_context *ctx, pdf_obj *obj, pdf_obj *key, pdf_obj *val)
|
|
}
|
|
|
|
void
|
|
+pdf_dict_put(fz_context *ctx, pdf_obj *obj, pdf_obj *key, pdf_obj *val)
|
|
+{
|
|
+ pdf_dict_get_put(ctx, obj, key, val, NULL);
|
|
+}
|
|
+
|
|
+void
|
|
pdf_dict_put_drop(fz_context *ctx, pdf_obj *obj, pdf_obj *key, pdf_obj *val)
|
|
{
|
|
fz_try(ctx)
|
|
- pdf_dict_put(ctx, obj, key, val);
|
|
+ pdf_dict_get_put(ctx, obj, key, val, NULL);
|
|
+ fz_always(ctx)
|
|
+ pdf_drop_obj(ctx, val);
|
|
+ fz_catch(ctx)
|
|
+ fz_rethrow(ctx);
|
|
+}
|
|
+
|
|
+void
|
|
+pdf_dict_get_put_drop(fz_context *ctx, pdf_obj *obj, pdf_obj *key, pdf_obj *val, pdf_obj **old_val)
|
|
+{
|
|
+ fz_try(ctx)
|
|
+ pdf_dict_get_put(ctx, obj, key, val, old_val);
|
|
fz_always(ctx)
|
|
pdf_drop_obj(ctx, val);
|
|
fz_catch(ctx)
|
|
diff --git a/source/pdf/pdf-repair.c b/source/pdf/pdf-repair.c
|
|
index fdd4648..212c8b7 100644
|
|
--- a/source/pdf/pdf-repair.c
|
|
+++ b/source/pdf/pdf-repair.c
|
|
@@ -259,6 +259,27 @@ pdf_repair_obj_stm(fz_context *ctx, pdf_document *doc, int num, int gen)
|
|
}
|
|
}
|
|
|
|
+static void
|
|
+orphan_object(fz_context *ctx, pdf_document *doc, pdf_obj *obj)
|
|
+{
|
|
+ if (doc->orphans_count == doc->orphans_max)
|
|
+ {
|
|
+ int new_max = (doc->orphans_max ? doc->orphans_max*2 : 32);
|
|
+
|
|
+ fz_try(ctx)
|
|
+ {
|
|
+ doc->orphans = fz_resize_array(ctx, doc->orphans, new_max, sizeof(*doc->orphans));
|
|
+ doc->orphans_max = new_max;
|
|
+ }
|
|
+ fz_catch(ctx)
|
|
+ {
|
|
+ pdf_drop_obj(ctx, obj);
|
|
+ fz_rethrow(ctx);
|
|
+ }
|
|
+ }
|
|
+ doc->orphans[doc->orphans_count++] = obj;
|
|
+}
|
|
+
|
|
void
|
|
pdf_repair_xref(fz_context *ctx, pdf_document *doc)
|
|
{
|
|
@@ -520,12 +541,13 @@ pdf_repair_xref(fz_context *ctx, pdf_document *doc)
|
|
/* correct stream length for unencrypted documents */
|
|
if (!encrypt && list[i].stm_len >= 0)
|
|
{
|
|
+ pdf_obj *old_obj = NULL;
|
|
dict = pdf_load_object(ctx, doc, list[i].num, list[i].gen);
|
|
|
|
length = pdf_new_int(ctx, doc, list[i].stm_len);
|
|
- pdf_dict_put(ctx, dict, PDF_NAME_Length, length);
|
|
- pdf_drop_obj(ctx, length);
|
|
-
|
|
+ pdf_dict_get_put_drop(ctx, dict, PDF_NAME_Length, length, &old_obj);
|
|
+ if (old_obj)
|
|
+ orphan_object(ctx, doc, old_obj);
|
|
pdf_drop_obj(ctx, dict);
|
|
}
|
|
}
|
|
diff --git a/source/pdf/pdf-xref.c b/source/pdf/pdf-xref.c
|
|
index 3de1cd2..6682741 100644
|
|
--- a/source/pdf/pdf-xref.c
|
|
+++ b/source/pdf/pdf-xref.c
|
|
@@ -1626,6 +1626,12 @@ pdf_close_document(fz_context *ctx, pdf_document *doc)
|
|
|
|
pdf_drop_resource_tables(ctx, doc);
|
|
|
|
+ for (i = 0; i < doc->orphans_count; i++)
|
|
+ {
|
|
+ pdf_drop_obj(ctx, doc->orphans[i]);
|
|
+ }
|
|
+ fz_free(ctx, doc->orphans);
|
|
+
|
|
fz_free(ctx, doc);
|
|
}
|
|
|
|
--
|
|
2.10.1
|
|
|