diff options
author | Stanislav Malyshev <stas@php.net> | 2019-04-02 00:12:26 -0700 |
---|---|---|
committer | Sara Golemon <pollita@php.net> | 2019-04-02 11:01:16 -0400 |
commit | 330f1716df49c0d3474c18b6dcd370a9dcf57422 (patch) | |
tree | 6a905cff8b4200ec26f2e06b29b3b67be430585a | |
parent | 1c0d06441aefee18b30520e2b1ae89cbfcf56a59 (diff) | |
download | php-git-330f1716df49c0d3474c18b6dcd370a9dcf57422.tar.gz |
Fixed bug #77831 - Heap-buffer-overflow in exif_iif_add_value in EXIF
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | ext/exif/exif.c | 43 | ||||
-rw-r--r-- | ext/exif/tests/bug77831.phpt | 13 | ||||
-rw-r--r-- | ext/exif/tests/bug77831.tiff | bin | 0 -> 49 bytes |
4 files changed, 45 insertions, 15 deletions
@@ -23,6 +23,10 @@ PHP NEWS . Fixed bug #75113 (Added DatePeriod::getRecurrences() method). (Ignace Nyamagana Butera) +- EXIF: + . Fixed bug #77753 (Heap-buffer-overflow in php_ifd_get32s). (Stas) + . Fixed bug #77831 (Heap-buffer-overflow in exif_iif_add_value). (Stas) + - FPM: . Fixed bug #77677 (FPM fails to build on AIX due to missing WCOREDUMP). (Kevin Adler) diff --git a/ext/exif/exif.c b/ext/exif/exif.c index 407145fffc..75f59d71c9 100644 --- a/ext/exif/exif.c +++ b/ext/exif/exif.c @@ -2062,10 +2062,10 @@ static int exif_file_sections_free(image_info_type *ImageInfo) /* {{{ exif_iif_add_value Add a value to image_info */ -static void exif_iif_add_value(image_info_type *image_info, int section_index, char *name, int tag, int format, int length, void* value, int motorola_intel) +static void exif_iif_add_value(image_info_type *image_info, int section_index, char *name, int tag, int format, int length, void* value, size_t value_len, int motorola_intel) { size_t idex; - void *vptr; + void *vptr, *vptr_end; image_info_value *info_value; image_info_data *info_data; image_info_data *list; @@ -2087,8 +2087,12 @@ static void exif_iif_add_value(image_info_type *image_info, int section_index, c switch (format) { case TAG_FMT_STRING: + if (length > value_len) { + exif_error_docref("exif_iif_add_value" EXIFERR_CC, image_info, E_WARNING, "length > value_len: %d > %zu", length, value_len); + value = NULL; + } if (value) { - length = php_strnlen(value, length); + length = (int)php_strnlen(value, length); info_value->s = estrndup(value, length); info_data->length = length; } else { @@ -2110,6 +2114,10 @@ static void exif_iif_add_value(image_info_type *image_info, int section_index, c if (!length) break; case TAG_FMT_UNDEFINED: + if (length > value_len) { + exif_error_docref("exif_iif_add_value" EXIFERR_CC, image_info, E_WARNING, "length > value_len: %d > %zu", length, value_len); + value = NULL; + } if (value) { if (tag == TAG_MAKER_NOTE) { length = (int) php_strnlen(value, length); @@ -2140,7 +2148,12 @@ static void exif_iif_add_value(image_info_type *image_info, int section_index, c } else { info_value = &info_data->value; } + vptr_end = value+value_len; for (idex=0,vptr=value; idex<(size_t)length; idex++,vptr=(char *) vptr + php_tiff_bytes_per_format[format]) { + if (vptr_end - vptr < php_tiff_bytes_per_format[format]) { + exif_error_docref("exif_iif_add_value" EXIFERR_CC, image_info, E_WARNING, "Value too short"); + break; + } if (length>1) { info_value = &info_data->value.list[idex]; } @@ -2176,7 +2189,7 @@ static void exif_iif_add_value(image_info_type *image_info, int section_index, c php_error_docref(NULL, E_WARNING, "Found value of type single"); #endif info_value->f = *(float *)value; - + break; case TAG_FMT_DOUBLE: #ifdef EXIF_DEBUG php_error_docref(NULL, E_WARNING, "Found value of type double"); @@ -2194,9 +2207,9 @@ static void exif_iif_add_value(image_info_type *image_info, int section_index, c /* {{{ exif_iif_add_tag Add a tag from IFD to image_info */ -static void exif_iif_add_tag(image_info_type *image_info, int section_index, char *name, int tag, int format, size_t length, void* value) +static void exif_iif_add_tag(image_info_type *image_info, int section_index, char *name, int tag, int format, size_t length, void* value, size_t value_len) { - exif_iif_add_value(image_info, section_index, name, tag, format, (int)length, value, image_info->motorola_intel); + exif_iif_add_value(image_info, section_index, name, tag, format, (int)length, value, value_len, image_info->motorola_intel); } /* }}} */ @@ -2617,7 +2630,7 @@ static void add_assoc_image_info(zval *value, int sub_array, image_info_type *im */ static void exif_process_COM (image_info_type *image_info, char *value, size_t length) { - exif_iif_add_tag(image_info, SECTION_COMMENT, "Comment", TAG_COMPUTED_VALUE, TAG_FMT_STRING, length-2, value+2); + exif_iif_add_tag(image_info, SECTION_COMMENT, "Comment", TAG_COMPUTED_VALUE, TAG_FMT_STRING, length-2, value+2, length-2); } /* }}} */ @@ -2632,17 +2645,17 @@ static void exif_process_CME (image_info_type *image_info, char *value, size_t l if (length>3) { switch(value[2]) { case 0: - exif_iif_add_tag(image_info, SECTION_COMMENT, "Comment", TAG_COMPUTED_VALUE, TAG_FMT_UNDEFINED, length, value); + exif_iif_add_tag(image_info, SECTION_COMMENT, "Comment", TAG_COMPUTED_VALUE, TAG_FMT_UNDEFINED, length, value), length; break; case 1: - exif_iif_add_tag(image_info, SECTION_COMMENT, "Comment", TAG_COMPUTED_VALUE, TAG_FMT_STRING, length, value); + exif_iif_add_tag(image_info, SECTION_COMMENT, "Comment", TAG_COMPUTED_VALUE, TAG_FMT_STRING, length, value, length); break; default: php_error_docref(NULL, E_NOTICE, "Undefined JPEG2000 comment encoding"); break; } } else { - exif_iif_add_tag(image_info, SECTION_COMMENT, "Comment", TAG_COMPUTED_VALUE, TAG_FMT_UNDEFINED, 0, NULL); + exif_iif_add_tag(image_info, SECTION_COMMENT, "Comment", TAG_COMPUTED_VALUE, TAG_FMT_UNDEFINED, 0, NULL, 0); php_error_docref(NULL, E_NOTICE, "JPEG2000 comment section too small"); } } @@ -3240,7 +3253,7 @@ static int exif_process_IFD_in_MAKERNOTE(image_info_type *ImageInfo, char * valu static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, char *offset_base, size_t IFDlength, size_t displacement, int section_index, int ReadNextIFD, tag_table_type tag_table) { size_t length; - int tag, format, components; + unsigned int tag, format, components; char *value_ptr, tagname[64], cbuf[32], *outside=NULL; size_t byte_count, offset_val, fpos, fgot; int64_t byte_count_signed; @@ -3555,7 +3568,7 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha } } } - exif_iif_add_tag(ImageInfo, section_index, exif_get_tagname(tag, tagname, sizeof(tagname), tag_table), tag, format, components, value_ptr); + exif_iif_add_tag(ImageInfo, section_index, exif_get_tagname(tag, tagname, sizeof(tagname), tag_table), tag, format, components, value_ptr, byte_count); EFREE_IF(outside); return TRUE; } @@ -3717,10 +3730,10 @@ static void exif_process_APP12(image_info_type *ImageInfo, char *buffer, size_t size_t l1, l2=0; if ((l1 = php_strnlen(buffer+2, length-2)) > 0) { - exif_iif_add_tag(ImageInfo, SECTION_APP12, "Company", TAG_NONE, TAG_FMT_STRING, l1, buffer+2); + exif_iif_add_tag(ImageInfo, SECTION_APP12, "Company", TAG_NONE, TAG_FMT_STRING, l1, buffer+2, l1); if (length > 2+l1+1) { l2 = php_strnlen(buffer+2+l1+1, length-2-l1-1); - exif_iif_add_tag(ImageInfo, SECTION_APP12, "Info", TAG_NONE, TAG_FMT_STRING, l2, buffer+2+l1+1); + exif_iif_add_tag(ImageInfo, SECTION_APP12, "Info", TAG_NONE, TAG_FMT_STRING, l2, buffer+2+l1+1, l2); } } #ifdef EXIF_DEBUG @@ -4588,7 +4601,7 @@ PHP_FUNCTION(exif_read_data) if (ImageInfo.Thumbnail.size) { if (read_thumbnail) { /* not exif_iif_add_str : this is a buffer */ - exif_iif_add_tag(&ImageInfo, SECTION_THUMBNAIL, "THUMBNAIL", TAG_NONE, TAG_FMT_UNDEFINED, ImageInfo.Thumbnail.size, ImageInfo.Thumbnail.data); + exif_iif_add_tag(&ImageInfo, SECTION_THUMBNAIL, "THUMBNAIL", TAG_NONE, TAG_FMT_UNDEFINED, ImageInfo.Thumbnail.size, ImageInfo.Thumbnail.data, ImageInfo.Thumbnail.size); } if (!ImageInfo.Thumbnail.width || !ImageInfo.Thumbnail.height) { /* try to evaluate if thumbnail data is present */ diff --git a/ext/exif/tests/bug77831.phpt b/ext/exif/tests/bug77831.phpt new file mode 100644 index 0000000000..d868d47a1f --- /dev/null +++ b/ext/exif/tests/bug77831.phpt @@ -0,0 +1,13 @@ +--TEST-- +Bug #77831 (Heap-buffer-overflow in exif_iif_add_value in EXIF) +--SKIPIF-- +<?php if (!extension_loaded('exif')) print 'skip exif extension not available';?> +--FILE-- +<?php +var_dump(exif_read_data(__DIR__."/bug77831.tiff")); +?> +DONE +--EXPECTF-- +%A +bool(false) +DONE
\ No newline at end of file diff --git a/ext/exif/tests/bug77831.tiff b/ext/exif/tests/bug77831.tiff Binary files differnew file mode 100644 index 0000000000..c7e9f4472b --- /dev/null +++ b/ext/exif/tests/bug77831.tiff |