diff options
author | Ken Sharp <ken.sharp@artifex.com> | 2022-01-13 12:16:29 +0000 |
---|---|---|
committer | Ken Sharp <ken.sharp@artifex.com> | 2022-01-13 12:18:30 +0000 |
commit | 0d023e9bc705345bd383158a5dc6889f06280a91 (patch) | |
tree | 04f4aab7a603f1c04c910afa7026785a009997d2 | |
parent | 4affbf8fe0e5982058c498a33689cc5182eab0ed (diff) | |
download | ghostpdl-0d023e9bc705345bd383158a5dc6889f06280a91.tar.gz |
OSS-fuzz #43247 - special treatment for reading streams
When reading objects from the PDF file we don't generally dereference
anything, we just store indirect references as indirect references.
This insulates us from circular references in obejcts at this point
and the loop detection machinery caters for later dereferencing.
However, streams are an exception, we validate the /Length when we read
the stream object, which means that if the /Length is associated with
an indirect reference we will try to dereference it. If the reference
points back to the same stream object, we end up in infinite recursion.
Do special case loop detection just for this.
-rw-r--r-- | pdf/pdf_deref.c | 30 |
1 files changed, 29 insertions, 1 deletions
diff --git a/pdf/pdf_deref.c b/pdf/pdf_deref.c index 1740c6135..b4fddedc5 100644 --- a/pdf/pdf_deref.c +++ b/pdf/pdf_deref.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2020-2021 Artifex Software, Inc. +/* Copyright (C) 2020-2022 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -245,6 +245,28 @@ static int pdfi_read_stream_object(pdf_context *ctx, pdf_c_stream *s, gs_offset_ stream_obj->stream_dict->indirect_gen = stream_obj->stream_dict->generation_num = gen; stream_obj->stream_offset = offset; + /* Exceptional code. Normally we do not need to worry about detecting circular references + * when reading objects, because we do not dereference any indirect objects. However streams + * are a slight exception in that we do get the Length from the stream dictionay and if that + * is an indirect reference, then we dereference it. + * OSS-fuzz bug 43247 has a stream where the value associated iwht the /Length is an indirect + * reference to the same stream object, and leads to infinite recursion. So deal with that + * possibility here. + */ + code = pdfi_loop_detector_mark(ctx); + if (code < 0) { + pdfi_countdown(stream_obj); /* get rid of extra ref */ + return code; + } + if (pdfi_loop_detector_check_object(ctx, stream_obj->object_num)) + return_error(gs_error_circular_reference); + + code = pdfi_loop_detector_add_object(ctx, stream_obj->object_num); + if (code < 0) { + pdfi_countdown(stream_obj); /* get rid of extra ref */ + return code; + } + /* This code may be a performance overhead, it simply skips over the stream contents * and checks that the stream ends with a 'endstream endobj' pair. We could add a * 'go faster' flag for users who are certain their PDF files are well-formed. This @@ -255,11 +277,17 @@ static int pdfi_read_stream_object(pdf_context *ctx, pdf_c_stream *s, gs_offset_ if (code < 0) { char extra_info[gp_file_name_sizeof]; + (void)pdfi_loop_detector_cleartomark(ctx); gs_sprintf(extra_info, "Stream object %u missing mandatory keyword /Length, unable to verify the stream length.\n", objnum); pdfi_set_error(ctx, 0, NULL, E_PDF_BADSTREAM, "pdfi_read_stream_object", extra_info); pdfi_countdown(stream_obj); /* get rid of extra ref */ return 0; } + code = pdfi_loop_detector_cleartomark(ctx); + if (code < 0) { + pdfi_countdown(stream_obj); /* get rid of extra ref */ + return code; + } if (i < 0 || (i + offset)> ctx->main_stream_length) { char extra_info[gp_file_name_sizeof]; |