Fix sporadic test suite failures caused by greedy whitespace removal in token

reader.

Update read code to handle signal/temporary failures.

Add some more useful debug messages for the encryption code.

Eliminate more warnings from Clang.
This commit is contained in:
Michael R Sweet 2021-10-31 11:12:54 -04:00
parent 9d121335f5
commit 6432187dea
No known key found for this signature in database
GPG Key ID: BE67C75EC81F3244
4 changed files with 72 additions and 33 deletions

View File

@ -329,6 +329,11 @@ _pdfioFileRead(pdfio_file_t *pdf, // I - PDF file
pdf->bufpos += rbytes; pdf->bufpos += rbytes;
continue; continue;
} }
else if (rbytes < 0 && (errno == EINTR || errno == EAGAIN))
{
rbytes = 0;
continue;
}
else else
break; break;
} }

View File

@ -104,7 +104,7 @@ static void decrypt_user_key(pdfio_encryption_t encryption, const uint8_t *file_
static void encrypt_user_key(pdfio_encryption_t encryption, const uint8_t *file_key, uint8_t user_key[32]); static void encrypt_user_key(pdfio_encryption_t encryption, const uint8_t *file_key, uint8_t user_key[32]);
static void make_file_key(pdfio_encryption_t encryption, pdfio_permission_t permissions, const unsigned char *file_id, size_t file_idlen, const uint8_t *user_pad, const uint8_t *owner_key, uint8_t file_key[16]); static void make_file_key(pdfio_encryption_t encryption, pdfio_permission_t permissions, const unsigned char *file_id, size_t file_idlen, const uint8_t *user_pad, const uint8_t *owner_key, uint8_t file_key[16]);
static void make_owner_key(pdfio_encryption_t encryption, const uint8_t *owner_pad, const uint8_t *user_pad, uint8_t owner_key[32]); static void make_owner_key(pdfio_encryption_t encryption, const uint8_t *owner_pad, const uint8_t *user_pad, uint8_t owner_key[32]);
static void make_user_key(pdfio_encryption_t encryption, const unsigned char *file_id, size_t file_idlen, uint8_t user_key[32]); static void make_user_key(const unsigned char *file_id, size_t file_idlen, uint8_t user_key[32]);
static void pad_password(const char *password, uint8_t pad[32]); static void pad_password(const char *password, uint8_t pad[32]);
@ -166,7 +166,7 @@ _pdfioCryptoLock(
pdf->file_keylen = 16; pdf->file_keylen = 16;
// Generate the user key... // Generate the user key...
make_user_key(encryption, file_id, file_idlen, pdf->user_key); make_user_key(file_id, file_idlen, pdf->user_key);
encrypt_user_key(encryption, pdf->file_key, pdf->user_key); encrypt_user_key(encryption, pdf->file_key, pdf->user_key);
pdf->user_keylen = 32; pdf->user_keylen = 32;
@ -415,6 +415,8 @@ _pdfio_crypto_cb_t // O - Decryption callback or `NULL` for none
uint8_t digest[16]; /* MD5 digest value */ uint8_t digest[16]; /* MD5 digest value */
PDFIO_DEBUG("_pdfioCryptoMakeReader(pdf=%p, obj=%p(%d), ctx=%p, iv=%p, ivlen=%p(%d))\n", pdf, obj, (int)obj->number, ctx, iv, ivlen, (int)*ivlen);
// Range check input... // Range check input...
if (!pdf) if (!pdf)
{ {
@ -479,6 +481,8 @@ _pdfio_crypto_cb_t // O - Encryption callback or `NULL` for none
uint8_t digest[16]; /* MD5 digest value */ uint8_t digest[16]; /* MD5 digest value */
PDFIO_DEBUG("_pdfioCryptoMakeWriter(pdf=%p, obj=%p(%d), ctx=%p, iv=%p, ivlen=%p(%d))\n", pdf, obj, (int)obj->number, ctx, iv, ivlen, (int)*ivlen);
// Range check input... // Range check input...
if (!pdf) if (!pdf)
{ {
@ -569,9 +573,6 @@ _pdfioCryptoUnlock(
version = (int)pdfioDictGetNumber(encrypt_dict, "V"); version = (int)pdfioDictGetNumber(encrypt_dict, "V");
revision = (int)pdfioDictGetNumber(encrypt_dict, "R"); revision = (int)pdfioDictGetNumber(encrypt_dict, "R");
length = (int)pdfioDictGetNumber(encrypt_dict, "Length"); length = (int)pdfioDictGetNumber(encrypt_dict, "Length");
stream_filter = pdfioDictGetName(encrypt_dict, "StmF");
string_filter = pdfioDictGetName(encrypt_dict, "StrF");
cf_dict = pdfioDictGetDict(encrypt_dict, "CF");
if (!handler || strcmp(handler, "Standard")) if (!handler || strcmp(handler, "Standard"))
{ {
@ -585,7 +586,41 @@ _pdfioCryptoUnlock(
pdfio_dict_t *filter; // Crypt Filter pdfio_dict_t *filter; // Crypt Filter
const char *cfm; // Crypt filter method const char *cfm; // Crypt filter method
if ((filter = pdfioDictGetDict(cf_dict, stream_filter)) != NULL && (cfm = pdfioDictGetName(filter, "CFM")) != NULL) stream_filter = pdfioDictGetName(encrypt_dict, "StmF");
string_filter = pdfioDictGetName(encrypt_dict, "StrF");
cf_dict = pdfioDictGetDict(encrypt_dict, "CF");
if (!cf_dict)
{
_pdfioFileError(pdf, "Missing encryption filter dictionary.");
return (false);
}
else if (!stream_filter)
{
_pdfioFileError(pdf, "Missing stream encryption filter.");
return (false);
}
else if (!string_filter)
{
_pdfioFileError(pdf, "Missing string encryption filter.");
return (false);
}
else if (strcmp(stream_filter, string_filter))
{
_pdfioFileError(pdf, "Different stream and string encryption filters - not supported.");
return (false);
}
else if ((filter = pdfioDictGetDict(cf_dict, stream_filter)) == NULL)
{
_pdfioFileError(pdf, "Missing stream encryption filter '%s'.", stream_filter);
return (false);
}
else if ((cfm = pdfioDictGetName(filter, "CFM")) == NULL)
{
_pdfioFileError(pdf, "Missing encryption filter method.");
return (false);
}
else
{ {
if (!strcmp(cfm, "V2")) if (!strcmp(cfm, "V2"))
{ {
@ -623,7 +658,7 @@ _pdfioCryptoUnlock(
} }
// Grab the remaining values we need to unlock the PDF... // Grab the remaining values we need to unlock the PDF...
pdf->file_keylen = length / 8; pdf->file_keylen = (size_t)(length / 8);
pdf->permissions = (pdfio_permission_t)pdfioDictGetNumber(encrypt_dict, "P"); pdf->permissions = (pdfio_permission_t)pdfioDictGetNumber(encrypt_dict, "P");
owner_key = pdfioDictGetBinary(encrypt_dict, "O", &owner_keylen); owner_key = pdfioDictGetBinary(encrypt_dict, "O", &owner_keylen);
@ -667,7 +702,7 @@ _pdfioCryptoUnlock(
uint8_t pad[32], // Padded password uint8_t pad[32], // Padded password
file_key[16], // File key file_key[16], // File key
user_pad[32], // Padded user password user_pad[32], // Padded user password
user_key[32], // User key own_user_key[32], // Calculated user key
pdf_user_key[32]; // Decrypted user key pdf_user_key[32]; // Decrypted user key
// Pad the supplied password, if any... // Pad the supplied password, if any...
@ -684,12 +719,12 @@ _pdfioCryptoUnlock(
make_file_key(pdf->encryption, pdf->permissions, file_id, file_idlen, user_pad, pdf->owner_key, file_key); make_file_key(pdf->encryption, pdf->permissions, file_id, file_idlen, user_pad, pdf->owner_key, file_key);
PDFIO_DEBUG("Fown=%02X%02X%02X%02X...%02X%02X%02X%02X\n", file_key[0], file_key[1], file_key[2], file_key[3], file_key[12], file_key[13], file_key[14], file_key[15]); PDFIO_DEBUG("Fown=%02X%02X%02X%02X...%02X%02X%02X%02X\n", file_key[0], file_key[1], file_key[2], file_key[3], file_key[12], file_key[13], file_key[14], file_key[15]);
make_user_key(pdf->encryption, file_id, file_idlen, user_key); make_user_key(file_id, file_idlen, own_user_key);
PDFIO_DEBUG("U=%02X%02X%02X%02X...%02X%02X%02X%02X\n", pdf->user_key[0], pdf->user_key[1], pdf->user_key[2], pdf->user_key[3], pdf->user_key[28], pdf->user_key[29], pdf->user_key[30], pdf->user_key[31]); PDFIO_DEBUG("U=%02X%02X%02X%02X...%02X%02X%02X%02X\n", pdf->user_key[0], pdf->user_key[1], pdf->user_key[2], pdf->user_key[3], pdf->user_key[28], pdf->user_key[29], pdf->user_key[30], pdf->user_key[31]);
PDFIO_DEBUG("Uown=%02X%02X%02X%02X...%02X%02X%02X%02X\n", user_key[0], user_key[1], user_key[2], user_key[3], user_key[28], user_key[29], user_key[30], user_key[31]); PDFIO_DEBUG("Uown=%02X%02X%02X%02X...%02X%02X%02X%02X\n", own_user_key[0], own_user_key[1], own_user_key[2], own_user_key[3], own_user_key[28], own_user_key[29], own_user_key[30], own_user_key[31]);
if (!memcmp(user_key, pdf->user_key, sizeof(user_key))) if (!memcmp(own_user_key, pdf->user_key, sizeof(own_user_key)))
{ {
// Matches! // Matches!
memcpy(pdf->file_key, file_key, sizeof(pdf->file_key)); memcpy(pdf->file_key, file_key, sizeof(pdf->file_key));
@ -703,7 +738,7 @@ _pdfioCryptoUnlock(
make_file_key(pdf->encryption, pdf->permissions, file_id, file_idlen, pad, pdf->owner_key, file_key); make_file_key(pdf->encryption, pdf->permissions, file_id, file_idlen, pad, pdf->owner_key, file_key);
PDFIO_DEBUG("Fuse=%02X%02X%02X%02X...%02X%02X%02X%02X\n", file_key[0], file_key[1], file_key[2], file_key[3], file_key[12], file_key[13], file_key[14], file_key[15]); PDFIO_DEBUG("Fuse=%02X%02X%02X%02X...%02X%02X%02X%02X\n", file_key[0], file_key[1], file_key[2], file_key[3], file_key[12], file_key[13], file_key[14], file_key[15]);
make_user_key(pdf->encryption, file_id, file_idlen, user_key); make_user_key(file_id, file_idlen, user_key);
memcpy(pdf_user_key, pdf->user_key, sizeof(pdf_user_key)); memcpy(pdf_user_key, pdf->user_key, sizeof(pdf_user_key));
decrypt_user_key(pdf->encryption, file_key, pdf_user_key); decrypt_user_key(pdf->encryption, file_key, pdf_user_key);
@ -928,7 +963,6 @@ make_owner_key(
static void static void
make_user_key( make_user_key(
pdfio_encryption_t encryption, // I - Type of encryption
const unsigned char *file_id, // I - File ID value const unsigned char *file_id, // I - File ID value
size_t file_idlen, // I - Length of file ID size_t file_idlen, // I - Length of file ID
uint8_t user_key[32]) // O - User key uint8_t user_key[32]) // O - User key

View File

@ -68,7 +68,7 @@ pdfioStreamClose(pdfio_stream_t *st) // I - Stream
if (st->crypto_cb) if (st->crypto_cb)
{ {
// Encrypt it first... // Encrypt it first...
outbytes = (st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, bytes & ~15); outbytes = (st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, bytes & (size_t)~15);
} }
else else
{ {
@ -93,7 +93,7 @@ pdfioStreamClose(pdfio_stream_t *st) // I - Stream
} }
st->flate.next_out = (Bytef *)st->cbuffer + bytes; st->flate.next_out = (Bytef *)st->cbuffer + bytes;
st->flate.avail_out = (uInt)sizeof(st->cbuffer) - bytes; st->flate.avail_out = (uInt)(sizeof(st->cbuffer) - bytes);
} }
if (st->flate.avail_out < (uInt)sizeof(st->cbuffer)) if (st->flate.avail_out < (uInt)sizeof(st->cbuffer))
@ -430,7 +430,7 @@ _pdfioStreamOpen(pdfio_obj_t *obj, // I - Object
uint8_t iv[64]; // Initialization vector uint8_t iv[64]; // Initialization vector
size_t ivlen; // Length of initialization vector, if any size_t ivlen; // Length of initialization vector, if any
ivlen = _pdfioFilePeek(st->pdf, iv, sizeof(iv)); ivlen = (size_t)_pdfioFilePeek(st->pdf, iv, sizeof(iv));
if ((st->crypto_cb = _pdfioCryptoMakeReader(st->pdf, obj, &st->crypto_ctx, iv, &ivlen)) == NULL) if ((st->crypto_cb = _pdfioCryptoMakeReader(st->pdf, obj, &st->crypto_ctx, iv, &ivlen)) == NULL)
{ {
@ -441,6 +441,9 @@ _pdfioStreamOpen(pdfio_obj_t *obj, // I - Object
if (ivlen > 0) if (ivlen > 0)
_pdfioFileConsume(st->pdf, ivlen); _pdfioFileConsume(st->pdf, ivlen);
if (st->pdf->encryption >= PDFIO_ENCRYPTION_AES_128)
st->remaining = (st->remaining + 15) & (size_t)~15;
} }
if (decode) if (decode)
@ -558,7 +561,7 @@ _pdfioStreamOpen(pdfio_obj_t *obj, // I - Object
} }
if (st->crypto_cb) if (st->crypto_cb)
rbytes = (st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, rbytes); rbytes = (ssize_t)(st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, (size_t)rbytes);
st->flate.next_in = (Bytef *)st->cbuffer; st->flate.next_in = (Bytef *)st->cbuffer;
st->flate.avail_in = (uInt)rbytes; st->flate.avail_in = (uInt)rbytes;
@ -825,8 +828,8 @@ pdfioStreamWrite(
if (st->bufptr > st->buffer || bytes < 16) if (st->bufptr > st->buffer || bytes < 16)
{ {
// Write through the stream's buffer... // Write through the stream's buffer...
if ((cbytes = bytes) > (st->bufend - st->bufptr)) if ((cbytes = bytes) > (size_t)(st->bufend - st->bufptr))
cbytes = st->bufend - st->bufptr; cbytes = (size_t)(st->bufend - st->bufptr);
memcpy(st->bufptr, bufptr, cbytes); memcpy(st->bufptr, bufptr, cbytes);
st->bufptr += cbytes; st->bufptr += cbytes;
@ -848,7 +851,7 @@ pdfioStreamWrite(
if (cbytes & 15) if (cbytes & 15)
{ {
// AES has a 16-byte block size, so save the last few bytes... // AES has a 16-byte block size, so save the last few bytes...
cbytes &= ~15; cbytes &= (size_t)~15;
} }
outbytes = (st->crypto_cb)(&st->crypto_ctx, temp, bufptr, cbytes); outbytes = (st->crypto_cb)(&st->crypto_ctx, temp, bufptr, cbytes);
@ -1007,7 +1010,7 @@ stream_read(pdfio_stream_t *st, // I - Stream
st->remaining -= (size_t)rbytes; st->remaining -= (size_t)rbytes;
if (st->crypto_cb) if (st->crypto_cb)
(st->crypto_cb)(&st->crypto_ctx, (uint8_t *)buffer, (uint8_t *)buffer, rbytes); (st->crypto_cb)(&st->crypto_ctx, (uint8_t *)buffer, (uint8_t *)buffer, (size_t)rbytes);
} }
return (rbytes); return (rbytes);
@ -1034,7 +1037,7 @@ stream_read(pdfio_stream_t *st, // I - Stream
return (-1); // End of file... return (-1); // End of file...
if (st->crypto_cb) if (st->crypto_cb)
rbytes = (st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, rbytes); rbytes = (ssize_t)(st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, (size_t)rbytes);
st->remaining -= (size_t)rbytes; st->remaining -= (size_t)rbytes;
st->flate.next_in = (Bytef *)st->cbuffer; st->flate.next_in = (Bytef *)st->cbuffer;
@ -1090,7 +1093,7 @@ stream_read(pdfio_stream_t *st, // I - Stream
return (-1); // End of file... return (-1); // End of file...
if (st->crypto_cb) if (st->crypto_cb)
rbytes = (st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, rbytes); rbytes = (ssize_t)(st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, (size_t)rbytes);
st->remaining -= (size_t)rbytes; st->remaining -= (size_t)rbytes;
st->flate.next_in = (Bytef *)st->cbuffer; st->flate.next_in = (Bytef *)st->cbuffer;
@ -1157,7 +1160,7 @@ stream_read(pdfio_stream_t *st, // I - Stream
return (-1); // End of file... return (-1); // End of file...
if (st->crypto_cb) if (st->crypto_cb)
rbytes = (st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, rbytes); rbytes = (ssize_t)(st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, (size_t)rbytes);
st->remaining -= (size_t)rbytes; st->remaining -= (size_t)rbytes;
st->flate.next_in = (Bytef *)st->cbuffer; st->flate.next_in = (Bytef *)st->cbuffer;
@ -1261,7 +1264,7 @@ stream_write(pdfio_stream_t *st, // I - Stream
if (st->crypto_cb) if (st->crypto_cb)
{ {
// Encrypt it first... // Encrypt it first...
outbytes = (st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, cbytes & ~15); outbytes = (st->crypto_cb)(&st->crypto_ctx, st->cbuffer, st->cbuffer, cbytes & (size_t)~15);
} }
else else
{ {
@ -1284,7 +1287,7 @@ stream_write(pdfio_stream_t *st, // I - Stream
} }
st->flate.next_out = (Bytef *)st->cbuffer + cbytes; st->flate.next_out = (Bytef *)st->cbuffer + cbytes;
st->flate.avail_out = sizeof(st->cbuffer) - cbytes; st->flate.avail_out = (uInt)(sizeof(st->cbuffer) - cbytes);
} }
// Deflate what we can this time... // Deflate what we can this time...

View File

@ -498,9 +498,6 @@ _pdfioTokenRead(_pdfio_token_t *tb, // I - Token buffer/stack
break; break;
} }
while (tb->bufptr < tb->bufend && isspace(*(tb->bufptr)))
tb->bufptr ++;
*bufptr = '\0'; *bufptr = '\0';
PDFIO_DEBUG("_pdfioTokenRead: Read '%s'.\n", buffer); PDFIO_DEBUG("_pdfioTokenRead: Read '%s'.\n", buffer);