summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'pdf/pdf_obj.c')
-rw-r--r--pdf/pdf_obj.c73
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;
}