1
0
mirror of https://github.com/michaelrsweet/pdfio.git synced 2025-04-09 02:16:43 +02:00

Move token buffers off the stack (Issue )

This commit is contained in:
Michael R Sweet 2025-04-04 21:20:23 -04:00
parent fe755eac3d
commit 0bd9edc845
No known key found for this signature in database
GPG Key ID: BE67C75EC81F3244
4 changed files with 170 additions and 35 deletions

@ -110,6 +110,8 @@ pdfioFileClose(pdfio_file_t *pdf) // I - PDF file
{
bool ret = true; // Return value
size_t i; // Looping var
_pdfio_strbuf_t *current, // Current string buffer
*next; // Next string buffer
// Range check input
@ -152,6 +154,12 @@ pdfioFileClose(pdfio_file_t *pdf) // I - PDF file
free(pdf->strings[i]);
free(pdf->strings);
for (current = pdf->strbuffers; current; current = next)
{
next = current->next;
free(current);
}
free(pdf);
return (ret);

@ -225,6 +225,14 @@ typedef struct _pdfio_objmap_s // PDF object map
size_t src_number; // Source object number
} _pdfio_objmap_t;
typedef struct _pdfio_strbuf_s // PDF string buffer
{
struct _pdfio_strbuf_s *next; // Next string buffer
bool bufused; // Is this string buffer being used?
char buffer[PDFIO_MAX_STRING + 32];
// String buffer
} _pdfio_strbuf_t;
struct _pdfio_file_s // PDF file structure
{
char *filename; // Filename
@ -284,6 +292,7 @@ struct _pdfio_file_s // PDF file structure
size_t num_strings, // Number of strings
alloc_strings; // Allocated strings
char **strings; // Nul-terminated strings
_pdfio_strbuf_t *strbuffers; // String buffers
};
struct _pdfio_obj_s // Object
@ -391,6 +400,8 @@ extern bool _pdfioObjWriteHeader(pdfio_obj_t *obj) _PDFIO_INTERNAL;
extern pdfio_stream_t *_pdfioStreamCreate(pdfio_obj_t *obj, pdfio_obj_t *length_obj, size_t cbsize, pdfio_filter_t compression) _PDFIO_INTERNAL;
extern pdfio_stream_t *_pdfioStreamOpen(pdfio_obj_t *obj, bool decode) _PDFIO_INTERNAL;
extern char *_pdfioStringAllocBuffer(pdfio_file_t *pdf);
extern void _pdfioStringFreeBuffer(pdfio_file_t *pdf, char *buffer);
extern bool _pdfioStringIsAllocated(pdfio_file_t *pdf, const char *s) _PDFIO_INTERNAL;
extern void _pdfioTokenClear(_pdfio_token_t *tb) _PDFIO_INTERNAL;

@ -532,6 +532,41 @@ _pdfio_vsnprintf(pdfio_file_t *pdf, // I - PDF file
}
//
// '_pdfioStringAllocBuffer()' - Allocate a string buffer.
//
char * // O - Buffer or `NULL` on error
_pdfioStringAllocBuffer(
pdfio_file_t *pdf) // I - PDF file
{
_pdfio_strbuf_t *current; // Current string buffer
// See if we have an available string buffer...
for (current = pdf->strbuffers; current; current = current->next)
{
if (!current->bufused)
{
current->bufused = true;
return (current->buffer);
}
}
// Didn't find one, allocate a new one...
if ((current = calloc(1, sizeof(_pdfio_strbuf_t))) == NULL)
return (NULL);
// Add to the linked list of string buffers...
current->next = pdf->strbuffers;
current->bufused = true;
pdf->strbuffers = current;
return (current->buffer);
}
//
// 'pdfioStringCreate()' - Create a durable literal string.
//
@ -642,6 +677,29 @@ pdfioStringCreatef(
}
//
// '_pdfioStringFreeBuffer()' - Free a string buffer.
//
void
_pdfioStringFreeBuffer(
pdfio_file_t *pdf, // I - PDF file
char *buffer) // I - String buffer
{
_pdfio_strbuf_t *current; // Current string buffer
for (current = pdf->strbuffers; current; current = current->next)
{
if (current->buffer == buffer)
{
current->bufused = false;
break;
}
}
}
//
// '_pdfioStringIsAllocated()' - Check whether a string has been allocated.
//

@ -125,8 +125,7 @@ _pdfioValueDecrypt(pdfio_file_t *pdf, // I - PDF file
_pdfio_crypto_ctx_t ctx; // Decryption context
_pdfio_crypto_cb_t cb; // Decryption callback
size_t ivlen; // Number of initialization vector bytes
uint8_t temp[PDFIO_MAX_STRING + 32];
// Temporary buffer for decryption
uint8_t *temp = NULL; // Temporary buffer for decryption
size_t templen; // Number of actual data bytes
time_t timeval; // Date/time value
@ -153,11 +152,16 @@ _pdfioValueDecrypt(pdfio_file_t *pdf, // I - PDF file
case PDFIO_VALTYPE_BINARY :
// Decrypt the binary string...
if (v->value.binary.datalen > (sizeof(temp) - 32))
if (v->value.binary.datalen > PDFIO_MAX_STRING)
{
_pdfioFileError(pdf, "Unable to read encrypted binary string - too long.");
return (false);
}
else if ((temp = (uint8_t *)_pdfioStringAllocBuffer(pdf)) == NULL)
{
_pdfioFileError(pdf, "Unable to read encrypted binary string - out of memory.");
return (false);
}
ivlen = v->value.binary.datalen;
if ((cb = _pdfioCryptoMakeReader(pdf, obj, &ctx, v->value.binary.data, &ivlen)) == NULL)
@ -172,6 +176,8 @@ _pdfioValueDecrypt(pdfio_file_t *pdf, // I - PDF file
v->value.binary.datalen = templen - temp[templen - 1];
else
v->value.binary.datalen = templen;
_pdfioStringFreeBuffer(pdf, (char *)temp);
break;
case PDFIO_VALTYPE_STRING :
@ -301,7 +307,9 @@ _pdfioValueRead(pdfio_file_t *pdf, // I - PDF file
_pdfio_value_t *v, // I - Value
size_t depth) // I - Depth of value
{
char token[PDFIO_MAX_STRING];// Token buffer
_pdfio_value_t *ret = NULL; // Return value
char *token = _pdfioStringAllocBuffer(pdf);
// Token buffer
time_t timeval; // Date/time value
#ifdef DEBUG
static const char * const valtypes[] =
@ -323,8 +331,11 @@ _pdfioValueRead(pdfio_file_t *pdf, // I - PDF file
PDFIO_DEBUG("_pdfioValueRead(pdf=%p, obj=%p, v=%p)\n", pdf, obj, v);
if (!_pdfioTokenGet(tb, token, sizeof(token)))
return (NULL);
if (!token)
goto done;
if (!_pdfioTokenGet(tb, token, PDFIO_MAX_STRING))
goto done;
if (!strcmp(token, "["))
{
@ -332,12 +343,14 @@ _pdfioValueRead(pdfio_file_t *pdf, // I - PDF file
if (depth >= PDFIO_MAX_DEPTH)
{
_pdfioFileError(pdf, "Too many nested arrays.");
return (NULL);
goto done;
}
v->type = PDFIO_VALTYPE_ARRAY;
if ((v->value.array = _pdfioArrayRead(pdf, obj, tb, depth + 1)) == NULL)
return (NULL);
goto done;
ret = v;
}
else if (!strcmp(token, "<<"))
{
@ -345,29 +358,34 @@ _pdfioValueRead(pdfio_file_t *pdf, // I - PDF file
if (depth >= PDFIO_MAX_DEPTH)
{
_pdfioFileError(pdf, "Too many nested dictionaries.");
return (NULL);
goto done;
}
v->type = PDFIO_VALTYPE_DICT;
if ((v->value.dict = _pdfioDictRead(pdf, obj, tb, depth + 1)) == NULL)
return (NULL);
goto done;
ret = v;
}
else if ((timeval = get_date_time(token + 1)) != 0)
{
v->type = PDFIO_VALTYPE_DATE;
v->value.date = timeval;
ret = v;
}
else if (token[0] == '(')
{
// String
v->type = PDFIO_VALTYPE_STRING;
v->value.string = pdfioStringCreate(pdf, token + 1);
ret = v;
}
else if (token[0] == '/')
{
// Name
v->type = PDFIO_VALTYPE_NAME;
v->value.name = pdfioStringCreate(pdf, token + 1);
ret = v;
}
else if (token[0] == '<')
{
@ -380,7 +398,7 @@ _pdfioValueRead(pdfio_file_t *pdf, // I - PDF file
if ((v->value.binary.data = (unsigned char *)malloc(v->value.binary.datalen)) == NULL)
{
_pdfioFileError(pdf, "Out of memory for hex string.");
return (NULL);
goto done;
}
// Convert hex to binary...
@ -407,6 +425,8 @@ _pdfioValueRead(pdfio_file_t *pdf, // I - PDF file
*dataptr++ = (unsigned char)d;
}
ret = v;
}
else if (strchr("0123456789-+.", token[0]) != NULL)
{
@ -494,7 +514,8 @@ _pdfioValueRead(pdfio_file_t *pdf, // I - PDF file
PDFIO_DEBUG("_pdfioValueRead: Returning indirect value %lu %u R.\n", (unsigned long)v->value.indirect.number, v->value.indirect.generation);
return (v);
ret = v;
goto done;
}
}
}
@ -502,27 +523,41 @@ _pdfioValueRead(pdfio_file_t *pdf, // I - PDF file
// If we get here, we have a number...
v->type = PDFIO_VALTYPE_NUMBER;
v->value.number = _pdfio_strtod(pdf, token);
ret = v;
}
else if (!strcmp(token, "true") || !strcmp(token, "false"))
{
// Boolean value
v->type = PDFIO_VALTYPE_BOOLEAN;
v->value.boolean = !strcmp(token, "true");
ret = v;
}
else if (!strcmp(token, "null"))
{
// null value
v->type = PDFIO_VALTYPE_NULL;
ret = v;
}
else
{
_pdfioFileError(pdf, "Unexpected '%s' token seen.", token);
return (NULL);
}
PDFIO_DEBUG("_pdfioValueRead: Returning %s value.\n", valtypes[v->type]);
done:
return (v);
if (token)
_pdfioStringFreeBuffer(pdf, token);
if (ret)
{
PDFIO_DEBUG("_pdfioValueRead: Returning %s value.\n", valtypes[ret->type]);
return (ret);
}
else
{
PDFIO_DEBUG("_pdfioValueRead: Returning NULL.\n");
return (NULL);
}
}
@ -547,9 +582,10 @@ _pdfioValueWrite(pdfio_file_t *pdf, // I - PDF file
case PDFIO_VALTYPE_BINARY :
{
size_t databytes; // Bytes to write
uint8_t temp[PDFIO_MAX_STRING + 32],
// Temporary buffer for encryption
uint8_t *temp = NULL, // Temporary buffer for encryption
*dataptr; // Pointer into data
bool ret = false; // Return value
if (obj && pdf->encryption)
{
@ -558,11 +594,16 @@ _pdfioValueWrite(pdfio_file_t *pdf, // I - PDF file
_pdfio_crypto_cb_t cb; // Encryption callback
size_t ivlen; // Number of initialization vector bytes
if (v->value.binary.datalen > (sizeof(temp) - 32))
if (v->value.binary.datalen > PDFIO_MAX_STRING)
{
_pdfioFileError(pdf, "Unable to write encrypted binary string - too long.");
return (false);
}
else if ((temp = (uint8_t *)_pdfioStringAllocBuffer(pdf)) == NULL)
{
_pdfioFileError(pdf, "Unable to write encrypted binary string - out of memory.");
return (false);
}
cb = _pdfioCryptoMakeWriter(pdf, obj, &ctx, temp, &ivlen);
databytes = (cb)(&ctx, temp + ivlen, v->value.binary.data, v->value.binary.datalen) + ivlen;
@ -575,18 +616,25 @@ _pdfioValueWrite(pdfio_file_t *pdf, // I - PDF file
}
if (!_pdfioFilePuts(pdf, "<"))
return (false);
goto bindone;
for (; databytes > 1; databytes -= 2, dataptr += 2)
{
if (!_pdfioFilePrintf(pdf, "%02X%02X", dataptr[0], dataptr[1]))
return (false);
goto bindone;
}
if (databytes > 0)
return (_pdfioFilePrintf(pdf, "%02X>", dataptr[0]));
else
return (_pdfioFilePuts(pdf, ">"));
if (databytes > 0 && !_pdfioFilePrintf(pdf, "%02X", dataptr[0]))
goto bindone;
ret = _pdfioFilePuts(pdf, ">");
bindone:
if (temp)
_pdfioStringFreeBuffer(pdf, (char *)temp);
return (ret);
}
case PDFIO_VALTYPE_BOOLEAN :
@ -611,8 +659,7 @@ _pdfioValueWrite(pdfio_file_t *pdf, // I - PDF file
if (obj && pdf->encryption)
{
// Write encrypted string...
uint8_t temp[PDFIO_MAX_STRING + 32],
// Encrypted bytes
uint8_t temp[64], // Encrypted bytes
*tempptr; // Pointer into encrypted bytes
_pdfio_crypto_ctx_t ctx; // Encryption context
_pdfio_crypto_cb_t cb; // Encryption callback
@ -663,8 +710,7 @@ _pdfioValueWrite(pdfio_file_t *pdf, // I - PDF file
if (obj && pdf->encryption)
{
// Write encrypted string...
uint8_t temp[PDFIO_MAX_STRING + 32],
// Encrypted bytes
uint8_t *temp = NULL, // Encrypted bytes
*tempptr; // Pointer into encrypted bytes
_pdfio_crypto_ctx_t ctx; // Encryption context
_pdfio_crypto_cb_t cb; // Encryption callback
@ -672,29 +718,41 @@ _pdfioValueWrite(pdfio_file_t *pdf, // I - PDF file
// Length of value
ivlen, // Number of initialization vector bytes
tempbytes; // Number of output bytes
bool ret = false; // Return value
if (len > (sizeof(temp) - 32))
if (len > PDFIO_MAX_STRING)
{
_pdfioFileError(pdf, "Unable to write encrypted string - too long.");
return (false);
}
else if ((temp = (uint8_t *)_pdfioStringAllocBuffer(pdf)) == NULL)
{
_pdfioFileError(pdf, "Unable to write encrypted string - out of memory.");
return (false);
}
cb = _pdfioCryptoMakeWriter(pdf, obj, &ctx, temp, &ivlen);
tempbytes = (cb)(&ctx, temp + ivlen, (const uint8_t *)v->value.string, len) + ivlen;
if (!_pdfioFilePuts(pdf, "<"))
return (false);
goto strdone;
for (tempptr = temp; tempbytes > 1; tempbytes -= 2, tempptr += 2)
{
if (!_pdfioFilePrintf(pdf, "%02X%02X", tempptr[0], tempptr[1]))
return (false);
goto strdone;
}
if (tempbytes > 0)
return (_pdfioFilePrintf(pdf, "%02X>", *tempptr));
else
return (_pdfioFilePuts(pdf, ">"));
if (tempbytes > 0 && !_pdfioFilePrintf(pdf, "%02X", *tempptr))
goto strdone;
ret = _pdfioFilePuts(pdf, ">");
strdone :
_pdfioStringFreeBuffer(pdf, (char *)temp);
return (ret);
}
else
{