diff options
Diffstat (limited to 'pdf/pdf_obj.c')
-rw-r--r-- | pdf/pdf_obj.c | 73 |
1 files changed, 38 insertions, 35 deletions
diff --git a/pdf/pdf_obj.c b/pdf/pdf_obj.c index 931f2137..58bd59b0 100644 --- a/pdf/pdf_obj.c +++ b/pdf/pdf_obj.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 @@ -23,6 +23,7 @@ #include "pdf_deref.h" /* for replace_cache_entry() */ #include "pdf_mark.h" #include "pdf_file.h" /* for pdfi_stream_to_buffer() */ +#include "pdf_loop_detect.h" /***********************************************************************************/ /* Functions to create the various kinds of 'PDF objects', Created objects have a */ @@ -49,7 +50,7 @@ int pdfi_object_alloc(pdf_context *ctx, pdf_obj_type type, unsigned int size, pd break; case PDF_STRING: case PDF_NAME: - bytes = sizeof(pdf_string); + bytes = sizeof(pdf_string) + size - sizeof(PDF_NAME_DECLARED_LENGTH); break; case PDF_ARRAY: bytes = sizeof(pdf_array); @@ -64,7 +65,7 @@ int pdfi_object_alloc(pdf_context *ctx, pdf_obj_type type, unsigned int size, pd bytes = sizeof(pdf_bool); break; case PDF_KEYWORD: - bytes = sizeof(pdf_keyword); + bytes = sizeof(pdf_keyword) + size - sizeof(PDF_NAME_DECLARED_LENGTH); break; /* The following aren't PDF object types, but are objects we either want to * reference count, or store on the stack. @@ -99,17 +100,7 @@ int pdfi_object_alloc(pdf_context *ctx, pdf_obj_type type, unsigned int size, pd case PDF_KEYWORD: case PDF_STRING: case PDF_NAME: - { - unsigned char *data = NULL; - data = (unsigned char *)gs_alloc_bytes(ctx->memory, size, "pdfi_object_alloc"); - if (data == NULL) { - gs_free_object(ctx->memory, *obj, "pdfi_object_alloc"); - *obj = NULL; - return_error(gs_error_VMerror); - } - ((pdf_string *)*obj)->data = data; - ((pdf_string *)*obj)->length = size; - } + ((pdf_string *)*obj)->length = size; break; case PDF_ARRAY: { @@ -131,23 +122,18 @@ int pdfi_object_alloc(pdf_context *ctx, pdf_obj_type type, unsigned int size, pd break; case PDF_DICT: { - pdf_obj **keys = NULL, **values = NULL; + pdf_dict_entry *entries = NULL; ((pdf_dict *)*obj)->size = size; if (size > 0) { - keys = (pdf_obj **)gs_alloc_bytes(ctx->memory, size * sizeof(pdf_obj *), "pdfi_object_alloc"); - values = (pdf_obj **)gs_alloc_bytes(ctx->memory, size * sizeof(pdf_obj *), "pdfi_object_alloc"); - if (keys == NULL || values == NULL) { + entries = (pdf_dict_entry *)gs_alloc_bytes(ctx->memory, size * sizeof(pdf_dict_entry), "pdfi_object_alloc"); + if (entries == NULL) { gs_free_object(ctx->memory, *obj, "pdfi_object_alloc"); - gs_free_object(ctx->memory, keys, "pdfi_object_alloc"); - gs_free_object(ctx->memory, values, "pdfi_object_alloc"); *obj = NULL; return_error(gs_error_VMerror); } - ((pdf_dict *)*obj)->values = values; - ((pdf_dict *)*obj)->keys = keys; - memset(((pdf_dict *)*obj)->values, 0x00, size * sizeof(pdf_obj *)); - memset(((pdf_dict *)*obj)->keys, 0x00, size * sizeof(pdf_obj *)); + ((pdf_dict *)*obj)->list = entries; + memset(((pdf_dict *)*obj)->list, 0x00, size * sizeof(pdf_dict_entry)); } } break; @@ -160,7 +146,7 @@ int pdfi_object_alloc(pdf_context *ctx, pdf_obj_type type, unsigned int size, pd break; } #if REFCNT_DEBUG - (*obj)->UID = ctx->UID++; + (*obj)->UID = ctx->ref_UID++; dmprintf2(ctx->memory, "Allocated object of type %c with UID %"PRIi64"\n", (*obj)->type, (*obj)->UID); #endif return 0; @@ -205,18 +191,13 @@ static void pdfi_free_namestring(pdf_obj *o) /* Currently names and strings are the same, so a single cast is OK */ pdf_name *n = (pdf_name *)o; - if (n->data != NULL) - gs_free_object(OBJ_MEMORY(n), n->data, "pdf interpreter free name or string data"); gs_free_object(OBJ_MEMORY(n), n, "pdf interpreter free name or string"); } static void pdfi_free_keyword(pdf_obj *o) { - /* Currently names and strings are the same, so a single cast is OK */ pdf_keyword *k = (pdf_keyword *)o; - if (k->data != NULL) - gs_free_object(OBJ_MEMORY(k), k->data, "pdf interpreter free keyword data"); gs_free_object(OBJ_MEMORY(k), k, "pdf interpreter free keyword"); } @@ -238,6 +219,8 @@ static void pdfi_free_stream(pdf_obj *o) void pdfi_free_object(pdf_obj *o) { + if (o == NULL) + return; switch(o->type) { case PDF_ARRAY_MARK: case PDF_DICT_MARK: @@ -540,7 +523,7 @@ static int pdfi_obj_int_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *le buf = (char *)gs_alloc_bytes(ctx->memory, size, "pdfi_obj_int_str(data)"); if (buf == NULL) return_error(gs_error_VMerror); - snprintf(buf, size, "%ld", number->value.i); + snprintf(buf, size, "%"PRId64"", number->value.i); *data = (byte *)buf; *len = strlen(buf); return code; @@ -554,7 +537,7 @@ static int pdfi_obj_getrefstr(pdf_context *ctx, uint64_t object_num, uint32_t ge buf = (char *)gs_alloc_bytes(ctx->memory, size, "pdfi_obj_getrefstr(data)"); if (buf == NULL) return_error(gs_error_VMerror); - snprintf(buf, size, "%ld %d R", object_num, generation); + snprintf(buf, size, "%"PRId64" %d R", object_num, generation); *data = (byte *)buf; *len = strlen(buf); return 0; @@ -573,7 +556,7 @@ static int pdfi_obj_indirect_str(pdf_context *ctx, pdf_obj *obj, byte **data, in ref->is_highlevelform = false; } else { if (!ref->is_marking) { - code = pdfi_dereference(ctx, ref->ref_object_num, ref->ref_generation_num, &object); + code = pdfi_deref_loop_detect(ctx, ref->ref_object_num, ref->ref_generation_num, &object); if (code == gs_error_undefined) { /* Do something sensible for undefined reference (this would be a broken file) */ /* TODO: Flag an error? */ @@ -584,10 +567,10 @@ static int pdfi_obj_indirect_str(pdf_context *ctx, pdf_obj *obj, byte **data, in goto exit; if (code == 0) { if (object->type == PDF_STREAM) { - code = pdfi_mark_stream(ctx, (pdf_stream *)object); + code = pdfi_pdfmark_stream(ctx, (pdf_stream *)object); if (code < 0) goto exit; } else if (object->type == PDF_DICT) { - code = pdfi_mark_dict(ctx, (pdf_dict *)object); + code = pdfi_pdfmark_dict(ctx, (pdf_dict *)object); if (code < 0) goto exit; } else { code = pdfi_obj_to_string(ctx, object, data, len); @@ -833,6 +816,10 @@ static int pdfi_obj_dict_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *l uint64_t index, dictsize; uint64_t itemnum = 0; + code = pdfi_loop_detector_mark(ctx); + if (code < 0) + return code; + code = pdfi_bufstream_init(ctx, &bufstream); if (code < 0) goto exit; @@ -851,6 +838,18 @@ static int pdfi_obj_dict_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *l /* Note: We specifically fetch without dereferencing, so there will be no circular * references to handle here. */ + /* Wrong.... */ + + if (dict->object_num !=0 ) { + if (pdfi_loop_detector_check_object(ctx, dict->object_num)) { + code = gs_note_error(gs_error_circular_reference); + goto exit; + } + code = pdfi_loop_detector_add_object(ctx, dict->object_num); + if (code < 0) + goto exit; + } + /* Get each (key,val) pair from dict and setup param for it */ code = pdfi_dict_key_first(ctx, dict, (pdf_obj **)&Key, &index); while (code >= 0) { @@ -914,6 +913,10 @@ static int pdfi_obj_dict_str(pdf_context *ctx, pdf_obj *obj, byte **data, int *l pdfi_countdown(Key); pdfi_countdown(Value); pdfi_bufstream_free(ctx, &bufstream); + if (code < 0) + (void)pdfi_loop_detector_cleartomark(ctx); + else + code = pdfi_loop_detector_cleartomark(ctx); return code; } |