summaryrefslogtreecommitdiff
path: root/ext/exif
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-12-17 13:15:01 +0100
committerNikita Popov <nikita.ppv@gmail.com>2019-12-17 13:26:05 +0100
commitdd997a40d0be9b03973b1317041f92ad9582237f (patch)
treeb6ab04543385f2667e6edb8ab38a460fb698d544 /ext/exif
parentddd6e68ef9dcd138089ee1595d3ddcdf0b81e2f3 (diff)
downloadphp-git-dd997a40d0be9b03973b1317041f92ad9582237f.tar.gz
Avoid float to int cast UB in exif
Diffstat (limited to 'ext/exif')
-rw-r--r--ext/exif/exif.c25
-rw-r--r--ext/exif/tests/float_cast_overflow.phpt43
-rw-r--r--ext/exif/tests/float_cast_overflow.tiffbin0 -> 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
new file mode 100644
index 0000000000..faebc8eaa1
--- /dev/null
+++ b/ext/exif/tests/float_cast_overflow.tiff
Binary files differ