From e62d1afec0e9e81971e4f6941a5abbc5c22e8b1f Mon Sep 17 00:00:00 2001 From: Akira Kakuto Date: Fri, 4 Sep 2020 22:48:15 +0000 Subject: Avoid deref-ing an already released object. (S. Hirata) git-svn-id: svn://tug.org/texlive/trunk@56266 c570f23f-e606-0410-a88d-b1316a301751 --- Build/source/texk/dvipdfm-x/ChangeLog | 4 +++ Build/source/texk/dvipdfm-x/pdfdoc.c | 10 +++++- Build/source/texk/dvipdfm-x/pdfobj.c | 62 +++++++++++++++++++++++------------ 3 files changed, 54 insertions(+), 22 deletions(-) diff --git a/Build/source/texk/dvipdfm-x/ChangeLog b/Build/source/texk/dvipdfm-x/ChangeLog index f4197108dbd..31948578624 100644 --- a/Build/source/texk/dvipdfm-x/ChangeLog +++ b/Build/source/texk/dvipdfm-x/ChangeLog @@ -4,6 +4,10 @@ indirect object (object reference) is used for a resource dictionary entry in pdf:put command. The content of an already existing resource dictionary is copied to the new dictionary. + * pdfobj.c, pdfdoc.c: pdf_indirect stores a pointer to the + object itself but there is no way to know if the object is + released. This can result in using junk pointers. To resolve + this issue, a list is added to record released indirect objects. * configure.ac: Version 20200905. 2020-09-02 Shunsaku Hirata diff --git a/Build/source/texk/dvipdfm-x/pdfdoc.c b/Build/source/texk/dvipdfm-x/pdfdoc.c index 443b537818a..a4e96026c8a 100644 --- a/Build/source/texk/dvipdfm-x/pdfdoc.c +++ b/Build/source/texk/dvipdfm-x/pdfdoc.c @@ -513,7 +513,11 @@ pdf_doc_get_page_resources (pdf_doc *p, const char *category) pdf_add_dict(res_dict, pdf_new_name(category), resources); } else if (pdf_obj_typeof(resources) == PDF_INDIRECT) { resources = pdf_deref_obj(resources); /* FIXME: deref_obj increment link count */ - pdf_release_obj(resources); /* FIXME: just to decrement link count */ + if (!resources) { + WARN("Resource %s already released?", category); + } else { + pdf_release_obj(resources); /* FIXME: just to decrement link count */ + } } return resources; @@ -528,6 +532,10 @@ pdf_doc_add_page_resource (const char *category, pdf_obj *duplicate; resources = pdf_doc_get_page_resources(p, category); + if (!resources) { + WARN("Can't add object to resource %s", category); + return; + } duplicate = pdf_lookup_dict(resources, resource_name); if (duplicate) { if (pdf_compare_reference(duplicate, resource_ref)) { diff --git a/Build/source/texk/dvipdfm-x/pdfobj.c b/Build/source/texk/dvipdfm-x/pdfobj.c index 6c90ad861a8..76f2155ec15 100644 --- a/Build/source/texk/dvipdfm-x/pdfobj.c +++ b/Build/source/texk/dvipdfm-x/pdfobj.c @@ -231,6 +231,8 @@ struct pdf_out { pdf_obj *xref_stream; pdf_obj *output_stream; pdf_obj *current_objstm; + + char *free_list; /* 8192bytes each bit representing if the object is freed */ }; #if defined(LIBDPX) @@ -284,11 +286,16 @@ init_pdf_out_struct (pdf_out *p) p->xref_stream = NULL; p->output_stream = NULL; p->current_objstm = NULL; + + p->free_list = NEW(8192, char); + memset(p->free_list, 0, 8192); } static void clean_pdf_out_struct (pdf_out *p) { + if (p->free_list) + RELEASE(p->free_list); memset(p, 0, sizeof(pdf_out)); } @@ -3197,6 +3204,8 @@ release_objstm (pdf_obj *objstm) pdf_release_obj(objstm); } +#define is_free(b,c) (((b)[(c)/8]) & (1 << (7-((c)%8)))) + void pdf_release_obj (pdf_obj *object) { @@ -3221,22 +3230,25 @@ pdf_release_obj (pdf_obj *object) * Nothing is using this object so it's okay to remove it. * Nonzero "label" means object needs to be written before it's destroyed. */ - if (object->label && p->output.file != NULL) { - if (!p->options.use_objstm || object->flags & OBJ_NO_OBJSTM || - (p->options.enable_encrypt && (object->flags & OBJ_NO_ENCRYPT)) || - object->generation) - pdf_flush_obj(p, object); - else { - if (!p->current_objstm) { - int *data = NEW(2*OBJSTM_MAX_OBJS+2, int); - data[0] = data[1] = 0; - p->current_objstm = pdf_new_stream(STREAM_COMPRESS); - set_objstm_data(p->current_objstm, data); - pdf_label_obj(p, p->current_objstm); - } - if (pdf_add_objstm(p, p->current_objstm, object) == OBJSTM_MAX_OBJS) { - release_objstm(p->current_objstm); - p->current_objstm = NULL; + if (object->label) { + p->free_list[object->label/8] |= (1 << (7-(object->label % 8))); + if (p->output.file != NULL) { + if (!p->options.use_objstm || object->flags & OBJ_NO_OBJSTM || + (p->options.enable_encrypt && (object->flags & OBJ_NO_ENCRYPT)) || + object->generation) { + pdf_flush_obj(p, object); + } else { + if (!p->current_objstm) { + int *data = NEW(2*OBJSTM_MAX_OBJS+2, int); + data[0] = data[1] = 0; + p->current_objstm = pdf_new_stream(STREAM_COMPRESS); + set_objstm_data(p->current_objstm, data); + pdf_label_obj(p, p->current_objstm); + } + if (pdf_add_objstm(p, p->current_objstm, object) == OBJSTM_MAX_OBJS) { + release_objstm(p->current_objstm); + p->current_objstm = NULL; + } } } } @@ -3681,12 +3693,20 @@ pdf_deref_obj (pdf_obj *obj) pdf_release_obj(obj); obj = pdf_get_object(pf, obj_num, obj_gen); } else { - pdf_obj *next_obj = OBJ_OBJ(obj); - if (!next_obj) { - ERROR("Undefined object reference"); + pdf_out *p = current_output(); + pdf_indirect *data = obj->data; + + if ((p->free_list[data->label/8] & (1 << (7-((data->label) % 8))))) { + pdf_release_obj(obj); + return NULL; + } else { + pdf_obj *next_obj = OBJ_OBJ(obj); + if (!next_obj) { + ERROR("Undefined object reference"); + } + pdf_release_obj(obj); + obj = pdf_link_obj(next_obj); } - pdf_release_obj(obj); - obj = pdf_link_obj(next_obj); } } -- cgit v1.2.3