File CVE-2023-31794.patch of Package mupdf.18178

From c0015401693b58e2deb5d75c39f27bc1216e47c6 Mon Sep 17 00:00:00 2001
From: Robin Watts <Robin.Watts@artifex.com>
Date: Thu, 30 Mar 2023 04:35:43 -0700
Subject: [PATCH] Bug 706506: Fix infinite recursion in mutool info.

2 separate problems here.

Firstly, pdf_mark_list_push fails to copy the pushed data
from local_list to the newly malloced block when we first
move from local storage to malloced storage.

(Also, while we are here, there is no point in storing
0 entries in the list as they will never be checked!)

Secondly, while gatherresourceinfo is supposed to be
called with indirected objects, it can (as is the case
with the given fuzzed file) be called with direct
references. These don't put anything sane in the cycle
checker.

Thus by using (legal) indirections from (say) the Font
resource entry back to something that contains the
original resource entry, we can get cycles that we don't
detect.

Fix this by pushing such entries onto the mark list.
---
 source/pdf/pdf-object.c | 18 +++++++++++-------
 source/tools/pdfinfo.c  |  8 ++++----
 2 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/source/pdf/pdf-object.c b/source/pdf/pdf-object.c
index 6971260aa6..31e40096ef 100644
--- a/source/pdf/pdf-object.c
+++ b/source/pdf/pdf-object.c
@@ -2617,19 +2617,23 @@ pdf_mark_list_push(fz_context *ctx, pdf_mark_list *marks, pdf_obj *obj)
 	int num = pdf_to_num(ctx, obj);
 	int i;
 
-	if (num > 0)
-	{
-		/* Note: this is slow, if the mark list is expected to be big use pdf_mark_bits instead! */
-		for (i = 0; i < marks->len; ++i)
-			if (marks->list[i] == num)
-				return 1;
-	}
+	/* If object is not an indirection, then no record to store, or check. */
+	if (num == 0)
+		return 0;
+
+	/* Note: this is slow, if the mark list is expected to be big use pdf_mark_bits instead! */
+	for (i = 0; i < marks->len; ++i)
+		if (marks->list[i] == num)
+			return 1;
 
 	if (marks->len == marks->max)
 	{
 		int newsize = marks->max << 1;
 		if (marks->list == marks->local_list)
+		{
 			marks->list = fz_malloc_array(ctx, newsize, int);
+			memcpy(marks->list, marks->local_list, sizeof(marks->local_list));
+		}
 		else
 			marks->list = fz_realloc_array(ctx, marks->list, newsize, int);
 		marks->max = newsize;
diff --git a/source/tools/pdfinfo.c b/source/tools/pdfinfo.c
index bffbfa8475..f7e7de369f 100644
--- a/source/tools/pdfinfo.c
+++ b/source/tools/pdfinfo.c
@@ -617,7 +617,7 @@ gatherresourceinfo(fz_context *ctx, pdf_mark_list *mark_list, globals *glo, int
 		fz_throw(ctx, FZ_ERROR_GENERIC, "cannot retrieve info from page %d", page);
 
 	font = pdf_dict_get(ctx, rsrc, PDF_NAME(Font));
-	if (show & FONTS && font)
+	if (show & FONTS && font && !pdf_mark_list_push(ctx, mark_list, font))
 	{
 		int n;
 
@@ -630,7 +630,7 @@ gatherresourceinfo(fz_context *ctx, pdf_mark_list *mark_list, globals *glo, int
 	}
 
 	xobj = pdf_dict_get(ctx, rsrc, PDF_NAME(XObject));
-	if (show & (IMAGES|XOBJS) && xobj)
+	if (show & (IMAGES|XOBJS) && xobj && !pdf_mark_list_push(ctx, mark_list, xobj))
 	{
 		int n;
 
@@ -649,11 +649,11 @@ gatherresourceinfo(fz_context *ctx, pdf_mark_list *mark_list, globals *glo, int
 	}
 
 	shade = pdf_dict_get(ctx, rsrc, PDF_NAME(Shading));
-	if (show & SHADINGS && shade)
+	if (show & SHADINGS && shade && !pdf_mark_list_push(ctx, mark_list, shade))
 		gathershadings(ctx, glo, page, pageref, shade);
 
 	pattern = pdf_dict_get(ctx, rsrc, PDF_NAME(Pattern));
-	if (show & PATTERNS && pattern)
+	if (show & PATTERNS && pattern && !pdf_mark_list_push(ctx, mark_list, pattern))
 	{
 		int n;
 		gatherpatterns(ctx, glo, page, pageref, pattern);
openSUSE Build Service is sponsored by