diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2019-12-17 13:15:01 +0100 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2019-12-17 13:26:05 +0100 |
commit | dd997a40d0be9b03973b1317041f92ad9582237f (patch) | |
tree | b6ab04543385f2667e6edb8ab38a460fb698d544 /ext/exif | |
parent | ddd6e68ef9dcd138089ee1595d3ddcdf0b81e2f3 (diff) | |
download | php-git-dd997a40d0be9b03973b1317041f92ad9582237f.tar.gz |
Avoid float to int cast UB in exif
Diffstat (limited to 'ext/exif')
-rw-r--r-- | ext/exif/exif.c | 25 | ||||
-rw-r--r-- | ext/exif/tests/float_cast_overflow.phpt | 43 | ||||
-rw-r--r-- | ext/exif/tests/float_cast_overflow.tiff | bin | 0 -> 142 bytes |
3 files changed, 66 insertions, 2 deletions
diff --git a/ext/exif/exif.c b/ext/exif/exif.c index b686ec2fd4..4f8b8af719 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 0000000000..112191437d --- /dev/null +++ b/ext/exif/tests/float_cast_overflow.phpt @@ -0,0 +1,43 @@ +--TEST-- +Overflow in float to int cast +--FILE-- +<?php + +var_dump(@exif_read_data(__DIR__ . '/float_cast_overflow.tiff')); + +?> +--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 Binary files differnew file mode 100644 index 0000000000..faebc8eaa1 --- /dev/null +++ b/ext/exif/tests/float_cast_overflow.tiff |