summaryrefslogtreecommitdiff
path: root/psi
diff options
context:
space:
mode:
authorKen Sharp <ken.sharp@artifex.com>2022-08-02 13:58:55 +0100
committerKen Sharp <ken.sharp@artifex.com>2022-08-02 13:58:55 +0100
commit04e351b71856d10c44b3977efbb6b14e8f88f0dc (patch)
treee25330b5f065fc485f29915233f91a3d37335052 /psi
parent1dc1ac2e70b675c0fe17adf8799b2290426f7478 (diff)
downloadghostpdl-04e351b71856d10c44b3977efbb6b14e8f88f0dc.tar.gz
GhostPDF - yet more circular references in Info dictionaries
OSS-fuzz #49703 OSS-fuzz finds another way to evade the circular reference checking on the Info dictionary, this time by having Annots point to the Pages tree instead of the Page, **and** having the Info dictionary point to the first Page dictionary. I was going to dump anything except names and strings from the dictionary, forgetting that we use the same mechanism for returning the Page dictionary, and we need to have that able to deal with arrays at least, for the various Boxes. So add yet more checking to the contents of the PDF object we are being asked to turn into a PostScript object.
Diffstat (limited to 'psi')
-rw-r--r--psi/zpdfops.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/psi/zpdfops.c b/psi/zpdfops.c
index 50b8b1b5a..5d06b7931 100644
--- a/psi/zpdfops.c
+++ b/psi/zpdfops.c
@@ -631,6 +631,46 @@ static int zPDFclose(i_ctx_t *i_ctx_p)
static int PDFobj_to_PSobj(i_ctx_t *i_ctx_p, pdfctx_t *pdfctx, pdf_obj *PDFobj, ref *PSobj);
+static void debug_pdfobj(i_ctx_t *i_ctx_p, pdfctx_t *pdfctx, pdf_obj *PDFobj)
+{
+ char *str = NULL;
+ int code = 0, len = 0;
+
+ switch(pdfi_type_of(PDFobj)) {
+ case PDF_NAME:
+ code = pdfi_string_from_name(pdfctx->ctx, (pdf_name *)PDFobj, &str, &len);
+ if (code < 0)
+ return;
+ dbgprintf1("/%s ", str);
+ (void)pdfi_free_string_from_name(pdfctx->ctx, str);
+ break;
+ case PDF_STRING:
+ str = (char *)gs_alloc_bytes(pdfctx->ctx->memory, ((pdf_string *)PDFobj)->length + 1, "");
+ if (str == NULL)
+ return;
+ memset(str, 0x00, ((pdf_string *)PDFobj)->length + 1);
+ memcpy(str, ((pdf_string *)PDFobj)->data, ((pdf_string *)PDFobj)->length);
+ dbgprintf1("/%s ", str);
+ gs_free_object(pdfctx->ctx->memory, str, "");
+ break;
+ case PDF_INT:
+ dbgprintf1("/%d ", ((pdf_num *)PDFobj)->value.i);
+ break;
+ case PDF_REAL:
+ dbgprintf1("/%f ", ((pdf_num *)PDFobj)->value.d);
+ break;
+ break;
+ case PDF_BOOL:
+ if (PDFobj == PDF_TRUE_OBJ)
+ dbgprintf("true ");
+ else
+ dbgprintf("false ");
+ break;
+ default:
+ break;
+ }
+}
+
static int PDFdict_to_PSdict(i_ctx_t *i_ctx_p, pdfctx_t *pdfctx, pdf_dict *PDFdict, ref *PSdict)
{
int code = 0;
@@ -660,6 +700,8 @@ static int PDFdict_to_PSdict(i_ctx_t *i_ctx_p, pdfctx_t *pdfctx, pdf_dict *PDFdi
if (code < 0)
goto error;
+ debug_pdfobj(i_ctx_p, pdfctx, (pdf_obj *)Key);
+
code = names_ref(imemory->gs_lib_ctx->gs_name_table, (const byte *)str, len, &nameref, 1);
if (code < 0)
goto error;
@@ -672,6 +714,7 @@ static int PDFdict_to_PSdict(i_ctx_t *i_ctx_p, pdfctx_t *pdfctx, pdf_dict *PDFdi
if (code < 0)
goto error;
+ dbgprintf("\n");
pdfi_countdown(Key);
pdfi_countdown(Value);
Key = NULL;
@@ -752,6 +795,8 @@ static int PDFobj_to_PSobj(i_ctx_t *i_ctx_p, pdfctx_t *pdfctx, pdf_obj *PDFobj,
if (code < 0)
goto error;
+ debug_pdfobj(i_ctx_p, pdfctx, PDFobj);
+
switch(pdfi_type_of(PDFobj)) {
case PDF_NAME:
{
@@ -806,10 +851,26 @@ static int PDFobj_to_PSobj(i_ctx_t *i_ctx_p, pdfctx_t *pdfctx, pdf_obj *PDFobj,
}
break;
case PDF_DICT:
+ code = pdfi_loop_detector_mark(pdfctx->ctx);
+ if (code < 0)
+ goto error;
+ if (PDFobj->object_num != 0)
+ pdfi_loop_detector_add_object(pdfctx->ctx, PDFobj->object_num);
+ dbgprintf("<<\n");
code = PDFdict_to_PSdict(i_ctx_p, pdfctx, (pdf_dict *)PDFobj, PSobj);
+ dbgprintf(">>\n");
+ pdfi_loop_detector_cleartomark(pdfctx->ctx);
break;
case PDF_ARRAY:
+ code = pdfi_loop_detector_mark(pdfctx->ctx);
+ if (code < 0)
+ goto error;
+ if (PDFobj->object_num != 0)
+ pdfi_loop_detector_add_object(pdfctx->ctx, PDFobj->object_num);
+ dbgprintf("[ ");
code = PDFarray_to_PSarray(i_ctx_p, pdfctx, (pdf_array *)PDFobj, PSobj);
+ dbgprintf("]\n");
+ pdfi_loop_detector_cleartomark(pdfctx->ctx);
break;
default:
make_null(PSobj);