summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorFlorian Kriener <floriank@google.com>2016-02-29 15:38:08 +0100
committerFlorian Kriener <floriank@google.com>2016-03-01 12:40:19 +0100
commita9912faa4ebc5100cfb7f03718304a315edf32fb (patch)
treeb686396ed7f251badccf2ceabdfb8a7269cf5233 /source
parent0b098b759cf9a2a8659babaf8c3b74e1b48ca604 (diff)
downloaddng_sdk-a9912faa4ebc5100cfb7f03718304a315edf32fb.tar.gz
Integrate integer overflow changes from security branch
Bug: 26535130 Change-Id: Idafa0626ce5bea6c265d64175702ac85ed738b41
Diffstat (limited to 'source')
-rw-r--r--source/RawEnvironment.h4
-rw-r--r--source/dng_auto_ptr.h2
-rw-r--r--source/dng_camera_profile.cpp27
-rw-r--r--source/dng_color_spec.cpp3
-rw-r--r--source/dng_date_time.cpp8
-rw-r--r--source/dng_date_time.h2
-rw-r--r--source/dng_filter_task.cpp16
-rw-r--r--source/dng_fingerprint.h4
-rw-r--r--source/dng_flags.h2
-rw-r--r--source/dng_gain_map.cpp8
-rw-r--r--source/dng_host.cpp2
-rw-r--r--source/dng_hue_sat_map.cpp9
-rw-r--r--source/dng_ifd.cpp36
-rw-r--r--source/dng_image_writer.cpp6
-rw-r--r--source/dng_info.cpp43
-rw-r--r--source/dng_lens_correction.cpp56
-rw-r--r--source/dng_linearization_info.cpp4
-rw-r--r--source/dng_lossless_jpeg.cpp4
-rw-r--r--source/dng_memory_stream.cpp8
-rw-r--r--source/dng_misc_opcodes.cpp26
-rw-r--r--source/dng_mosaic_info.cpp12
-rw-r--r--source/dng_negative.cpp33
-rw-r--r--source/dng_pixel_buffer.cpp4
-rw-r--r--source/dng_pixel_buffer.h2
-rw-r--r--source/dng_point.h2
-rw-r--r--source/dng_read_image.cpp30
-rw-r--r--source/dng_render.cpp2
-rw-r--r--source/dng_resample.cpp48
-rw-r--r--source/dng_resample.h2
-rw-r--r--source/dng_safe_arithmetic.cpp90
-rw-r--r--source/dng_safe_arithmetic.h87
-rw-r--r--source/dng_shared.cpp42
-rw-r--r--source/dng_simple_image.cpp1
-rw-r--r--source/dng_string.cpp19
-rw-r--r--source/dng_types.h6
-rw-r--r--source/dng_utils.cpp3
-rw-r--r--source/dng_utils.h47
37 files changed, 397 insertions, 303 deletions
diff --git a/source/RawEnvironment.h b/source/RawEnvironment.h
index 3613cd4..688ee0e 100644
--- a/source/RawEnvironment.h
+++ b/source/RawEnvironment.h
@@ -1,3 +1,6 @@
+#ifndef __dng_RawEnvironment__
+#define __dng_RawEnvironment__
+
// Define preprocessor constants that control platform-specific conditional
// compilation. The constants qMacOS and qWinOS must be defined on all
// platforms. Other constants, such as qLinux, only need to be defined if we're
@@ -14,3 +17,4 @@
#define qWinOS 1
#endif
+#endif // __dng_RawEnvironment__
diff --git a/source/dng_auto_ptr.h b/source/dng_auto_ptr.h
index 6d70fe6..ed88bba 100644
--- a/source/dng_auto_ptr.h
+++ b/source/dng_auto_ptr.h
@@ -193,7 +193,7 @@ class AutoArray
/// Construct an AutoArray that refers to a null pointer.
AutoArray () { }
-
+
/// Construct an AutoArray containing 'count' elements, which are
/// default-constructed. If an out-of-memory condition occurs, a
/// dng_exception with error code dng_error_memory is thrown.
diff --git a/source/dng_camera_profile.cpp b/source/dng_camera_profile.cpp
index 06f423b..34a3105 100644
--- a/source/dng_camera_profile.cpp
+++ b/source/dng_camera_profile.cpp
@@ -21,6 +21,7 @@
#include "dng_image_writer.h"
#include "dng_info.h"
#include "dng_parse_utils.h"
+#include "dng_safe_arithmetic.h"
#include "dng_tag_codes.h"
#include "dng_tag_types.h"
#include "dng_temperature.h"
@@ -898,11 +899,6 @@ void dng_camera_profile::ReadHueSatMap (dng_stream &stream,
/*****************************************************************************/
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
void dng_camera_profile::Parse (dng_stream &stream,
dng_camera_profile_info &profileInfo)
{
@@ -971,9 +967,10 @@ void dng_camera_profile::Parse (dng_stream &stream,
stream.SetReadPosition (profileInfo.fHueSatDeltas1Offset);
- bool skipSat0 = (profileInfo.fHueSatDeltas1Count == profileInfo.fProfileHues *
- (profileInfo.fProfileSats - 1) *
- profileInfo.fProfileVals * 3);
+ bool skipSat0 = (profileInfo.fHueSatDeltas1Count == SafeUint32Mult(
+ profileInfo.fProfileHues,
+ SafeUint32Sub(profileInfo.fProfileSats, 1),
+ profileInfo.fProfileVals, 3));
ReadHueSatMap (stream,
fHueSatDeltas1,
@@ -992,9 +989,10 @@ void dng_camera_profile::Parse (dng_stream &stream,
stream.SetReadPosition (profileInfo.fHueSatDeltas2Offset);
- bool skipSat0 = (profileInfo.fHueSatDeltas2Count == profileInfo.fProfileHues *
- (profileInfo.fProfileSats - 1) *
- profileInfo.fProfileVals * 3);
+ bool skipSat0 = (profileInfo.fHueSatDeltas2Count == SafeUint32Mult(
+ profileInfo.fProfileHues,
+ SafeUint32Sub(profileInfo.fProfileSats, 1),
+ profileInfo.fProfileVals, 3));
ReadHueSatMap (stream,
fHueSatDeltas2,
@@ -1013,9 +1011,10 @@ void dng_camera_profile::Parse (dng_stream &stream,
stream.SetReadPosition (profileInfo.fLookTableOffset);
- bool skipSat0 = (profileInfo.fLookTableCount == profileInfo.fLookTableHues *
- (profileInfo.fLookTableSats - 1) *
- profileInfo.fLookTableVals * 3);
+ bool skipSat0 = (profileInfo.fLookTableCount == SafeUint32Mult(
+ profileInfo.fLookTableHues,
+ SafeUint32Sub(profileInfo.fLookTableSats, 1),
+ profileInfo.fLookTableVals, 3));
ReadHueSatMap (stream,
fLookTable,
diff --git a/source/dng_color_spec.cpp b/source/dng_color_spec.cpp
index b376410..57c8b25 100644
--- a/source/dng_color_spec.cpp
+++ b/source/dng_color_spec.cpp
@@ -409,6 +409,7 @@ void dng_color_spec::SetWhiteXY (const dng_xy_coord &white)
// Find the camera white values.
fCameraWhite = colorMatrix * XYtoXYZ (fWhiteXY);
+
real64 cameraWhiteMaxEntry = MaxEntry (fCameraWhite);
if (cameraWhiteMaxEntry == 0)
{
@@ -433,7 +434,7 @@ void dng_color_spec::SetWhiteXY (const dng_xy_coord &white)
fPCStoCamera = colorMatrix * MapWhiteMatrix (PCStoXY (), fWhiteXY);
real64 scale = MaxEntry (fPCStoCamera * PCStoXYZ ());
-
+
if (scale == 0)
{
ThrowBadFormat ();
diff --git a/source/dng_date_time.cpp b/source/dng_date_time.cpp
index e7175b8..bede131 100644
--- a/source/dng_date_time.cpp
+++ b/source/dng_date_time.cpp
@@ -103,11 +103,6 @@ void dng_date_time::Clear ()
/*****************************************************************************/
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
static uint32 DateTimeParseU32 (const char *&s)
{
@@ -118,7 +113,8 @@ static uint32 DateTimeParseU32 (const char *&s)
while (*s >= '0' && *s <= '9')
{
- x = x * 10 + (uint32) (*(s++) - '0');
+ x = SafeUint32Mult(x, 10);
+ x = SafeUint32Add(x, (uint32) (*(s++) - '0'));
}
return x;
diff --git a/source/dng_date_time.h b/source/dng_date_time.h
index 846c5c9..8cb5433 100644
--- a/source/dng_date_time.h
+++ b/source/dng_date_time.h
@@ -149,7 +149,7 @@ class dng_time_zone
void SetOffsetHours (int32 offset)
{
- fOffsetMinutes = (int32) ((int64) offset * 60);
+ fOffsetMinutes = SafeInt32Mult(offset, 60);
}
void SetOffsetMinutes (int32 offset)
diff --git a/source/dng_filter_task.cpp b/source/dng_filter_task.cpp
index 3676b6e..7823102 100644
--- a/source/dng_filter_task.cpp
+++ b/source/dng_filter_task.cpp
@@ -62,12 +62,12 @@ void dng_filter_task::Start (uint32 threadCount,
{
fSrcTileSize = SrcTileSize (tileSize);
-
+
uint32 srcBufferSize = ComputeBufferSize(fSrcPixelType, fSrcTileSize,
fSrcPlanes, pad16Bytes);
uint32 dstBufferSize = ComputeBufferSize(fDstPixelType, tileSize,
fDstPlanes, pad16Bytes);
-
+
for (uint32 threadIndex = 0; threadIndex < threadCount; threadIndex++)
{
@@ -95,20 +95,20 @@ void dng_filter_task::Process (uint32 threadIndex,
{
// Find source area for this destination area.
-
+
dng_rect srcArea = SrcArea (area);
-
+
int32 src_area_w;
int32 src_area_h;
if (!ConvertUint32ToInt32 (srcArea.W (), &src_area_w) || !ConvertUint32ToInt32 (srcArea.H (), &src_area_h) || src_area_w > fSrcTileSize.h || src_area_h > fSrcTileSize.v)
{
-
+
ThrowMemoryFull("Area exceeds tile size.");
-
+
}
-
+
// Setup srcBuffer.
-
+
dng_pixel_buffer srcBuffer(srcArea, fSrcPlane, fSrcPlanes, fSrcPixelType,
pcRowInterleavedAlign16,
fSrcBuffer [threadIndex]->Buffer ());
diff --git a/source/dng_fingerprint.h b/source/dng_fingerprint.h
index 74830e9..fe5c6d3 100644
--- a/source/dng_fingerprint.h
+++ b/source/dng_fingerprint.h
@@ -225,8 +225,8 @@ class dng_md5_printer
}
// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
-
-#if defined(__clang__) && defined(__has_attribute)
+
+#if defined(__clang__) && defined(__has_attribute)
#if __has_attribute(no_sanitize)
__attribute__((no_sanitize("unsigned-integer-overflow")))
#endif
diff --git a/source/dng_flags.h b/source/dng_flags.h
index 8b6c2f9..036914a 100644
--- a/source/dng_flags.h
+++ b/source/dng_flags.h
@@ -158,7 +158,7 @@
#ifndef qDNG64Bit
-#if qMacOS
+#if qMacOS || qLinux
#ifdef __LP64__
#if __LP64__
diff --git a/source/dng_gain_map.cpp b/source/dng_gain_map.cpp
index 489fca0..87d7e6f 100644
--- a/source/dng_gain_map.cpp
+++ b/source/dng_gain_map.cpp
@@ -19,6 +19,7 @@
#include "dng_globals.h"
#include "dng_host.h"
#include "dng_pixel_buffer.h"
+#include "dng_safe_arithmetic.h"
#include "dng_stream.h"
#include "dng_tag_values.h"
@@ -248,11 +249,6 @@ void dng_gain_map_interpolator::ResetColumn ()
/*****************************************************************************/
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
dng_gain_map::dng_gain_map (dng_memory_allocator &allocator,
const dng_point &points,
const dng_point_real64 &spacing,
@@ -264,7 +260,7 @@ dng_gain_map::dng_gain_map (dng_memory_allocator &allocator,
, fOrigin (origin)
, fPlanes (planes)
- , fRowStep (planes * points.h)
+ , fRowStep (SafeUint32Mult(planes, points.h))
, fBuffer ()
diff --git a/source/dng_host.cpp b/source/dng_host.cpp
index d36572c..28f1930 100644
--- a/source/dng_host.cpp
+++ b/source/dng_host.cpp
@@ -275,7 +275,7 @@ dng_exif * dng_host::Make_dng_exif ()
dng_xmp * dng_host::Make_dng_xmp ()
{
-
+
dng_xmp *result = new dng_xmp (Allocator ());
if (!result)
diff --git a/source/dng_hue_sat_map.cpp b/source/dng_hue_sat_map.cpp
index 4740e82..c86446f 100644
--- a/source/dng_hue_sat_map.cpp
+++ b/source/dng_hue_sat_map.cpp
@@ -97,11 +97,6 @@ dng_hue_sat_map::~dng_hue_sat_map ()
/*****************************************************************************/
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
void dng_hue_sat_map::SetDivisions (uint32 hueDivisions,
uint32 satDivisions,
uint32 valDivisions)
@@ -125,9 +120,9 @@ void dng_hue_sat_map::SetDivisions (uint32 hueDivisions,
fValDivisions = valDivisions;
fHueStep = satDivisions;
- fValStep = hueDivisions * fHueStep;
+ fValStep = SafeUint32Mult(hueDivisions, fHueStep);
- uint32 size = DeltasCount () * (uint32) sizeof (HSBModify);
+ uint32 size = SafeUint32Mult(DeltasCount (), (uint32) sizeof (HSBModify));
fDeltas.Allocate (size);
diff --git a/source/dng_ifd.cpp b/source/dng_ifd.cpp
index b0ff06b..570477d 100644
--- a/source/dng_ifd.cpp
+++ b/source/dng_ifd.cpp
@@ -256,11 +256,6 @@ dng_ifd::~dng_ifd ()
/*****************************************************************************/
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
// Parses tags that should only appear in IFDs that contain images.
bool dng_ifd::ParseTag (dng_stream &stream,
@@ -1541,9 +1536,9 @@ bool dng_ifd::ParseTag (dng_stream &stream,
CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong, ttRational);
- if (!CheckTagCount (parentCode, tagCode, tagCount, fBlackLevelRepeatRows *
- fBlackLevelRepeatCols *
- fSamplesPerPixel))
+ if (!CheckTagCount (parentCode, tagCode, tagCount, SafeUint32Mult(fBlackLevelRepeatRows,
+ fBlackLevelRepeatCols,
+ fSamplesPerPixel)))
{
return false;
}
@@ -2722,11 +2717,6 @@ bool dng_ifd::IsValidCFA (dng_shared &shared,
/*****************************************************************************/
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
bool dng_ifd::IsValidDNG (dng_shared &shared,
uint32 parentCode)
{
@@ -3446,8 +3436,8 @@ bool dng_ifd::IsValidDNG (dng_shared &shared,
// Check tile info.
- uint32 tilesWide = (fImageWidth + fTileWidth - 1) / fTileWidth;
- uint32 tilesHigh = (fImageLength + fTileLength - 1) / fTileLength;
+ uint32 tilesWide = SafeUint32DivideUp(fImageWidth, fTileWidth);
+ uint32 tilesHigh = SafeUint32DivideUp(fImageLength, fTileLength);
uint32 tileCount = tilesWide * tilesHigh;
@@ -4061,37 +4051,31 @@ dng_rect dng_ifd::TileArea (uint32 rowIndex,
/*****************************************************************************/
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
uint32 dng_ifd::TileByteCount (const dng_rect &tile) const
{
if (fCompression == ccUncompressed)
{
- uint32 bitsPerRow = tile.W () *
- fBitsPerSample [0];
+ uint32 bitsPerRow = SafeUint32Mult(tile.W (), fBitsPerSample [0]);
if (fPlanarConfiguration == pcInterleaved)
{
- bitsPerRow *= fSamplesPerPixel;
+ bitsPerRow = SafeUint32Mult(bitsPerRow, fSamplesPerPixel);
}
- uint32 bytesPerRow = (bitsPerRow + 7) >> 3;
+ uint32 bytesPerRow = SafeUint32DivideUp(bitsPerRow, 8);
if (fPlanarConfiguration == pcRowInterleaved)
{
- bytesPerRow *= fSamplesPerPixel;
+ bytesPerRow = SafeUint32Mult(bytesPerRow, fSamplesPerPixel);
}
- return bytesPerRow * tile.H ();
+ return SafeUint32Mult(bytesPerRow, tile.H ());
}
diff --git a/source/dng_image_writer.cpp b/source/dng_image_writer.cpp
index 049d7c3..5c81042 100644
--- a/source/dng_image_writer.cpp
+++ b/source/dng_image_writer.cpp
@@ -50,7 +50,7 @@
#if qDNGUseLibJPEG
#include "dng_jpeglib.h"
#endif
-
+
/*****************************************************************************/
// Defines for testing DNG 1.2 features.
@@ -4901,9 +4901,9 @@ static void CopyBoolean (const dng_xmp &oldXMP,
}
}
-
#endif
+
/*****************************************************************************/
void dng_image_writer::CleanUpMetadata (dng_host &host,
@@ -6506,7 +6506,7 @@ void dng_image_writer::WriteDNG (dng_host &host,
}
// XMP metadata.
-
+
#if qDNGUseXMP
tag_xmp tagXMP (metadata->GetXMP ());
diff --git a/source/dng_info.cpp b/source/dng_info.cpp
index 65f3a4b..ed87692 100644
--- a/source/dng_info.cpp
+++ b/source/dng_info.cpp
@@ -21,6 +21,7 @@
#include "dng_host.h"
#include "dng_tag_codes.h"
#include "dng_parse_utils.h"
+#include "dng_safe_arithmetic.h"
#include "dng_tag_types.h"
#include "dng_tag_values.h"
#include "dng_utils.h"
@@ -334,11 +335,6 @@ void dng_info::ParseTag (dng_host &host,
/*****************************************************************************/
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
bool dng_info::ValidateIFD (dng_stream &stream,
uint64 ifdOffset,
int64 offsetDelta)
@@ -388,7 +384,7 @@ bool dng_info::ValidateIFD (dng_stream &stream,
return false;
}
- uint32 tag_data_size = tagCount * tag_type_size;
+ uint32 tag_data_size = SafeUint32Mult(tagCount, tag_type_size);
if (tag_data_size > 4)
{
@@ -397,7 +393,7 @@ bool dng_info::ValidateIFD (dng_stream &stream,
tagOffset += offsetDelta;
- if (tagOffset + tag_data_size > stream.Length ())
+ if (SafeUint64Add(tagOffset, tag_data_size) > stream.Length())
{
return false;
}
@@ -412,11 +408,6 @@ bool dng_info::ValidateIFD (dng_stream &stream,
/*****************************************************************************/
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
void dng_info::ParseIFD (dng_host &host,
dng_stream &stream,
dng_exif *exif,
@@ -558,7 +549,7 @@ void dng_info::ParseIFD (dng_host &host,
uint64 tagOffset = ifdOffset + 2 + tag_index * 12 + 8;
- if (tagCount * tag_type_size > 4)
+ if (SafeUint32Mult(tagCount, tag_type_size) > 4)
{
tagOffset = stream.Get_uint32 ();
@@ -662,11 +653,6 @@ void dng_info::ParseIFD (dng_host &host,
/*****************************************************************************/
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
bool dng_info::ParseMakerNoteIFD (dng_host &host,
dng_stream &stream,
uint64 ifdSize,
@@ -760,7 +746,7 @@ bool dng_info::ParseMakerNoteIFD (dng_host &host,
continue;
}
- uint32 tagSize = tagCount * TagTypeSize (tagType);
+ uint32 tagSize = SafeUint32Mult(tagCount, TagTypeSize (tagType));
uint64 tagOffset = ifdOffset + 2 + tagIndex * 12 + 8;
@@ -770,7 +756,7 @@ bool dng_info::ParseMakerNoteIFD (dng_host &host,
tagOffset = stream.Get_uint32 () + offsetDelta;
if (tagOffset < minOffset ||
- tagOffset + tagSize > maxOffset)
+ SafeUint64Add(tagOffset, tagSize) > maxOffset)
{
// Tag data is outside the valid offset range,
@@ -1427,11 +1413,6 @@ void dng_info::ParseSonyPrivateData (dng_host & /* host */,
/*****************************************************************************/
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
void dng_info::ParseDNGPrivateData (dng_host &host,
dng_stream &stream)
{
@@ -1543,7 +1524,7 @@ void dng_info::ParseDNGPrivateData (dng_host &host,
uint16 order_mark = stream.Get_uint16 ();
int64 old_offset = stream.Get_uint32 ();
- uint32 tempSize = section_count - 6;
+ uint32 tempSize = SafeUint32Sub(section_count, 6);
AutoPtr<dng_memory_block> tempBlock (host.Allocate (tempSize));
@@ -1629,7 +1610,7 @@ void dng_info::ParseDNGPrivateData (dng_host &host,
tagOffset,
0);
- stream.SetReadPosition (tagOffset + tagCount);
+ stream.SetReadPosition (SafeUint64Add(tagOffset, tagCount));
}
@@ -1654,7 +1635,7 @@ void dng_info::ParseDNGPrivateData (dng_host &host,
tagOffset,
0);
- stream.SetReadPosition (tagOffset + tagCount);
+ stream.SetReadPosition (SafeUint64Add(tagOffset, tagCount));
}
@@ -1679,7 +1660,7 @@ void dng_info::ParseDNGPrivateData (dng_host &host,
tagOffset,
0);
- stream.SetReadPosition (tagOffset + tagCount);
+ stream.SetReadPosition (SafeUint64Add(tagOffset, tagCount));
}
@@ -1860,7 +1841,7 @@ void dng_info::ParseDNGPrivateData (dng_host &host,
uint32 tagCount = stream.Get_uint32 ();
- uint32 tagSize = tagCount * TagTypeSize (tagType);
+ uint32 tagSize = SafeUint32Mult(tagCount, TagTypeSize (tagType));
uint64 tagOffset = stream.Position ();
@@ -1878,7 +1859,7 @@ void dng_info::ParseDNGPrivateData (dng_host &host,
tagOffset,
0);
- stream.SetReadPosition (tagOffset + tagSize);
+ stream.SetReadPosition (SafeUint64Add(tagOffset, tagSize));
}
diff --git a/source/dng_lens_correction.cpp b/source/dng_lens_correction.cpp
index 5afda9f..67c09ac 100644
--- a/source/dng_lens_correction.cpp
+++ b/source/dng_lens_correction.cpp
@@ -29,6 +29,7 @@
#include "dng_safe_arithmetic.h"
#include "dng_sdk_limits.h"
#include "dng_tag_values.h"
+#include "dng_utils.h"
/*****************************************************************************/
@@ -1111,11 +1112,6 @@ void dng_filter_warp::Initialize (dng_host &host)
/*****************************************************************************/
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("float-cast-overflow")))
-#endif
-#endif
dng_rect dng_filter_warp::SrcArea (const dng_rect &dstArea)
{
@@ -1143,7 +1139,7 @@ dng_rect dng_filter_warp::SrcArea (const dng_rect &dstArea)
const dng_point_real64 src = GetSrcPixelPosition (dst, plane);
- const int32 y = (int32) floor (src.v);
+ const int32 y = ConvertDoubleToInt32 (floor (src.v));
yMin = Min_int32 (yMin, y);
@@ -1157,7 +1153,7 @@ dng_rect dng_filter_warp::SrcArea (const dng_rect &dstArea)
const dng_point_real64 src = GetSrcPixelPosition (dst, plane);
- const int32 y = (int32) ceil (src.v);
+ const int32 y = ConvertDoubleToInt32 (ceil (src.v));
yMax = Max_int32 (yMax, y);
@@ -1178,7 +1174,7 @@ dng_rect dng_filter_warp::SrcArea (const dng_rect &dstArea)
const dng_point_real64 src = GetSrcPixelPosition (dst, plane);
- const int32 x = (int32) floor (src.h);
+ const int32 x = ConvertDoubleToInt32 (floor (src.h));
xMin = Min_int32 (xMin, x);
@@ -1192,7 +1188,7 @@ dng_rect dng_filter_warp::SrcArea (const dng_rect &dstArea)
const dng_point_real64 src = GetSrcPixelPosition (dst, plane);
- const int32 x = (int32) ceil (src.h);
+ const int32 x = ConvertDoubleToInt32 (ceil (src.h));
xMax = Max_int32 (xMax, x);
@@ -1204,15 +1200,15 @@ dng_rect dng_filter_warp::SrcArea (const dng_rect &dstArea)
// Pad each side by filter radius.
- const int32 pad = (int32) fWeights.Radius ();
+ const int32 pad = ConvertUint32ToInt32(fWeights.Radius());
- xMin = (int32) ((int64) xMin - (int64)pad);
- yMin = (int32) ((int64) yMin - (int64)pad);
- xMax = (int32) ((int64) xMax + (int64)pad);
- yMax = (int32) ((int64) yMax + (int64)pad);
+ xMin = SafeInt32Sub(xMin, pad);
+ yMin = SafeInt32Sub(yMin, pad);
+ xMax = SafeInt32Add(xMax, pad);
+ yMax = SafeInt32Add(yMax, pad);
- xMax = (int32) ((int64) xMax + 1);
- yMax = (int32) ((int64) yMax + 1);
+ xMax = SafeInt32Add(xMax, 1);
+ yMax = SafeInt32Add(yMax, 1);
const dng_rect srcArea (yMin,
xMin,
@@ -1225,11 +1221,6 @@ dng_rect dng_filter_warp::SrcArea (const dng_rect &dstArea)
/*****************************************************************************/
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("float-cast-overflow")))
-#endif
-#endif
dng_point dng_filter_warp::SrcTileSize (const dng_point &dstTileSize)
{
@@ -1266,14 +1257,14 @@ dng_point dng_filter_warp::SrcTileSize (const dng_point &dstTileSize)
const real64 maxSrcGap = fParams->MaxSrcRadiusGap (maxDstGap);
- const int32 dim = (int32) ceil (maxSrcGap * fNormRadius);
+ const int32 dim = ConvertDoubleToInt32 (ceil (maxSrcGap * fNormRadius));
srcTileSize = dng_point (dim, dim);
}
- srcTileSize.h += (int32) (fWeights.Width ());
- srcTileSize.v += (int32) (fWeights.Width ());
+ srcTileSize.h += ConvertUint32ToInt32(fWeights.Width());
+ srcTileSize.v += ConvertUint32ToInt32(fWeights.Width());
// Get upper bound on src tile size from tangential warp.
@@ -1290,8 +1281,8 @@ dng_point dng_filter_warp::SrcTileSize (const dng_point &dstTileSize)
// Add the two bounds together.
- srcTileSize.v = (int32) ((real64) srcTileSize.v + (real64) ceil (srcTanGap.v * fNormRadius));
- srcTileSize.h = (int32) ((real64) srcTileSize.h + (real64) ceil (srcTanGap.h * fNormRadius));
+ srcTileSize.v += ConvertDoubleToInt32 (ceil (srcTanGap.v * fNormRadius));
+ srcTileSize.h += ConvertDoubleToInt32 (ceil (srcTanGap.h * fNormRadius));
return srcTileSize;
@@ -1299,11 +1290,6 @@ dng_point dng_filter_warp::SrcTileSize (const dng_point &dstTileSize)
/*****************************************************************************/
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("float-cast-overflow")))
-#endif
-#endif
void dng_filter_warp::ProcessArea (uint32 /* threadIndex */,
dng_pixel_buffer &srcBuffer,
dng_pixel_buffer &dstBuffer)
@@ -1367,11 +1353,11 @@ void dng_filter_warp::ProcessArea (uint32 /* threadIndex */,
// Decompose into integer and fractional parts.
- dng_point sInt ((int32) floor (sPos.v),
- (int32) floor (sPos.h));
+ dng_point sInt (ConvertDoubleToInt32 (floor (sPos.v)),
+ ConvertDoubleToInt32 (floor (sPos.h)));
- dng_point sFct ((int32) ((sPos.v - (real64) sInt.v) * numSubsamples),
- (int32) ((sPos.h - (real64) sInt.h) * numSubsamples));
+ dng_point sFct (ConvertDoubleToInt32 ((sPos.v - (real64) sInt.v) * numSubsamples),
+ ConvertDoubleToInt32 ((sPos.h - (real64) sInt.h) * numSubsamples));
// Add resample offset.
diff --git a/source/dng_linearization_info.cpp b/source/dng_linearization_info.cpp
index 27bc457..95fa493 100644
--- a/source/dng_linearization_info.cpp
+++ b/source/dng_linearization_info.cpp
@@ -687,7 +687,7 @@ void dng_linearize_plane::Process (const dng_rect &srcTile)
uint16 *dstPtr = (uint16 *) dPtr;
- b1 = (int32) ((int64) b1 - (int64) 128); // Rounding for 8 bit shift
+ b1 -= 128; // Rounding for 8 bit shift
if (fSrcPixelType == ttByte)
{
@@ -735,7 +735,7 @@ void dng_linearize_plane::Process (const dng_rect &srcTile)
if (b2_count)
{
- x = (int32) ((int64)x - b2 [b2_phase]);
+ x -= b2 [b2_phase];
if (++b2_phase == b2_count)
{
diff --git a/source/dng_lossless_jpeg.cpp b/source/dng_lossless_jpeg.cpp
index 9257f88..e3b0576 100644
--- a/source/dng_lossless_jpeg.cpp
+++ b/source/dng_lossless_jpeg.cpp
@@ -254,7 +254,7 @@ static void FixHuffTbl (HuffmanTable *htbl)
{
ThrowBadFormat ();
}
-
+
for (i = ll; i <= ul; i++)
{
htbl->numbits [i] = size;
@@ -1680,7 +1680,7 @@ inline int32 dng_lossless_decoder::HuffDecode (HuffmanTable *htbl)
inline void dng_lossless_decoder::HuffExtend (int32 &x, int32 s)
{
-
+
if (x < (0x08000 >> (16 - s)))
{
x += -(1 << s) + 1;
diff --git a/source/dng_memory_stream.cpp b/source/dng_memory_stream.cpp
index c5821f3..b6e903e 100644
--- a/source/dng_memory_stream.cpp
+++ b/source/dng_memory_stream.cpp
@@ -121,7 +121,7 @@ void dng_memory_stream::DoSetLength (uint64 length)
if (fPageCount == fPagesAllocated)
{
-
+
uint32 newSizeTemp1 = 0, newSizeTemp2 = 0;
if (!SafeUint32Add (fPagesAllocated, 32u, &newSizeTemp1) ||
!SafeUint32Mult (fPagesAllocated, 2u, &newSizeTemp2))
@@ -135,10 +135,10 @@ void dng_memory_stream::DoSetLength (uint64 length)
{
ThrowMemoryFull ("Arithmetic overflow in DoSetLength()");
}
-
+
dng_memory_block **list = (dng_memory_block **) malloc (numBytes);
-
- if (!list)
+
+ if (!list)
{
ThrowMemoryFull ();
diff --git a/source/dng_misc_opcodes.cpp b/source/dng_misc_opcodes.cpp
index ca7ba8f..5a6fa82 100644
--- a/source/dng_misc_opcodes.cpp
+++ b/source/dng_misc_opcodes.cpp
@@ -201,11 +201,6 @@ void dng_area_spec::PutData (dng_stream &stream) const
/*****************************************************************************/
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
dng_rect dng_area_spec::Overlap (const dng_rect &tile) const
{
@@ -222,8 +217,12 @@ dng_rect dng_area_spec::Overlap (const dng_rect &tile) const
if (overlap.NotEmpty ())
{
- overlap.t = fArea.t + ((overlap.t - fArea.t + fRowPitch - 1) / fRowPitch) * fRowPitch;
- overlap.l = fArea.l + ((overlap.l - fArea.l + fColPitch - 1) / fColPitch) * fColPitch;
+ overlap.t = fArea.t + ConvertUint32ToInt32(
+ RoundUpUint32ToMultiple(static_cast<uint32>(overlap.t - fArea.t),
+ fRowPitch));
+ overlap.l = fArea.l + ConvertUint32ToInt32(
+ RoundUpUint32ToMultiple(static_cast<uint32>(overlap.l - fArea.l),
+ fColPitch));
if (overlap.NotEmpty ())
{
@@ -468,11 +467,6 @@ dng_opcode_MapPolynomial::dng_opcode_MapPolynomial (const dng_area_spec &areaSpe
/*****************************************************************************/
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
dng_opcode_MapPolynomial::dng_opcode_MapPolynomial (dng_stream &stream)
: dng_inplace_opcode (dngOpcode_MapPolynomial,
@@ -490,16 +484,16 @@ dng_opcode_MapPolynomial::dng_opcode_MapPolynomial (dng_stream &stream)
fDegree = stream.Get_uint32 ();
- if (dataSize != dng_area_spec::kDataSize + 4 + (fDegree + 1) * 8)
+ if (fDegree > kMaxDegree)
{
ThrowBadFormat ();
}
-
- if (fDegree > kMaxDegree)
+
+ if (dataSize != dng_area_spec::kDataSize + 4 + (fDegree + 1) * 8)
{
ThrowBadFormat ();
}
-
+
for (uint32 j = 0; j <= kMaxDegree; j++)
{
diff --git a/source/dng_mosaic_info.cpp b/source/dng_mosaic_info.cpp
index 0fb50e6..0a51d9b 100644
--- a/source/dng_mosaic_info.cpp
+++ b/source/dng_mosaic_info.cpp
@@ -293,17 +293,21 @@ __attribute__((no_sanitize("unsigned-integer-overflow")))
#endif
uint32 DeltaRow (uint32 row, int32 delta)
{
- return (row + fPatRows + (uint32) delta) % fPatRows;
+ // Potential overflow in the conversion from delta to a uint32 as
+ // well as in the subsequent addition is intentional.
+ return (SafeUint32Add(row, fPatRows) + (uint32) delta) % fPatRows;
}
-
+
#if defined(__clang__) && defined(__has_attribute)
#if __has_attribute(no_sanitize)
__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
+#endif
#endif
uint32 DeltaCol (uint32 col, int32 delta)
{
- return (col + fPatCols + (uint32) delta) % fPatCols;
+ // Potential overflow in the conversion from delta to a uint32 as
+ // well as in the subsequent addition is intentional.
+ return (SafeUint32Add(col, fPatCols) + (uint32) delta) % fPatCols;
}
real32 LinearWeight1 (int32 d1, int32 d2)
diff --git a/source/dng_negative.cpp b/source/dng_negative.cpp
index ab63e5d..1f7d6ad 100644
--- a/source/dng_negative.cpp
+++ b/source/dng_negative.cpp
@@ -43,6 +43,7 @@
#include "dng_tag_values.h"
#include "dng_tile_iterator.h"
#include "dng_utils.h"
+
#if qDNGUseXMP
#include "dng_xmp.h"
#endif
@@ -237,9 +238,9 @@ void dng_metadata::ApplyOrientation (const dng_orientation &orientation)
{
fBaseOrientation += orientation;
-
#if qDNGUseXMP
+
fXMP->SetOrientation (fBaseOrientation);
#endif
@@ -545,7 +546,7 @@ void dng_metadata::ResetXMP (dng_xmp * newXMP)
{
fXMP.Reset (newXMP);
-
+
}
/*****************************************************************************/
@@ -720,9 +721,9 @@ void dng_metadata::UpdateMetadataDateTimeToNow ()
CurrentDateTimeAndZone (dt);
- #if qDNGUseXMP
+#if qDNGUseXMP
fXMP->UpdateMetadataDate (dt);
- #endif
+#endif
}
@@ -1679,7 +1680,7 @@ class dng_find_new_raw_image_digest_task : public dng_area_task
const uint32 bufferSize =
ComputeBufferSize(fPixelType, tileSize, fImage.Planes(),
padNone);
-
+
for (uint32 index = 0; index < threadCount; index++)
{
@@ -4158,11 +4159,6 @@ void dng_negative::DoBuildStage3 (dng_host &host,
/*****************************************************************************/
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
void dng_negative::BuildStage3Image (dng_host &host,
int32 srcPlane)
{
@@ -4201,9 +4197,11 @@ void dng_negative::BuildStage3Image (dng_host &host,
uint32 adjust = Round_uint32 (fRawToFullScaleH);
- fDefaultCropSizeH .n *= adjust;
- fDefaultCropOriginH.n *= adjust;
- fDefaultScaleH .d *= adjust;
+ fDefaultCropSizeH .n =
+ SafeUint32Mult (fDefaultCropSizeH.n, adjust);
+ fDefaultCropOriginH.n =
+ SafeUint32Mult (fDefaultCropOriginH.n, adjust);
+ fDefaultScaleH .d = SafeUint32Mult (fDefaultScaleH.d, adjust);
fRawToFullScaleH /= (real64) adjust;
@@ -4214,9 +4212,12 @@ void dng_negative::BuildStage3Image (dng_host &host,
uint32 adjust = Round_uint32 (fRawToFullScaleV);
- fDefaultCropSizeV .n *= adjust;
- fDefaultCropOriginV.n *= adjust;
- fDefaultScaleV .d *= adjust;
+ fDefaultCropSizeV .n =
+ SafeUint32Mult (fDefaultCropSizeV.n, adjust);
+ fDefaultCropOriginV.n =
+ SafeUint32Mult (fDefaultCropOriginV.n, adjust);
+ fDefaultScaleV .d =
+ SafeUint32Mult (fDefaultScaleV.d, adjust);
fRawToFullScaleV /= (real64) adjust;
diff --git a/source/dng_pixel_buffer.cpp b/source/dng_pixel_buffer.cpp
index 28385d9..c1380eb 100644
--- a/source/dng_pixel_buffer.cpp
+++ b/source/dng_pixel_buffer.cpp
@@ -358,7 +358,7 @@ dng_pixel_buffer::dng_pixel_buffer ()
{
}
-
+
/*****************************************************************************/
dng_pixel_buffer::dng_pixel_buffer (const dng_rect &area,
@@ -382,7 +382,7 @@ dng_pixel_buffer::dng_pixel_buffer (const dng_rect &area,
{
const char *overflowMessage = "Arithmetic overflow in pixel buffer setup";
-
+
// Initialize fRowStep, fColStep and fPlaneStep according to the desired
// pixel layout.
switch (planarConfiguration)
diff --git a/source/dng_pixel_buffer.h b/source/dng_pixel_buffer.h
index 104d3b7..e144408 100644
--- a/source/dng_pixel_buffer.h
+++ b/source/dng_pixel_buffer.h
@@ -126,7 +126,7 @@ class dng_pixel_buffer
int32 col,
uint32 plane = 0) const
{
-
+
// Ensure pixel to be accessed lies inside valid area.
if (row < fArea.t || row >= fArea.b ||
col < fArea.l || col >= fArea.r ||
diff --git a/source/dng_point.h b/source/dng_point.h
index c6070b9..4cad777 100644
--- a/source/dng_point.h
+++ b/source/dng_point.h
@@ -18,8 +18,8 @@
/*****************************************************************************/
-#include "dng_types.h"
#include "dng_safe_arithmetic.h"
+#include "dng_types.h"
#include "dng_utils.h"
/*****************************************************************************/
diff --git a/source/dng_read_image.cpp b/source/dng_read_image.cpp
index b2f6dd4..08cb583 100644
--- a/source/dng_read_image.cpp
+++ b/source/dng_read_image.cpp
@@ -39,7 +39,7 @@
#include "dng_jpeg_memory_source.h"
#include "dng_jpeglib.h"
#endif
-
+
#include <limits>
/******************************************************************************/
@@ -1171,11 +1171,6 @@ dng_read_image::~dng_read_image ()
/*****************************************************************************/
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
bool dng_read_image::ReadUncompressed (dng_host &host,
const dng_ifd &ifd,
dng_stream &stream,
@@ -1192,15 +1187,15 @@ bool dng_read_image::ReadUncompressed (dng_host &host,
if (ifd.fPlanarConfiguration == pcRowInterleaved)
{
- rows *= planes;
+ rows = SafeUint32Mult(rows, planes);
}
else
{
- samplesPerRow *= planes;
+ samplesPerRow = SafeUint32Mult(samplesPerRow, planes);
}
- uint32 samplesPerTile = samplesPerRow * rows;
-
+ uint32 samplesPerTile = SafeUint32Mult(samplesPerRow, rows);
+
if (uncompressedBuffer.Get () == NULL)
{
@@ -1397,7 +1392,7 @@ bool dng_read_image::ReadUncompressed (dng_host &host,
uint32 *p = (uint32 *) uncompressedBuffer->Buffer ();
- uint32 bitMask = ((uint32)1 << bitDepth) - 1;
+ uint32 bitMask = ((uint32) 1 << bitDepth) - 1;
for (uint32 row = 0; row < rows; row++)
{
@@ -1809,11 +1804,6 @@ bool dng_read_image::ReadBaselineJPEG (dng_host &host,
/*****************************************************************************/
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
bool dng_read_image::ReadLosslessJPEG (dng_host &host,
const dng_ifd &ifd,
dng_stream &stream,
@@ -1868,9 +1858,9 @@ bool dng_read_image::ReadLosslessJPEG (dng_host &host,
*uncompressedBuffer.Get (),
subTileBlockBuffer);
- uint32 decodedSize = tileArea.W () *
- tileArea.H () *
- planes * (uint32) sizeof (uint16);
+ uint32 decodedSize = SafeUint32Mult(tileArea.W (),
+ tileArea.H (),
+ planes, (uint32) sizeof (uint16));
bool bug16 = ifd.fLosslessJPEGBug16;
@@ -2204,7 +2194,7 @@ void dng_read_image::ReadTile (dng_host &host,
ThrowMemoryFull ("Arithmetic overflow computing sample count.");
}
-
+
// Setup pixel buffer to hold uncompressed data.
uint32 pixelType = ttUndefined;
diff --git a/source/dng_render.cpp b/source/dng_render.cpp
index e3d9940..44ed445 100644
--- a/source/dng_render.cpp
+++ b/source/dng_render.cpp
@@ -45,7 +45,7 @@ dng_function_exposure_ramp::dng_function_exposure_ramp (real64 white,
{
ThrowBadFormat ();
}
-
+
const real64 kMaxCurveX = 0.5; // Fraction of minBlack.
const real64 kMaxCurveY = 1.0 / 16.0; // Fraction of white.
diff --git a/source/dng_resample.cpp b/source/dng_resample.cpp
index 5bb05d9..66bd002 100644
--- a/source/dng_resample.cpp
+++ b/source/dng_resample.cpp
@@ -310,7 +310,7 @@ dng_resample_weights_2d::~dng_resample_weights_2d ()
void dng_resample_weights_2d::Initialize (const dng_resample_function &kernel,
dng_memory_allocator &allocator)
{
-
+
// Find radius of this kernel. Unlike with 1d resample weights (see
// dng_resample_weights), we never scale up the kernel size.
@@ -326,12 +326,12 @@ void dng_resample_weights_2d::Initialize (const dng_resample_function &kernel,
!SafeUint32Mult (width, width, &widthSqr) ||
!RoundUpUint32ToMultiple (widthSqr, 8, &step) ||
!SafeUint32Mult (step, kResampleSubsampleCount2D, &fRowStep))
- {
-
- ThrowMemoryFull ("Arithmetic overflow computing row step.");
+ {
+
+ ThrowMemoryFull ("Arithmetic overflow computing row step.");
+
+ }
- }
-
fColStep = step;
// Allocate and zero weight tables.
@@ -354,13 +354,13 @@ void dng_resample_weights_2d::Initialize (const dng_resample_function &kernel,
if (!SafeUint32Mult (step, kResampleSubsampleCount2D, &bufferSize) ||
- !SafeUint32Mult (bufferSize, kResampleSubsampleCount2D, &bufferSize) ||
- !SafeUint32Mult (bufferSize, (uint32) sizeof (int16), &bufferSize))
- {
-
- ThrowMemoryFull ("Arithmetic overflow computing buffer size.");
-
- }
+ !SafeUint32Mult (bufferSize, kResampleSubsampleCount2D, &bufferSize) ||
+ !SafeUint32Mult (bufferSize, (uint32) sizeof (int16), &bufferSize))
+ {
+
+ ThrowMemoryFull ("Arithmetic overflow computing buffer size.");
+
+ }
fWeights16.Reset (allocator.Allocate (bufferSize));
@@ -557,7 +557,7 @@ dng_resample_task::dng_resample_task (const dng_image &srcImage,
if (fRowScale == 0 || fColScale == 0)
{
ThrowBadFormat ();
- }
+ }
if (srcImage.PixelSize () <= 2 &&
dstImage.PixelSize () <= 2 &&
@@ -587,11 +587,6 @@ dng_resample_task::dng_resample_task (const dng_image &srcImage,
/*****************************************************************************/
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
dng_rect dng_resample_task::SrcArea (const dng_rect &dstArea)
{
@@ -603,11 +598,17 @@ dng_rect dng_resample_task::SrcArea (const dng_rect &dstArea)
dng_rect srcArea;
- srcArea.t = fRowCoords.Pixel (dstArea.t) + offsetV;
- srcArea.l = fColCoords.Pixel (dstArea.l) + offsetH;
+ srcArea.t = SafeInt32Add (fRowCoords.Pixel (dstArea.t), offsetV);
+ srcArea.l = SafeInt32Add (fColCoords.Pixel (dstArea.l), offsetH);
- srcArea.b = fRowCoords.Pixel (dstArea.b - 1) + offsetV + widthV;
- srcArea.r = fColCoords.Pixel (dstArea.r - 1) + offsetH + widthH;
+ srcArea.b = SafeInt32Add (SafeInt32Add (
+ fRowCoords.Pixel (SafeInt32Sub (dstArea.b, 1)),
+ offsetV),
+ ConvertUint32ToInt32 (widthV));;
+ srcArea.r = SafeInt32Add(SafeInt32Add(
+ fColCoords.Pixel (SafeInt32Sub (dstArea.r, 1)),
+ offsetH),
+ ConvertUint32ToInt32(widthH));;
return srcArea;
@@ -629,6 +630,7 @@ void dng_resample_task::Start (uint32 threadCount,
dng_memory_allocator *allocator,
dng_abort_sniffer *sniffer)
{
+
// Compute sub-pixel resolution coordinates in the source image for
// each row and column of the destination area.
diff --git a/source/dng_resample.h b/source/dng_resample.h
index 9116e6e..9ad13dd 100644
--- a/source/dng_resample.h
+++ b/source/dng_resample.h
@@ -250,7 +250,7 @@ class dng_resample_weights_2d
}
const uint32 offset = fract.v * fRowStep + fract.h * fColStep;
-
+
return fWeights32->Buffer_real32 () + offset;
}
diff --git a/source/dng_safe_arithmetic.cpp b/source/dng_safe_arithmetic.cpp
index 1a4f543..9d3d51d 100644
--- a/source/dng_safe_arithmetic.cpp
+++ b/source/dng_safe_arithmetic.cpp
@@ -33,9 +33,7 @@ T SafeAdd(T arg1, T arg2) {
return arg1 + arg2;
} else {
ThrowProgramError("Arithmetic overflow");
-
- // Dummy return statement.
- return 0;
+ abort(); // Never reached.
}
}
@@ -48,9 +46,7 @@ T SafeUnsignedMult(T arg1, T arg2) {
return arg1 * arg2;
} else {
ThrowProgramError("Arithmetic overflow");
-
- // Dummy return statement.
- return 0;
+ abort(); // Never reached.
}
}
@@ -87,6 +83,10 @@ std::uint32_t SafeUint32Add(std::uint32_t arg1, std::uint32_t arg2) {
return SafeAdd<std::uint32_t>(arg1, arg2);
}
+std::uint64_t SafeUint64Add(std::uint64_t arg1, std::uint64_t arg2) {
+ return SafeAdd<std::uint64_t>(arg1, arg2);
+}
+
bool SafeInt32Sub(std::int32_t arg1, std::int32_t arg2, std::int32_t *result) {
if ((arg2 >= 0 && arg1 >= std::numeric_limits<int32_t>::min() + arg2) ||
(arg2 < 0 && arg1 <= std::numeric_limits<int32_t>::max() + arg2)) {
@@ -107,6 +107,15 @@ std::int32_t SafeInt32Sub(std::int32_t arg1, std::int32_t arg2) {
return result;
}
+std::uint32_t SafeUint32Sub(std::uint32_t arg1, std::uint32_t arg2) {
+ if (arg1 >= arg2) {
+ return arg1 - arg2;
+ } else {
+ ThrowProgramError("Arithmetic overflow");
+ abort(); // Never reached.
+ }
+}
+
bool SafeUint32Mult(std::uint32_t arg1, std::uint32_t arg2,
std::uint32_t *result) {
try {
@@ -151,11 +160,24 @@ std::uint32_t SafeUint32Mult(std::uint32_t arg1, std::uint32_t arg2,
return SafeUint32Mult(SafeUint32Mult(arg1, arg2, arg3), arg4);
}
+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) {
+ return static_cast<std::int32_t>(tmp);
+ } else {
+ ThrowProgramError("Arithmetic overflow");
+ abort();
+ }
+}
+
std::size_t SafeSizetMult(std::size_t arg1, std::size_t arg2) {
return SafeUnsignedMult<std::size_t>(arg1, arg2);
}
-std::int64_t SafeInt64Mult(std::int64_t arg1, std::int64_t arg2) {
+namespace dng_internal {
+
+std::int64_t SafeInt64MultSlow(std::int64_t arg1, std::int64_t arg2) {
bool overflow = true;
if (arg1 > 0) {
@@ -174,14 +196,14 @@ std::int64_t SafeInt64Mult(std::int64_t arg1, std::int64_t arg2) {
if (overflow) {
ThrowProgramError("Arithmetic overflow");
-
- // Dummy return.
- return 0;
+ abort(); // Never reached.
} else {
return arg1 * arg2;
}
}
+} // namespace dng_internal
+
std::uint32_t SafeUint32DivideUp(std::uint32_t arg1, std::uint32_t arg2) {
// It might seem more intuitive to implement this function simply as
//
@@ -191,9 +213,7 @@ std::uint32_t SafeUint32DivideUp(std::uint32_t arg1, std::uint32_t arg2) {
if (arg2 == 0) {
ThrowProgramError("Division by zero");
-
- // Dummy return to avoid compiler error about missing return statement.
- return 0;
+ abort(); // Never reached.
} else if (arg1 == 0) {
// If arg1 is zero, return zero to avoid wraparound in the expression
// "arg1 - 1" below.
@@ -205,27 +225,57 @@ std::uint32_t SafeUint32DivideUp(std::uint32_t arg1, std::uint32_t arg2) {
bool RoundUpUint32ToMultiple(std::uint32_t val, std::uint32_t multiple_of,
std::uint32_t *result) {
- if (multiple_of == 0) {
+ try {
+ *result = RoundUpUint32ToMultiple(val, multiple_of);
+ return true;
+ } catch (const dng_exception &) {
return false;
}
+}
+
+std::uint32_t RoundUpUint32ToMultiple(std::uint32_t val,
+ std::uint32_t multiple_of) {
+ if (multiple_of == 0) {
+ ThrowProgramError("multiple_of is zero in RoundUpUint32ToMultiple");
+ }
const std::uint32_t remainder = val % multiple_of;
if (remainder == 0) {
- *result = val;
- return true;
+ return val;
} else {
- return SafeUint32Add(val, multiple_of - remainder, result);
+ return SafeUint32Add(val, multiple_of - remainder);
}
}
bool ConvertUint32ToInt32(std::uint32_t val, std::int32_t *result) {
+ try {
+ *result = ConvertUint32ToInt32(val);
+ return true;
+ } catch (const dng_exception &) {
+ return false;
+ }
+}
+
+std::int32_t ConvertUint32ToInt32(std::uint32_t val) {
const std::uint32_t kInt32MaxAsUint32 =
static_cast<std::uint32_t>(std::numeric_limits<std::int32_t>::max());
if (val <= kInt32MaxAsUint32) {
- *result = static_cast<std::int32_t>(val);
- return true;
+ return static_cast<std::int32_t>(val);
} else {
- return false;
+ ThrowProgramError("Arithmetic overflow");
+ abort(); // Never reached.
+ }
+}
+
+std::int32_t ConvertDoubleToInt32(double val) {
+ constexpr double kMin = static_cast<double>(INT32_MIN);
+ constexpr double kMax = static_cast<double>(INT32_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);
+ } else {
+ ThrowProgramError("Argument not in range in ConvertDoubleToInt32");
+ abort(); // Never reached.
}
}
diff --git a/source/dng_safe_arithmetic.h b/source/dng_safe_arithmetic.h
index 31c2176..78d8ae0 100644
--- a/source/dng_safe_arithmetic.h
+++ b/source/dng_safe_arithmetic.h
@@ -26,6 +26,14 @@
#include "dng_exceptions.h"
+#ifndef __has_builtin
+#define __has_builtin(x) 0 // Compatibility with non-Clang compilers.
+#endif
+
+#if !defined(DNG_HAS_INT128) && defined(__SIZEOF_INT128__)
+#define DNG_HAS_INT128
+#endif
+
// If the result of adding arg1 and arg2 will fit in an int32_t (without
// under-/overflow), stores this result in *result and returns true. Otherwise,
// returns false and leaves *result unchanged.
@@ -43,10 +51,11 @@ std::int64_t SafeInt64Add(std::int64_t arg1, std::int64_t arg2);
bool SafeUint32Add(std::uint32_t arg1, std::uint32_t arg2,
std::uint32_t *result);
-// Returns the result of adding arg1 and arg2 if it will fit in a uint32_t
+// Returns the result of adding arg1 and arg2 if it will fit in the result type
// (without wraparound). Otherwise, throws a dng_exception with error code
// dng_error_unknown.
std::uint32_t SafeUint32Add(std::uint32_t arg1, std::uint32_t arg2);
+std::uint64_t SafeUint64Add(std::uint64_t arg1, std::uint64_t arg2);
// If the subtraction of arg2 from arg1 will not result in an int32_t under- or
// overflow, stores this result in *result and returns true. Otherwise,
@@ -58,6 +67,16 @@ bool SafeInt32Sub(std::int32_t arg1, std::int32_t arg2, std::int32_t *result);
// with error code dng_error_unknown.
std::int32_t SafeInt32Sub(std::int32_t arg1, std::int32_t arg2);
+// Returns the result of subtracting arg2 from arg1 if this operation will not
+// result in wraparound. Otherwise, throws a dng_exception with error code
+// dng_error_unknown.
+std::uint32_t SafeUint32Sub(std::uint32_t arg1, std::uint32_t arg2);
+
+// Returns the result of multiplying arg1 and arg2 if it will fit in a int32_t
+// (without overflow). Otherwise, throws a dng_exception with error code
+// dng_error_unknown.
+std::int32_t SafeInt32Mult(std::int32_t arg1, std::int32_t arg2);
+
// If the result of multiplying arg1, ..., argn will fit in a uint32_t (without
// wraparound), stores this result in *result and returns true. Otherwise,
// returns false and leaves *result unchanged.
@@ -82,10 +101,57 @@ std::uint32_t SafeUint32Mult(std::uint32_t arg1, std::uint32_t arg2,
// dng_error_unknown.
std::size_t SafeSizetMult(std::size_t arg1, std::size_t arg2);
+namespace dng_internal {
+
+// Internal function used as fallback for SafeInt64Mult() if other optimized
+// computation is not supported. Don't call this function directly.
+std::int64_t SafeInt64MultSlow(std::int64_t arg1, std::int64_t arg2);
+
+// Internal function used as optimization for SafeInt64Mult() if Clang
+// __builtin_smull_overflow is supported. Don't call this function directly.
+#if __has_builtin(__builtin_smull_overflow)
+inline std::int64_t SafeInt64MultByClang(std::int64_t arg1, std::int64_t arg2) {
+ std::int64_t result;
+#if (__WORDSIZE == 64) && !defined(__APPLE__)
+ if (__builtin_smull_overflow(arg1, arg2, &result)) {
+#else
+ if (__builtin_smulll_overflow(arg1, arg2, &result)) {
+#endif
+ ThrowProgramError("Arithmetic overflow");
+ abort(); // Never reached.
+ }
+ return result;
+}
+#endif
+
+// Internal function used as optimization for SafeInt64Mult() if __int128 type
+// is supported. Don't call this function directly.
+#ifdef DNG_HAS_INT128
+inline std::int64_t SafeInt64MultByInt128(std::int64_t arg1,
+ std::int64_t arg2) {
+ __int128 result = static_cast<__int128>(arg1) * static_cast<__int128>(arg2);
+ if (result > static_cast<__int128>(INT64_MAX) ||
+ result < static_cast<__int128>(INT64_MIN)) {
+ ThrowProgramError("Arithmetic overflow");
+ }
+ return static_cast<std::int64_t>(result);
+}
+#endif
+
+} // namespace dng_internal
+
// Returns the result of multiplying arg1 and arg2 if it will fit in an int64_t
// (without overflow). Otherwise, throws a dng_exception with error code
// dng_error_unknown.
-std::int64_t SafeInt64Mult(std::int64_t arg1, std::int64_t arg2);
+inline std::int64_t SafeInt64Mult(std::int64_t arg1, std::int64_t arg2) {
+#if __has_builtin(__builtin_smull_overflow)
+ return dng_internal::SafeInt64MultByClang(arg1, arg2);
+#elif defined(DNG_HAS_INT128)
+ return dng_internal::SafeInt64MultByInt128(arg1, arg2);
+#else
+ return dng_internal::SafeInt64MultSlow(arg1, arg2);
+#endif
+}
// Returns the result of dividing arg1 by arg2; if the result is not an integer,
// rounds up to the next integer. If arg2 is zero, throws a dng_exception with
@@ -101,10 +167,22 @@ std::uint32_t SafeUint32DivideUp(std::uint32_t arg1, std::uint32_t arg2);
bool RoundUpUint32ToMultiple(std::uint32_t val, std::uint32_t multiple_of,
std::uint32_t *result);
+// Returns the smallest integer multiple of 'multiple_of' that is greater than
+// or equal to 'val'. If the result will not fit in a std::uint32_t or if
+// 'multiple_of' is zero, throws a dng_exception with error code
+// dng_error_unknown.
+std::uint32_t RoundUpUint32ToMultiple(std::uint32_t val,
+ std::uint32_t multiple_of);
+
// If the uint32_t value val will fit in a int32_t, converts it to a int32_t and
// stores it in *result. Otherwise, returns false and leaves *result unchanged.
bool ConvertUint32ToInt32(std::uint32_t val, std::int32_t *result);
+// Returns the result of converting val to an int32_t if it can be converted
+// without overflow. Otherwise, throws a dng_exception with error code
+// dng_error_unknown.
+std::int32_t ConvertUint32ToInt32(std::uint32_t val);
+
// Converts a value of the unsigned integer type TSrc to the unsigned integer
// type TDest. If the value in 'src' cannot be converted to the type TDest
// without truncation, throws a dng_exception with error code dng_error_unknown.
@@ -135,4 +213,9 @@ static void ConvertUnsigned(TSrc src, TDest *dest) {
*dest = converted;
}
+// Returns the result of converting val to an int32_t using truncation if val is
+// in range of int32_t values. Otherwise, throws a dng_exception with error code
+// dng_error_unknown.
+std::int32_t ConvertDoubleToInt32(double val);
+
#endif // __dng_safe_arithmetic__
diff --git a/source/dng_shared.cpp b/source/dng_shared.cpp
index 5384116..961ac1f 100644
--- a/source/dng_shared.cpp
+++ b/source/dng_shared.cpp
@@ -20,6 +20,7 @@
#include "dng_globals.h"
#include "dng_memory.h"
#include "dng_parse_utils.h"
+#include "dng_safe_arithmetic.h"
#include "dng_tag_codes.h"
#include "dng_tag_types.h"
#include "dng_tag_values.h"
@@ -96,11 +97,6 @@ dng_camera_profile_info::~dng_camera_profile_info ()
/*****************************************************************************/
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
bool dng_camera_profile_info::ParseTag (dng_stream &stream,
uint32 parentCode,
uint32 tagCode,
@@ -588,9 +584,11 @@ bool dng_camera_profile_info::ParseTag (dng_stream &stream,
if (!CheckTagType (parentCode, tagCode, tagType, ttFloat))
return false;
- bool skipSat0 = (tagCount == fProfileHues *
- (fProfileSats - 1) *
- fProfileVals * 3);
+ bool skipSat0 = (tagCount ==
+ SafeUint32Mult(fProfileHues,
+ SafeUint32Sub(fProfileSats, 1u),
+ fProfileVals,
+ 3u));
if (!skipSat0)
{
@@ -634,9 +632,11 @@ bool dng_camera_profile_info::ParseTag (dng_stream &stream,
if (!CheckTagType (parentCode, tagCode, tagType, ttFloat))
return false;
- bool skipSat0 = (tagCount == fProfileHues *
- (fProfileSats - 1) *
- fProfileVals * 3);
+ bool skipSat0 = (tagCount ==
+ SafeUint32Mult(fProfileHues,
+ SafeUint32Sub(fProfileSats, 1u),
+ fProfileVals,
+ 3u));
if (!skipSat0)
{
@@ -755,9 +755,11 @@ bool dng_camera_profile_info::ParseTag (dng_stream &stream,
if (!CheckTagType (parentCode, tagCode, tagType, ttFloat))
return false;
- bool skipSat0 = (tagCount == fLookTableHues *
- (fLookTableSats - 1) *
- fLookTableVals * 3);
+ bool skipSat0 = (tagCount ==
+ SafeUint32Mult(fLookTableHues,
+ SafeUint32Sub(fLookTableSats, 1u),
+ fLookTableVals,
+ 3u));
if (!skipSat0)
{
@@ -1028,11 +1030,6 @@ bool dng_camera_profile_info::ParseTag (dng_stream &stream,
/*****************************************************************************/
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
bool dng_camera_profile_info::ParseExtended (dng_stream &stream)
{
@@ -1069,7 +1066,7 @@ bool dng_camera_profile_info::ParseExtended (dng_stream &stream)
uint32 offset = stream.Get_uint32 ();
- stream.Skip (offset - 8);
+ stream.Skip (SafeUint32Sub(offset, 8u));
// Start on IFD entries.
@@ -1091,7 +1088,7 @@ bool dng_camera_profile_info::ParseExtended (dng_stream &stream)
uint64 tagOffset = stream.Position ();
- if (TagTypeSize (tagType) * tagCount > 4)
+ if (SafeUint32Mult(TagTypeSize (tagType), tagCount) > 4)
{
tagOffset = startPosition + stream.Get_uint32 ();
@@ -1353,7 +1350,8 @@ bool dng_shared::Parse_ifd0 (dng_stream &stream,
CheckTagType (parentCode, tagCode, tagType, ttLong, ttAscii, ttUndefined);
- fIPTC_NAA_Count = SafeUint32Mult(tagCount, TagTypeSize(tagType));
+ fIPTC_NAA_Count = SafeUint32Mult(tagCount,
+ TagTypeSize(tagType));
fIPTC_NAA_Offset = fIPTC_NAA_Count ? tagOffset : 0;
#if qDNGValidate
diff --git a/source/dng_simple_image.cpp b/source/dng_simple_image.cpp
index 46d0011..ac8e1dc 100644
--- a/source/dng_simple_image.cpp
+++ b/source/dng_simple_image.cpp
@@ -182,3 +182,4 @@ void dng_simple_image::AcquireTileBuffer (dng_tile_buffer &buffer,
}
/*****************************************************************************/
+
diff --git a/source/dng_string.cpp b/source/dng_string.cpp
index af8514d..60e7d74 100644
--- a/source/dng_string.cpp
+++ b/source/dng_string.cpp
@@ -86,6 +86,11 @@ static void CheckSpaceLeftInBuffer(const T *currentPos,
// to the following Mac-OS- and Windows-specific functions. Calls to
// ThrowNotHardened() have been added to these functions to alert callers of
// this fact.
+//
+// If you're trying to use a function that calls ThrowNotHardened(), you need to
+// fix the security issues noted in the comment next to the ThrowNotHardened()
+// call. Once you have fixed these issues, obtain a security review for the
+// fixes. This may require fuzzing of the modified code on the target platform.
static void ThrowNotHardened()
{
ThrowProgramError ("This function has not been security-hardened");
@@ -97,6 +102,7 @@ static void ThrowNotHardened()
static uint32 Extract_SystemEncoding (const dng_string &dngString,
dng_memory_data &buffer)
{
+ // TODO: Needs implementation.
ThrowProgramError ("Extract_SystemEncoding() not implemented on iOS");
return 0;
}
@@ -104,6 +110,7 @@ static uint32 Extract_SystemEncoding (const dng_string &dngString,
static void Assign_SystemEncoding (dng_string &dngString,
const char *otherString)
{
+ // TODO: Needs implementation.
ThrowProgramError ("Assign_SystemEncoding() not implemented on iOS");
}
@@ -111,6 +118,7 @@ static void Assign_SystemEncoding (dng_string &dngString,
static void Assign_JIS_X208_1990 (dng_string &dngString,
const char *otherString)
{
+ // TODO: Needs implementation.
ThrowProgramError ("Assign_JIS_X208_1990() not implemented on iOS");
}
@@ -128,7 +136,7 @@ static void Assign_Multibyte (dng_string &dngString,
// - The computation of aBufSize and the subsequent addition of 1 in the
// call to the dng_memory_data constructor may wrap around.
ThrowNotHardened();
-
+
uint32 aSize = (uint32) strlen (otherString);
if (aSize > 0)
@@ -901,11 +909,6 @@ void dng_string::Set_JIS_X208_1990 (const char *s)
/*****************************************************************************/
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
uint32 dng_string::DecodeUTF8 (const char *&s,
uint32 maxBytes,
bool *isValid)
@@ -920,7 +923,7 @@ uint32 dng_string::DecodeUTF8 (const char *&s,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
- 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,6,6
+ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,0,0
};
if (isValid)
@@ -2182,6 +2185,7 @@ int32 dng_string::Compare (const dng_string &s) const
#if qMacOS
#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
+ // TODO: Needs implementation.
ThrowProgramError ("Compare() not implemented on iOS");
return 0;
@@ -2272,6 +2276,7 @@ int32 dng_string::Compare (const dng_string &s) const
}
#endif // TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
+
#elif qWinOS
{
diff --git a/source/dng_types.h b/source/dng_types.h
index f59771d..2baeb4e 100644
--- a/source/dng_types.h
+++ b/source/dng_types.h
@@ -32,7 +32,11 @@
/*****************************************************************************/
-#if qDNGUseStdInt || 1
+#if qDNGUseCustomIntegralTypes
+
+#include "dng_custom_integral_types.h"
+
+#elif qDNGUseStdInt || 1
typedef int8_t int8;
typedef int16_t int16;
diff --git a/source/dng_utils.cpp b/source/dng_utils.cpp
index daf85f5..bf129c1 100644
--- a/source/dng_utils.cpp
+++ b/source/dng_utils.cpp
@@ -171,6 +171,7 @@ uint32 ComputeBufferSize(uint32 pixelType, const dng_point &tileSize,
uint32 numPlanes, PaddingType paddingType)
{
+
// Convert tile size to uint32.
if (tileSize.h < 0 || tileSize.v < 0)
{
@@ -311,7 +312,7 @@ real64 TickCountInSeconds ()
// TODO: Needs implementation.
ThrowProgramError ("TickCountInSeconds() not implemented on iOS");
return 0;
- #else
+ #else
return TickCount () * (1.0 / 60.0);
#endif // TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
diff --git a/source/dng_utils.h b/source/dng_utils.h
index 218831d..d945a6e 100644
--- a/source/dng_utils.h
+++ b/source/dng_utils.h
@@ -225,7 +225,7 @@ inline bool RoundUpForPixelSize (uint32 x, uint32 pixelSize, uint32 *result)
default:
multiple = 16;
break;
-
+
}
return RoundUpUint32ToMultiple(x, multiple, result);
@@ -467,11 +467,6 @@ inline real64 Lerp_real64 (real64 a, real64 b, real64 t)
/*****************************************************************************/
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("float-cast-overflow")))
-#endif
-#endif
inline int32 Round_int32 (real32 x)
{
@@ -482,7 +477,21 @@ inline int32 Round_int32 (real32 x)
inline int32 Round_int32 (real64 x)
{
- return (int32) (x > 0.0 ? x + 0.5 : x - 0.5);
+ const real64 temp = x > 0.0 ? x + 0.5 : x - 0.5;
+
+ // 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)
+ {
+ return (int32) temp;
+ }
+
+ else
+ {
+ ThrowProgramError("Overflow in Round_int32");
+ // Dummy return.
+ return 0;
+ }
}
@@ -493,15 +502,24 @@ inline uint32 Floor_uint32 (real32 x)
}
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("float-cast-overflow")))
-#endif
-#endif
inline uint32 Floor_uint32 (real64 x)
{
- return (uint32) Max_real64 (0.0, x);
+ const real64 temp = Max_real64 (0.0, x);
+
+ // 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)
+ {
+ return (uint32) temp;
+ }
+
+ else
+ {
+ ThrowProgramError("Overflow in Floor_uint32");
+ // Dummy return.
+ return 0;
+ }
}
@@ -1146,7 +1164,8 @@ inline int32 Mulsh86 (int32 x, int32 y)
// This is the ACM standard 30 bit generator:
// x' = (x * 16807) mod 2^31-1
-
+// This function intentionally exploits the defined behavior of unsigned integer
+// overflow.
#if defined(__clang__) && defined(__has_attribute)
#if __has_attribute(no_sanitize)
__attribute__((no_sanitize("unsigned-integer-overflow")))