From 7b4f4e871ad5a0ec98f8e995e058ff87795fe272 Mon Sep 17 00:00:00 2001 From: Ken Sharp Date: Tue, 6 Sep 2022 14:00:11 +0100 Subject: GhostPDF - check for 0 Size entries in XRefStm /Index array Bug #705843 " heap-buffer-overflow in pdf/pdf_xref.c:114 read_xref_stream_entries (exploitable)" The /Index array in the XRefStm holds pairs of values, the first is the first object number in a subsection, the second is the number of entries in a subsection. We were doing loads of checks on the validity of these numbers, but forgot to check that the size was at least 1. Because we later use start + size - 1 we could then end up with a ridiculously large index, because these are unsigned values. If we get a size of 0, just ignore the subsection. While making changes, renamed 'end' to 'size' because its a better descriptive name. --- pdf/pdf_xref.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/pdf/pdf_xref.c b/pdf/pdf_xref.c index 78c0f1008..3f3d8008f 100644 --- a/pdf/pdf_xref.c +++ b/pdf/pdf_xref.c @@ -308,7 +308,7 @@ static int pdfi_process_xref_stream(pdf_context *ctx, pdf_stream *stream_obj, pd return code; } } else { - int64_t start, end; + int64_t start, size; if (code < 0) { pdfi_close_file(ctx, XRefStrm); @@ -335,7 +335,7 @@ static int pdfi_process_xref_stream(pdf_context *ctx, pdf_stream *stream_obj, pd return code; } - code = pdfi_array_get_int(ctx, a, (uint64_t)i+1, &end); + code = pdfi_array_get_int(ctx, a, (uint64_t)i+1, &size); if (code < 0) { pdfi_countdown(a); pdfi_close_file(ctx, XRefStrm); @@ -344,8 +344,11 @@ static int pdfi_process_xref_stream(pdf_context *ctx, pdf_stream *stream_obj, pd return code; } - if (start + end >= ctx->xref_table->xref_size) { - code = resize_xref(ctx, start + end); + if (size < 1) + continue; + + if (start + size >= ctx->xref_table->xref_size) { + code = resize_xref(ctx, start + size); if (code < 0) { pdfi_countdown(a); pdfi_close_file(ctx, XRefStrm); @@ -355,7 +358,7 @@ static int pdfi_process_xref_stream(pdf_context *ctx, pdf_stream *stream_obj, pd } } - code = read_xref_stream_entries(ctx, XRefStrm, start, start + end - 1, (uint64_t *)W); + code = read_xref_stream_entries(ctx, XRefStrm, start, start + size - 1, (uint64_t *)W); if (code < 0) { pdfi_countdown(a); pdfi_close_file(ctx, XRefStrm); -- cgit v1.2.1