From 94eaf1c5ed207f6103d0115f294aa70404948e7c Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Fri, 8 Jan 2016 16:49:25 +1030 Subject: [PATCH] check all byte ranges in signature dictionary --- poppler/Form.cc | 60 +++++++++++++++++++++++++++++--------------------------- poppler/Object.h | 1 + 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/poppler/Form.cc b/poppler/Form.cc index d94757a..94ef81c 100644 --- a/poppler/Form.cc +++ b/poppler/Form.cc @@ -1473,48 +1473,51 @@ SignatureInfo *FormFieldSignature::validateSignature(bool doVerifyCert, bool for return signature_info; } - if (!byte_range.isArray() || signature == NULL) { + if (signature == NULL) { + error(errSyntaxError, 0, "Invalid or missing Signature string"); return signature_info; } - Object r2, r3, r4; - NSSCMSVerificationStatus sig_val_state; - SECErrorCodes cert_val_state; - - byte_range.arrayGet(1, &r2); - byte_range.arrayGet(2, &r3); - byte_range.arrayGet(3, &r4); - - Goffset fileLength = doc->getBaseStream()->getLength(); - Goffset r_values[3]; - - r_values[0] = r2.isInt64() ? r2.getInt64() : r2.getInt(); - r_values[1] = r3.isInt64() ? r3.getInt64() : r3.getInt(); - r_values[2] = r4.isInt64() ? r4.getInt64() : r4.getInt(); + if (!byte_range.isArray()) { + error(errSyntaxError, 0, "Invalid or missing ByteRange array"); + return signature_info; + } - if (r_values[0] <= 0 || r_values[1] <= 0 || r_values[2] <= 0 || r_values[1] <= r_values[0] || - r_values[1] + r_values[2] > fileLength) - { - error(errSyntaxError, 0, "Illegal values in ByteRange array"); - return signature_info; + int arrayLen = byte_range.arrayGetLength(); + if (arrayLen < 2) { + error(errSyntaxError, 0, "Too few elements in ByteRange array"); + return signature_info; } + NSSCMSVerificationStatus sig_val_state; + SECErrorCodes cert_val_state; const int signature_len = signature->getLength(); - unsigned char *signatureuchar = (unsigned char *)gmalloc(signature_len); memcpy(signatureuchar, signature->getCString(), signature_len); SignatureHandler signature_handler(signatureuchar, signature_len); - //Read the 2 slices of data that are signed - doc->getBaseStream()->setPos(0); - Goffset block_len = r_values[0]; + Goffset fileLength = doc->getBaseStream()->getLength(); + for (int i = 0; i < arrayLen/2; i++) { + Object offsetObj, lenObj; + byte_range.arrayGet(i*2, &offsetObj); + byte_range.arrayGet(i*2+1, &lenObj); + + if (!offsetObj.isInteger() || !lenObj.isInteger()) { + error(errSyntaxError, 0, "Illegal values in ByteRange array"); + return signature_info; + } - hashSignedDataBlock(&signature_handler, block_len); + Goffset offset = offsetObj.isInt64() ? offsetObj.getInt64() : offsetObj.getInt(); + Goffset len = lenObj.isInt64() ? lenObj.getInt64() : lenObj.getInt(); - doc->getBaseStream()->setPos(r_values[1]); - block_len = r_values[2]; + if (offset < 0 || offset >= fileLength || len < 0 || len > fileLength || offset + len > fileLength) { + error(errSyntaxError, 0, "Illegal values in ByteRange array"); + return signature_info; + } - hashSignedDataBlock(&signature_handler, block_len); + doc->getBaseStream()->setPos(offset); + hashSignedDataBlock(&signature_handler, len); + } sig_val_state = signature_handler.validateSignature(); signature_info->setSignatureValStatus(SignatureHandler::NSS_SigTranslate(sig_val_state)); @@ -1534,7 +1537,6 @@ SignatureInfo *FormFieldSignature::validateSignature(bool doVerifyCert, bool for #endif return signature_info; - } #ifdef DEBUG_FORMS diff --git a/poppler/Object.h b/poppler/Object.h index 1b06a3c..9599bcc 100644 --- a/poppler/Object.h +++ b/poppler/Object.h @@ -181,6 +181,7 @@ public: GBool isEOF() { return type == objEOF; } GBool isNone() { return type == objNone; } GBool isInt64() { return type == objInt64; } + GBool isInteger() { return type == objInt || type == objInt64; } // Special type checking. GBool isName(const char *nameA) -- 2.1.4