From c0b18a7e4fa0d0209daaa3156a9f1390ecd24302 Mon Sep 17 00:00:00 2001 From: Michael R Sweet Date: Wed, 5 May 2021 13:51:42 -0400 Subject: [PATCH] Fix pdfioStringCreate - was returning a char ** instead of a char *, causing crashes/corruption. Optimize dict allocation/sorting. Add more values that are displayed by the testpdfio unit test program. --- pdfio-dict.c | 14 +++++++++----- pdfio-string.c | 17 +++++++++-------- testpdfio.c | 17 +++++++++++++++++ 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/pdfio-dict.c b/pdfio-dict.c index ea24faf..7be3353 100644 --- a/pdfio-dict.c +++ b/pdfio-dict.c @@ -739,6 +739,7 @@ _pdfioDictSetValue( if ((pair = (_pdfio_pair_t *)bsearch(&pkey, dict->pairs, dict->num_pairs, sizeof(_pdfio_pair_t), (int (*)(const void *, const void *))compare_pairs)) != NULL) { // Yes, replace the value... + PDFIO_DEBUG("_pdfioDictSetValue: Replacing existing value.\n"); pair->value = *value; return (true); } @@ -748,13 +749,16 @@ _pdfioDictSetValue( if (dict->num_pairs >= dict->alloc_pairs) { // Expand the dictionary... - _pdfio_pair_t *temp = (_pdfio_pair_t *)realloc(dict->pairs, (dict->alloc_pairs + 16) * sizeof(_pdfio_pair_t)); + _pdfio_pair_t *temp = (_pdfio_pair_t *)realloc(dict->pairs, (dict->alloc_pairs + 8) * sizeof(_pdfio_pair_t)); if (!temp) + { + PDFIO_DEBUG("_pdfioDictSetValue: Out of memory.\n"); return (false); + } dict->pairs = temp; - dict->alloc_pairs += 16; + dict->alloc_pairs += 8; } pair = dict->pairs + dict->num_pairs; @@ -764,7 +768,7 @@ _pdfioDictSetValue( pair->value = *value; // Re-sort the dictionary and return... - if (dict->num_pairs > 1) + if (dict->num_pairs > 1 && compare_pairs(pair - 1, pair) > 0) qsort(dict->pairs, dict->num_pairs, sizeof(_pdfio_pair_t), (int (*)(const void *, const void *))compare_pairs); #ifdef DEBUG @@ -802,11 +806,11 @@ _pdfioDictWrite(pdfio_dict_t *dict, // I - Dictionary if (!_pdfioFilePrintf(pdf, "/%s", pair->key)) return (false); - if (length && !strcmp(pair->key, "Length")) + if (length && !strcmp(pair->key, "Length") && pair->value.type == PDFIO_VALTYPE_NUMBER && pair->value.value.number <= 0.0f) { // Writing an object dictionary with an undefined length *length = _pdfioFileTell(pdf); - if (!_pdfioFilePuts(pdf, " 999999999")) + if (!_pdfioFilePuts(pdf, " 9999999999")) return (false); } else if (!_pdfioValueWrite(pdf, &pair->value)) diff --git a/pdfio-string.c b/pdfio-string.c index 10fa73f..a632619 100644 --- a/pdfio-string.c +++ b/pdfio-string.c @@ -22,7 +22,7 @@ static int compare_strings(char **a, char **b); // -// 'pdfioStringCreate()' - Create a literal string. +// 'pdfioStringCreate()' - Create a durable literal string. // // This function creates a literal string associated with the PDF file // "pwg". The "s" string points to a nul-terminated C string. @@ -31,12 +31,13 @@ static int compare_strings(char **a, char **b); // `pdfioFileClose` is called. // -char * // O - New string or `NULL` on error +char * // O - Durable string pointer or `NULL` on error pdfioStringCreate( pdfio_file_t *pdf, // I - PDF file const char *s) // I - Nul-terminated string { char *news; // New string + char **match; // Matching string PDFIO_DEBUG("pdfioStringCreate(pdf=%p, s=\"%s\")\n", pdf, s); @@ -46,8 +47,8 @@ pdfioStringCreate( return (NULL); // See if the string has already been added... - if (pdf->num_strings > 0 && (news = (char *)bsearch(&s, pdf->strings, pdf->num_strings, sizeof(char *), (int (*)(const void *, const void *))compare_strings)) != NULL) - return (news); + if (pdf->num_strings > 0 && (match = (char **)bsearch(&s, pdf->strings, pdf->num_strings, sizeof(char *), (int (*)(const void *, const void *))compare_strings)) != NULL) + return (*match); // Not already added, so add it... if ((news = strdup(s)) == NULL) @@ -56,7 +57,7 @@ pdfioStringCreate( if (pdf->num_strings >= pdf->alloc_strings) { // Expand the string array... - char **temp = (char **)realloc(pdf->strings, (pdf->alloc_strings + 32) * sizeof(char *)); + char **temp = (char **)realloc(pdf->strings, (pdf->alloc_strings + 128) * sizeof(char *)); if (!temp) { @@ -65,7 +66,7 @@ pdfioStringCreate( } pdf->strings = temp; - pdf->alloc_strings += 32; + pdf->alloc_strings += 128; } // TODO: Change to insertion sort as needed... @@ -89,7 +90,7 @@ pdfioStringCreate( // -// 'pdfioStringCreatef()' - Create a formatted string. +// 'pdfioStringCreatef()' - Create a durable formatted string. // // This function creates a formatted string associated with the PDF file // "pwg". The "format" string contains `printf`-style format characters. @@ -98,7 +99,7 @@ pdfioStringCreate( // `pdfioFileClose` is called. // -char * // O - New string or `NULL` on error +char * // O - Durable string pointer or `NULL` on error pdfioStringCreatef( pdfio_file_t *pdf, // I - PDF file const char *format, // I - `printf`-style format string diff --git a/testpdfio.c b/testpdfio.c index cc2683e..36f8162 100644 --- a/testpdfio.c +++ b/testpdfio.c @@ -65,6 +65,23 @@ main(int argc, // I - Number of command-line arguments case PDFIO_VALTYPE_INDIRECT : printf(" /%s %u %u R\n", pair->key, (unsigned)pair->value.value.indirect.number, pair->value.value.indirect.generation); break; + case PDFIO_VALTYPE_NAME : + printf(" /%s /%s\n", pair->key, pair->value.value.name); + break; + case PDFIO_VALTYPE_STRING : + printf(" /%s (%s)\n", pair->key, pair->value.value.string); + break; + case PDFIO_VALTYPE_BINARY : + { + size_t bn; + unsigned char *bptr; + + printf(" /%s <", pair->key); + for (bn = pair->value.value.binary.datalen, bptr = pair->value.value.binary.data; bn > 0; bn --, bptr ++) + printf("%02X", *bptr); + puts(">"); + } + break; case PDFIO_VALTYPE_NUMBER : printf(" /%s %g\n", pair->key, pair->value.value.number); break;