summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKen Sharp <ken.sharp@artifex.com>2022-01-13 12:16:29 +0000
committerKen Sharp <ken.sharp@artifex.com>2022-01-13 12:18:30 +0000
commit0d023e9bc705345bd383158a5dc6889f06280a91 (patch)
tree04f4aab7a603f1c04c910afa7026785a009997d2
parent4affbf8fe0e5982058c498a33689cc5182eab0ed (diff)
downloadghostpdl-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.c30
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];