guix/gnu/packages/patches/mupdf-CVE-2016-8674.patch
Marius Bakke 39df253e2b
gnu: mupdf: Modify CVE-2016-8674 patch to apply to 1.9a.
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.
2016-10-26 15:03:42 +01:00

166 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