Merge "Integrate integer overflow changes from security branch" into nyc-dev
diff --git a/source/dng_ifd.cpp b/source/dng_ifd.cpp
index 570477d..317ebf9 100644
--- a/source/dng_ifd.cpp
+++ b/source/dng_ifd.cpp
@@ -1326,8 +1326,8 @@
 				return false;
 				}
 			
-			if (!CheckTagCount (parentCode, tagCode, tagCount, fCFARepeatPatternRows *
-															   fCFARepeatPatternCols))
+			if (!CheckTagCount (parentCode, tagCode, tagCount,
+								SafeUint32Mult(fCFARepeatPatternRows, fCFARepeatPatternCols)))
 				{
 				return false;
 				}
diff --git a/source/dng_safe_arithmetic.cpp b/source/dng_safe_arithmetic.cpp
index fc450f1..96eaec8 100644
--- a/source/dng_safe_arithmetic.cpp
+++ b/source/dng_safe_arithmetic.cpp
@@ -163,7 +163,8 @@
 std::int32_t SafeInt32Mult(std::int32_t arg1, std::int32_t arg2) {
   const std::int64_t tmp =
       static_cast<std::int64_t>(arg1) * static_cast<std::int64_t>(arg2);
-  if (tmp >= INT32_MIN && tmp <= INT32_MAX) {
+  if (tmp >= std::numeric_limits<std::int32_t>::min() &&
+      tmp <= std::numeric_limits<std::int32_t>::max()) {
     return static_cast<std::int32_t>(tmp);
   } else {
     ThrowProgramError("Arithmetic overflow");
@@ -182,15 +183,16 @@
 
   if (arg1 > 0) {
     if (arg2 > 0) {
-      overflow = (arg1 > INT64_MAX / arg2);
+      overflow = (arg1 > std::numeric_limits<std::int64_t>::max() / arg2);
     } else {
-      overflow = (arg2 < INT64_MIN / arg1);
+      overflow = (arg2 < std::numeric_limits<std::int64_t>::min() / arg1);
     }
   } else {
     if (arg2 > 0) {
-      overflow = (arg1 < INT64_MIN / arg2);
+      overflow = (arg1 < std::numeric_limits<std::int64_t>::min() / arg2);
     } else {
-      overflow = (arg1 != 0 && arg2 < INT64_MAX / arg1);
+      overflow = (arg1 != 0 &&
+                  arg2 < std::numeric_limits<std::int64_t>::max() / arg1);
     }
   }
 
@@ -269,8 +271,10 @@
 }
 
 std::int32_t ConvertDoubleToInt32(double val) {
-  const double kMin = static_cast<double>(INT32_MIN);
-  const double kMax = static_cast<double>(INT32_MAX);
+  const double kMin =
+      static_cast<double>(std::numeric_limits<std::int32_t>::min());
+  const double kMax =
+      static_cast<double>(std::numeric_limits<std::int32_t>::max());
   // NaNs will fail this test; they always compare false.
   if (val > kMin - 1.0 && val < kMax + 1.0) {
     return static_cast<std::int32_t>(val);
@@ -279,3 +283,15 @@
     abort();  // Never reached.
   }
 }
+
+std::uint32_t ConvertDoubleToUint32(double val) {
+  const double kMax =
+      static_cast<double>(std::numeric_limits<std::uint32_t>::max());
+  // NaNs will fail this test; they always compare false.
+  if (val >= 0.0 && val < kMax + 1.0) {
+    return static_cast<std::uint32_t>(val);
+  } else {
+    ThrowProgramError("Argument not in range in ConvertDoubleToUint32");
+    abort();  // Never reached.
+  }
+}
diff --git a/source/dng_shared.cpp b/source/dng_shared.cpp
index 961ac1f..3ff40a4 100644
--- a/source/dng_shared.cpp
+++ b/source/dng_shared.cpp
@@ -593,9 +593,8 @@
 			if (!skipSat0)
 				{
 			
-				if (!CheckTagCount (parentCode, tagCode, tagCount, fProfileHues *
-																   fProfileSats * 
-																   fProfileVals * 3))
+				if (!CheckTagCount (parentCode, tagCode, tagCount,
+									SafeUint32Mult(fProfileHues, fProfileSats, fProfileVals, 3)))
 					return false;
 					
 				}
diff --git a/source/dng_utils.h b/source/dng_utils.h
index d945a6e..d87de51 100644
--- a/source/dng_utils.h
+++ b/source/dng_utils.h
@@ -18,6 +18,8 @@
 
 /*****************************************************************************/
 
+#include <limits>
+
 #include "dng_classes.h"
 #include "dng_flags.h"
 #include "dng_memory.h"
@@ -481,7 +483,8 @@
 	
 	// NaNs will fail this test (because NaNs compare false against
 	// everything) and will therefore also take the else branch.
-	if (temp > real64(INT32_MIN) - 1.0 && temp < real64(INT32_MAX) + 1.0)
+	if (temp > real64(std::numeric_limits<int32>::min()) - 1.0 &&
+			temp < real64(std::numeric_limits<int32>::max()) + 1.0)
 		{
 		return (int32) temp;
 		}
@@ -509,7 +512,7 @@
 	
 	// NaNs will fail this test (because NaNs compare false against
 	// everything) and will therefore also take the else branch.
-	if (temp < real64(UINT32_MAX) + 1.0)
+	if (temp < real64(std::numeric_limits<uint32>::max()) + 1.0)
 		{
 		return (uint32) temp;
 		}