diff --git a/ext/exif/exif.c b/ext/exif/exif.c index b686ec2fd4f..4f8b8af7191 100644 --- a/ext/exif/exif.c +++ b/ext/exif/exif.c @@ -1697,6 +1697,27 @@ static int exif_rewrite_tag_format_to_unsigned(int format) } /* }}} */ +/* Use saturation for out of bounds values to avoid UB */ +static size_t float_to_size_t(float x) { + if (x < 0.0f) { + return 0; + } else if (x > (float) SIZE_MAX) { + return SIZE_MAX; + } else { + return (size_t) x; + } +} + +static size_t double_to_size_t(double x) { + if (x < 0.0) { + return 0; + } else if (x > (double) SIZE_MAX) { + return SIZE_MAX; + } else { + return (size_t) x; + } +} + /* {{{ exif_convert_any_to_int * Evaluate number, be it int, rational, or float from directory. */ static size_t exif_convert_any_to_int(void *value, int format, int motorola_intel) @@ -1735,12 +1756,12 @@ static size_t exif_convert_any_to_int(void *value, int format, int motorola_inte #ifdef EXIF_DEBUG php_error_docref(NULL, E_NOTICE, "Found value of type single"); #endif - return (size_t) php_ifd_get_float(value); + return float_to_size_t(php_ifd_get_float(value)); case TAG_FMT_DOUBLE: #ifdef EXIF_DEBUG php_error_docref(NULL, E_NOTICE, "Found value of type double"); #endif - return (size_t) php_ifd_get_double(value); + return double_to_size_t(php_ifd_get_double(value)); } return 0; } diff --git a/ext/exif/tests/float_cast_overflow.phpt b/ext/exif/tests/float_cast_overflow.phpt new file mode 100644 index 00000000000..112191437dc --- /dev/null +++ b/ext/exif/tests/float_cast_overflow.phpt @@ -0,0 +1,43 @@ +--TEST-- +Overflow in float to int cast +--FILE-- + +--EXPECTF-- +array(8) { + ["FileName"]=> + string(24) "float_cast_overflow.tiff" + ["FileDateTime"]=> + int(%d) + ["FileSize"]=> + int(142) + ["FileType"]=> + int(7) + ["MimeType"]=> + string(10) "image/tiff" + ["SectionsFound"]=> + string(24) "ANY_TAG, IFD0, THUMBNAIL" + ["COMPUTED"]=> + array(5) { + ["html"]=> + string(20) "width="1" height="1"" + ["Height"]=> + int(1) + ["Width"]=> + int(1) + ["IsColor"]=> + int(0) + ["ByteOrderMotorola"]=> + int(0) + } + ["THUMBNAIL"]=> + array(2) { + ["ImageWidth"]=> + int(1) + ["ImageLength"]=> + float(-2.5961487387524E+33) + } +} diff --git a/ext/exif/tests/float_cast_overflow.tiff b/ext/exif/tests/float_cast_overflow.tiff new file mode 100644 index 00000000000..faebc8eaa12 Binary files /dev/null and b/ext/exif/tests/float_cast_overflow.tiff differ