#define EFREE_IF(ptr) if (ptr) efree(ptr)
-#define MAX_IFD_NESTING_LEVEL 200
+#define MAX_IFD_NESTING_LEVEL 10
+#define MAX_IFD_TAGS 1000
/* {{{ arginfo */
ZEND_BEGIN_ARG_INFO(arginfo_exif_tagname, 0)
int read_thumbnail;
int read_all;
int ifd_nesting_level;
+ int ifd_count;
/* internal */
file_section_list file;
} image_info_type;
/* forward declarations */
static int exif_process_IFD_in_JPEG(image_info_type *ImageInfo, char *dir_start, char *offset_base, size_t IFDlength, size_t displacement, int section_index, int tag);
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);
+static int exif_process_IFD_in_TIFF(image_info_type *ImageInfo, size_t dir_offset, int section_index);
/* {{{ exif_get_markername
Get name of marker */
/* {{{ exif_process_IFD_TAG
* Process one of the nested IFDs directories. */
-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)
+static int exif_process_IFD_TAG_impl(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;
unsigned int tag, format, components;
int dump_free;
#endif /* EXIF_DEBUG */
- /* Protect against corrupt headers */
- if (ImageInfo->ifd_nesting_level > MAX_IFD_NESTING_LEVEL) {
- exif_error_docref("exif_read_data#error_ifd" EXIFERR_CC, ImageInfo, E_WARNING, "corrupt EXIF header: maximum directory nesting level reached");
- return FALSE;
- }
- ImageInfo->ifd_nesting_level++;
-
tag = php_ifd_get16u(dir_entry, ImageInfo->motorola_intel);
format = php_ifd_get16u(dir_entry+2, ImageInfo->motorola_intel);
components = php_ifd_get32u(dir_entry+4, ImageInfo->motorola_intel);
}
/* }}} */
+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)
+{
+ int result;
+ /* Protect against corrupt headers */
+ if (ImageInfo->ifd_count++ > MAX_IFD_TAGS) {
+ exif_error_docref("exif_read_data#error_ifd" EXIFERR_CC, ImageInfo, E_WARNING, "corrupt EXIF header: maximum IFD tag count reached");
+ return FALSE;
+ }
+ if (ImageInfo->ifd_nesting_level > MAX_IFD_NESTING_LEVEL) {
+ exif_error_docref("exif_read_data#error_ifd" EXIFERR_CC, ImageInfo, E_WARNING, "corrupt EXIF header: maximum directory nesting level reached");
+ return FALSE;
+ }
+ ImageInfo->ifd_nesting_level++;
+ result = exif_process_IFD_TAG_impl(ImageInfo, dir_entry, offset_base, IFDlength, displacement, section_index, ReadNextIFD, tag_table);
+ ImageInfo->ifd_nesting_level--;
+ return result;
+}
+
/* {{{ exif_process_IFD_in_JPEG
* Process one of the nested IFDs directories. */
static int exif_process_IFD_in_JPEG(image_info_type *ImageInfo, char *dir_start, char *offset_base, size_t IFDlength, size_t displacement, int section_index, int tag)
/* {{{ exif_process_IFD_in_TIFF
* Parse the TIFF header; */
-static int exif_process_IFD_in_TIFF(image_info_type *ImageInfo, size_t dir_offset, int section_index)
+static int exif_process_IFD_in_TIFF_impl(image_info_type *ImageInfo, size_t dir_offset, int section_index)
{
int i, sn, num_entries, sub_section_index = 0;
unsigned char *dir_entry;
int entry_tag , entry_type;
tag_table_type tag_table = exif_get_tag_table(section_index);
- if (ImageInfo->ifd_nesting_level > MAX_IFD_NESTING_LEVEL) {
- return FALSE;
- }
-
if (ImageInfo->FileSize >= 2 && ImageInfo->FileSize - 2 >= dir_offset) {
sn = exif_file_sections_add(ImageInfo, M_PSEUDO, 2, NULL);
#ifdef EXIF_DEBUG
#ifdef EXIF_DEBUG
exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_NOTICE, "Next IFD: %s @x%04X", exif_get_sectionname(sub_section_index), entry_offset);
#endif
- ImageInfo->ifd_nesting_level++;
exif_process_IFD_in_TIFF(ImageInfo, entry_offset, sub_section_index);
if (section_index!=SECTION_THUMBNAIL && entry_tag==TAG_SUB_IFD) {
if (ImageInfo->Thumbnail.filetype != IMAGE_FILETYPE_UNKNOWN
#ifdef EXIF_DEBUG
exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_NOTICE, "Read next IFD (THUMBNAIL) at x%04X", next_offset);
#endif
- ImageInfo->ifd_nesting_level++;
exif_process_IFD_in_TIFF(ImageInfo, next_offset, SECTION_THUMBNAIL);
#ifdef EXIF_DEBUG
exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_NOTICE, "%s THUMBNAIL @0x%04X + 0x%04X", ImageInfo->Thumbnail.data ? "Ignore" : "Read", ImageInfo->Thumbnail.offset, ImageInfo->Thumbnail.size);
}
/* }}} */
+static int exif_process_IFD_in_TIFF(image_info_type *ImageInfo, size_t dir_offset, int section_index)
+{
+ int result;
+ if (ImageInfo->ifd_count++ > MAX_IFD_TAGS) {
+ return FALSE;
+ }
+ if (ImageInfo->ifd_nesting_level > MAX_IFD_NESTING_LEVEL) {
+ return FALSE;
+ }
+ ImageInfo->ifd_nesting_level++;
+ result = exif_process_IFD_in_TIFF_impl(ImageInfo, dir_offset, section_index);
+ ImageInfo->ifd_nesting_level--;
+ return result;
+}
+
/* {{{ exif_scan_FILE_header
* Parse the marker stream until SOS or EOI is seen; */
static int exif_scan_FILE_header(image_info_type *ImageInfo)
ImageInfo->ifd_nesting_level = 0;
+ ImageInfo->ifd_count = 0;
/* Scan the headers */
ret = exif_scan_FILE_header(ImageInfo);