[poppler] Branch 'signatureHandling' - poppler/Form.cc poppler/Object.h

Adrian Johnson ajohnson at kemper.freedesktop.org
Thu Jan 14 14:19:58 PST 2016


 poppler/Form.cc  |   60 ++++++++++++++++++++++++++++---------------------------
 poppler/Object.h |   12 ++++++++++-
 2 files changed, 42 insertions(+), 30 deletions(-)

New commits:
commit dcefd7a232ba17af878b95efaa4ffaf147d095b7
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Fri Jan 8 16:49:25 2016 +1030

    check all byte ranges in signature dictionary

diff --git a/poppler/Form.cc b/poppler/Form.cc
index d94757a..910c179 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.isIntOrInt64() || !lenObj.isIntOrInt64()) {
+      error(errSyntaxError, 0, "Illegal values in ByteRange array");
+      return signature_info;
+    }
 
-  hashSignedDataBlock(&signature_handler, block_len);
+    Goffset offset = offsetObj.getIntOrInt64();
+    Goffset len = lenObj.getIntOrInt64();
 
-  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..b9cae28 100644
--- a/poppler/Object.h
+++ b/poppler/Object.h
@@ -50,7 +50,14 @@
         abort(); \
     }
 
-#define OBJECT_3TYPES_CHECK(wanted_type1, wanted_type2, wanted_type3) \
+#define OBJECT_2TYPES_CHECK(wanted_type1, wanted_type2) \
+    if (unlikely(type != wanted_type1) && unlikely(type != wanted_type2)) { \
+        error(errInternal, 0, "Call to Object where the object was type {0:d}, " \
+	      "not the expected type {1:d} or {2:d}", type, wanted_type1, wanted_type2); \
+        abort(); \
+    }
+
+#define OBJECT_3TYPES_CHECK(wanted_type1, wanted_type2, wanted_type3)	\
     if (unlikely(type != wanted_type1) && unlikely(type != wanted_type2) && unlikely(type != wanted_type3)) { \
         error(errInternal, 0, "Call to Object where the object was type {0:d}, " \
 	      "not the expected type {1:d}, {2:d} or {3:d}", type, wanted_type1, wanted_type2, wanted_type3); \
@@ -181,6 +188,7 @@ public:
   GBool isEOF() { return type == objEOF; }
   GBool isNone() { return type == objNone; }
   GBool isInt64() { return type == objInt64; }
+  GBool isIntOrInt64() { return type == objInt || type == objInt64; }
 
   // Special type checking.
   GBool isName(const char *nameA)
@@ -213,6 +221,8 @@ public:
   int getRefGen() { OBJECT_TYPE_CHECK(objRef); return ref.gen; }
   char *getCmd() { OBJECT_TYPE_CHECK(objCmd); return cmd; }
   long long getInt64() { OBJECT_TYPE_CHECK(objInt64); return int64g; }
+  long long getIntOrInt64() { OBJECT_2TYPES_CHECK(objInt, objInt64);
+    return type == objInt ? intg : int64g; }
 
   // Array accessors.
   int arrayGetLength();


More information about the poppler mailing list