From dd997a40d0be9b03973b1317041f92ad9582237f Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 17 Dec 2019 13:15:01 +0100 Subject: [PATCH] Avoid float to int cast UB in exif --- ext/exif/exif.c | 25 ++++++++++++-- ext/exif/tests/float_cast_overflow.phpt | 43 ++++++++++++++++++++++++ ext/exif/tests/float_cast_overflow.tiff | Bin 0 -> 142 bytes 3 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 ext/exif/tests/float_cast_overflow.phpt create mode 100644 ext/exif/tests/float_cast_overflow.tiff 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 0000000000000000000000000000000000000000..faebc8eaa12c022cf067be602c82984c74a35524 GIT binary patch literal 142 zcmebD)MDshU|?WjU|?isU<9(jn2{UC{>}sxXL!QSz%bWR!O9efj2UDZ1Q=L>N*fpy b6o3>55W|6nAe;$f%=r&uK@`Ic!fFZtT`3HB literal 0 HcmV?d00001