diff options
author | Marcus Boerger <helly@php.net> | 2002-03-11 19:04:29 +0000 |
---|---|---|
committer | Marcus Boerger <helly@php.net> | 2002-03-11 19:04:29 +0000 |
commit | 8ec3b4740247030db06890875eb683fff37f3148 (patch) | |
tree | 07b69bdbca0777efd2d6320778191313453d037e | |
parent | f893cc65e1dcf08e4d1a3958b1c39e26758b761a (diff) | |
download | php-git-8ec3b4740247030db06890875eb683fff37f3148.tar.gz |
-fixes: memory handling & corrupted files
#don't worry i spend the whole day merging code
#and differenciating what was new functionality and what are
#necessary fixes.
-rw-r--r-- | ext/exif/exif.c | 223 | ||||
-rw-r--r-- | ext/standard/image.c | 70 | ||||
-rw-r--r-- | ext/standard/php_image.h | 3 |
3 files changed, 212 insertions, 84 deletions
diff --git a/ext/exif/exif.c b/ext/exif/exif.c index e690686a34..78a5b5821a 100644 --- a/ext/exif/exif.c +++ b/ext/exif/exif.c @@ -61,7 +61,7 @@ * while extending the module as it shows if you are at the right position. * You are always considered to have a copy of TIFF6.0 and EXIF 2.10 standard. */ -#undef EXIF_DEBUG /**/ +#undef EXIF_DEBUG #include "php_exif.h" #include <math.h> @@ -159,6 +159,7 @@ static int php_tiff_bytes_per_format[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8} #define TAG_FMT_SINGLE 11 #define TAG_FMT_DOUBLE 12 +#ifdef EXIF_DEBUG static char *exif_get_tagformat(int format) { switch(format) { @@ -177,6 +178,7 @@ static char *exif_get_tagformat(int format) } return "*Illegal"; } +#endif /* Describes tag values */ #define TAG_TIFF_COMMENT 0x00FE /* SHOUDLNT HAPPEN */ @@ -702,6 +704,7 @@ typedef struct { time_t FileDateTime; size_t FileSize; image_filetype FileType; + FILE *infile; int Height, Width; int IsColor; @@ -763,10 +766,19 @@ void exif_add_image_info( image_info_type *image_info, int section_index, char * break; case TAG_FMT_STRING: - length = php_strnlen(value,length); - info_value->value.s = emalloc(length+1); - strcpy(info_value->value.s,value); - info_value->length = length; + if ( value) { + length = php_strnlen(value,length); + info_value->length = length; + info_value->value.s = estrndup(value,length); + } else { + info_value->length = 0; + info_value->value.s = estrdup(""); + } + if ( !info_value->value.s) { + info_value->length = 0; + php_error(E_WARNING, "Could not allocate memory for thumbnail"); + return; + } break; case TAG_FMT_USHORT: @@ -794,10 +806,17 @@ void exif_add_image_info( image_info_type *image_info, int section_index, char * */ info_value->tag = TAG_FMT_UNDEFINED;/* otherwise not freed from memory */ case TAG_FMT_UNDEFINED: - info_value->value.s = emalloc(length+1); - memcpy(info_value->value.s,value,length); - info_value->value.s[length] = '\0'; - info_value->length = length; /* not +1 !!! */ + if ( value) { + info_value->value.s = estrndup(value,length); + } else { + info_value->length = 0; + info_value->value.s = estrdup(""); + } + if ( !info_value->value.s) { + info_value->length = 0; + php_error(E_WARNING, "Could not allocate memory for thumbnail"); + return; + } break; case TAG_FMT_SSHORT: @@ -827,26 +846,65 @@ void exif_add_image_info( image_info_type *image_info, int section_index, char * } /* }}} */ +/* {{{ exif_iif_add_int + Add a tag from IFD to image_info +*/ +void exif_iif_add_int( image_info_type *image_info, int section_index, char *name, int value) +{ + image_info_value *info_value, *list; + + list = erealloc(image_info->info_list[section_index].list,(image_info->info_list[section_index].count+1)*sizeof(image_info_value)); + if ( !list) { + php_error(E_WARNING, "Could not allocate memory for thumbnail"); + return; + } + image_info->info_list[section_index].list = list; + + info_value = &image_info->info_list[section_index].list[image_info->info_list[section_index].count]; + info_value->tag = TAG_NONE; + info_value->format = TAG_FMT_SLONG; + info_value->length = 1; + info_value->name = estrdup(name); + if ( !info_value->name) { + php_error(E_WARNING, "Could not allocate memory for thumbnail"); + return; + } + info_value->value.i = value; + image_info->sections_found |= 1<<section_index; + image_info->info_list[section_index].count++; +} +/* }}} */ + /* {{{ exif_free_image_info Free memory allocated for image_info */ void exif_free_image_info( image_info_type *image_info, int section_index) { int i; + void *f; if (image_info->info_list[section_index].count) { for (i=0; i < image_info->info_list[section_index].count; i++) { - efree(image_info->info_list[section_index].list[i].name); + if ( (f=image_info->info_list[section_index].list[i].name) != NULL) + { + efree(f); + } if ( image_info->info_list[section_index].list[i].format == TAG_FMT_STRING ||image_info->info_list[section_index].list[i].format == TAG_FMT_UNDEFINED ) { - efree(image_info->info_list[section_index].list[i].value.s); + if ( (f=image_info->info_list[section_index].list[i].value.s) != NULL) + { + efree(f); + } } } - efree(image_info->info_list[section_index].list); + if ( (f=image_info->info_list[section_index].list) != NULL) + { + efree(f); + } } } /* }}} */ @@ -858,8 +916,8 @@ void exif_free_image_info( image_info_type *image_info, int section_index) */ void add_assoc_image_info( pval *value, int sub_array, image_info_type *image_info, int section_index) { - char buffer[64]; - int idx=0; + char buffer[64], *val, *name, uname[64]; + int idx=0, unknown=0; image_info_value *info_value; if ( image_info->info_list[section_index].count) @@ -878,8 +936,12 @@ void add_assoc_image_info( pval *value, int sub_array, image_info_type *image_in { info_value = &image_info->info_list[section_index].list[i]; #ifdef EXIF_DEBUG - /* php_error(E_NOTICE,"adding info #%d: '%s:%s'", i, exif_get_sectionname(section_index), info_value->name);/**/ + /* php_error(E_NOTICE,"adding info #%d: '%s:%s'", i, exif_get_sectionname(section_index), info_value->name);*/ #endif + if ( !(name = info_value->name)) { + sprintf(uname,"%d", unknown++); + name = uname; + } switch(info_value->format) { default: @@ -889,45 +951,50 @@ void add_assoc_image_info( pval *value, int sub_array, image_info_type *image_in * return; */ case TAG_FMT_UNDEFINED: - add_assoc_stringl(tmpi, info_value->name, info_value->value.s, info_value->length, 1); + if ( !info_value->value.s) { + add_assoc_stringl(tmpi, name, "", 0, 1); + } else { + add_assoc_stringl(tmpi, name, info_value->value.s, info_value->length, 1); + } break; case TAG_FMT_STRING: + if ( !(val = info_value->value.s)) val = ""; if (section_index==SECTION_COMMENT) { - add_index_string(tmpi, idx++, info_value->value.s, 1); + add_index_string(tmpi, idx++, val, 1); } else { - add_assoc_string(tmpi, info_value->name, info_value->value.s, 1); + add_assoc_string(tmpi, name, val, 1); } break; case TAG_FMT_BYTE: case TAG_FMT_USHORT: case TAG_FMT_ULONG: - add_assoc_long(tmpi, info_value->name, (int)info_value->value.u); + add_assoc_long(tmpi, name, (int)info_value->value.u); break; case TAG_FMT_URATIONAL: sprintf(buffer,"%i/%i", info_value->value.ur.num, info_value->value.ur.den); - add_assoc_string(tmpi, info_value->name, buffer, 1); + add_assoc_string(tmpi, name, buffer, 1); break; case TAG_FMT_SBYTE: case TAG_FMT_SSHORT: case TAG_FMT_SLONG: - add_assoc_long(tmpi, info_value->name, info_value->value.i); + add_assoc_long(tmpi, name, info_value->value.i); break; case TAG_FMT_SRATIONAL: sprintf(buffer,"%i/%i", info_value->value.sr.num, info_value->value.sr.den); - add_assoc_string(tmpi, info_value->name, buffer, 1); + add_assoc_string(tmpi, name, buffer, 1); break; case TAG_FMT_SINGLE: - add_assoc_double(tmpi, info_value->name, info_value->value.f); + add_assoc_double(tmpi, name, info_value->value.f); break; case TAG_FMT_DOUBLE: - add_assoc_double(tmpi, info_value->name, info_value->value.d); + add_assoc_double(tmpi, name, info_value->value.d); break; } } @@ -1147,6 +1214,7 @@ static void exif_extract_thumbnail(image_info_type *ImageInfo, char *offset, uns } /* }}} */ +#ifdef EXIF_DEBUG /* {{{ exif_process_string_raw * Copy a string in Exif header to a character string returns length of allocated buffer if any. */ static int exif_process_string_raw(char **result,char *value,size_t byte_count) { @@ -1163,6 +1231,7 @@ static int exif_process_string_raw(char **result,char *value,size_t byte_count) return 0; } /* }}} */ +#endif /* {{{ exif_process_string * Copy a string in Exif header to a character string returns length of allocated buffer if any. */ @@ -1226,7 +1295,7 @@ static int exif_process_user_comment(char **pszInfoPtr,char *szEncoding,char *sz } /* Olympus has this padded with trailing spaces. Remove these first. */ - for (a=ByteCount-1;a && szValuePtr[a]==' ';a--) (szValuePtr)[a] = '\0'; + if (a) for (a=ByteCount-1;a && szValuePtr[a]==' ';a--) (szValuePtr)[a] = '\0'; /* normal text without encoding */ return exif_process_string(pszInfoPtr,szValuePtr,ByteCount); @@ -1266,9 +1335,8 @@ static void exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, ch { int l; int tag, format, components; - char *value_ptr, *buffer, tagname[64]; - size_t byte_count; - unsigned offset_val; + char *value_ptr, tagname[64], cbuf[32], *outside=NULL; + size_t byte_count, offset_val, fpos, fgot; tag = php_ifd_get16u(dir_entry, ImageInfo->motorola_intel); format = php_ifd_get16u(dir_entry+2, ImageInfo->motorola_intel); @@ -1285,12 +1353,55 @@ static void exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, ch if (byte_count > 4) { offset_val = php_ifd_get32u(dir_entry+8, ImageInfo->motorola_intel); /* If its bigger than 4 bytes, the dir entry contains an offset. */ - if (offset_val+byte_count > IFDlength) { - /* Bogus pointer offset and / or byte_count value */ - php_error(E_WARNING, "Illegal pointer offset(x%04X + x%04X = x%04X > x%04X) in IFD for Tag(x%04X=%s): ", offset_val, byte_count, offset_val+byte_count, IFDlength, tag, exif_get_tagname(tag,tagname)); - return; - } value_ptr = offset_base+offset_val; + if (offset_val+byte_count > IFDlength || value_ptr < dir_entry) { + // It is important to check for IMAGE_FILETYPE_TIFF + // JPEG does not use absolute pointers instead its pointers are relative to the start + // of the TIFF header in APP1 section. + if (offset_val<0 || offset_val+byte_count>ImageInfo->FileSize || (ImageInfo->FileType!=IMAGE_FILETYPE_TIFF_II && ImageInfo->FileType!=IMAGE_FILETYPE_TIFF_MM)) { + if (value_ptr < dir_entry) { + /* we can read this if offset_val > 0 */ + /* some files have their values in other parts of the file */ + php_error(E_WARNING, "process tag(x%04X=%s): Illegal pointer offset(x%04X < x%04X)", tag, exif_get_tagname(tag,tagname), offset_val, dir_entry); + } else { + /* this is for sure not allowed */ + /* exception are IFD pointers */ + php_error(E_WARNING, "process tag(x%04X=%s): Illegal pointer offset(x%04X + x%04X = x%04X > x%04X)", tag, exif_get_tagname(tag,tagname), offset_val, byte_count, offset_val+byte_count, IFDlength); + } + return; + } + if ( byte_count>sizeof(cbuf)) { + // mark as outside range and get buffer + value_ptr = emalloc(byte_count); + if ( !value_ptr) { + php_error(E_WARNING, "could not allocate data for entire image"); + return; + } + outside = value_ptr; + } else { + // in most cases we only access a small range so + // it is faster to use a static buffer there + // BUT it offers also the possibility to have + // pointers read without the need to free them + // explicitley before returning. + value_ptr = cbuf; + } + fpos = ftell(ImageInfo->infile); + fseek(ImageInfo->infile, offset_val, SEEK_SET); + fgot = ftell(ImageInfo->infile); + if ( fgot!=offset_val) { + if ( outside) efree( outside); + php_error(E_WARNING,"Wrong file pointer: 0x%08X != 0x08X", fgot, offset_val); + return; + } + fgot = fread(value_ptr, 1, byte_count, ImageInfo->infile); + fseek(ImageInfo->infile, fpos, SEEK_SET); + if ( fgot<byte_count) { + if ( outside) efree( outside); + php_error(E_WARNING, "File corrupt: End of file reached."); + return; + } + } } else { /* 4 bytes or less and value is in the dir entry itself */ value_ptr = dir_entry+8; @@ -1306,7 +1417,7 @@ static void exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, ch case TAG_JPEG_INTERCHANGE_FORMAT: /* accept both formats */ ImageInfo->ThumbnailOffset = (int)exif_convert_any_format(value_ptr, format, ImageInfo->motorola_intel); - return; + break; case TAG_JPEG_INTERCHANGE_FORMAT_LEN: ImageInfo->ThumbnailSize = (int)exif_convert_any_format(value_ptr, format, ImageInfo->motorola_intel); @@ -1429,27 +1540,27 @@ static void exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, ch #endif ImageInfo->sections_found |= FOUND_INTEROP; sub_section_index = SECTION_INTEROP; -/* return;/* we do not know how to handle that yet */ - break;/**/ + break; } SubdirStart = offset_base + php_ifd_get32u(value_ptr, ImageInfo->motorola_intel); if (SubdirStart < offset_base || SubdirStart > offset_base+IFDlength) { php_error(E_WARNING, "Illegal IFD Pointer"); - return; + break; } exif_process_IFD_in_JPEG(ImageInfo, SubdirStart, offset_base, IFDlength, sub_section_index); #ifdef EXIF_DEBUG php_error(E_NOTICE,"subsection %s done", exif_get_sectionname(sub_section_index)); #endif - return; + break; } - return; + break; } } /* correctly would be to set components as length * but we are ignoring length for those types where it is not the same as byte_count */ exif_add_image_info( ImageInfo, section_index, exif_get_tagname(tag,tagname), tag, format, byte_count, value_ptr); + if ( outside) efree( outside); } /* }}} */ @@ -1492,7 +1603,7 @@ static void exif_process_IFD_in_JPEG(image_info_type *ImageInfo, char *DirStart, #ifdef EXIF_DEBUG php_error(E_NOTICE,"expect next IFD to be thumbnail"); #endif - exif_process_IFD_in_JPEG(ImageInfo, OffsetBase + NextDirOffset, OffsetBase, IFDlength, SECTION_THUMBNAIL);/**/ + exif_process_IFD_in_JPEG(ImageInfo, OffsetBase + NextDirOffset, OffsetBase, IFDlength, SECTION_THUMBNAIL); } } /* }}} */ @@ -1577,7 +1688,6 @@ static void exif_process_APP12(image_info_type *ImageInfo, char *buffer, unsigne static int exif_scan_JPEG_header(image_info_type *ImageInfo, FILE *infile) { int a; - int HaveCom = FALSE; for(ImageInfo->sections_count=0;ImageInfo->sections_count < 19;) { int itemlen; @@ -1859,8 +1969,7 @@ static int exif_process_IFD_in_TIFF(image_info_type *ImageInfo, FILE *infile, si case TAG_INTEROP_IFD_POINTER: ImageInfo->sections_found |= FOUND_INTEROP; sub_section_index = SECTION_INTEROP; -/* return; /* we do not know how to handle that yet */ - break;/**/ + break; } entry_offset = php_ifd_get32u(dir_entry+8, ImageInfo->motorola_intel); #ifdef EXIF_DEBUG @@ -1929,26 +2038,26 @@ static int exif_scan_FILE_header (image_info_type *ImageInfo, FILE *infile) return exif_scan_JPEG_header(ImageInfo,infile); } else if ( ImageInfo->FileSize >= 8) { fread(file_header+2, 1, 6, infile); - if ( !memcmp(file_header,"II\x2A\x00\x08\x00\x00\x00", 8)) + if ( !memcmp(file_header,"II\x2A\x00", 4)) { - ImageInfo->FileType = IMAGE_FILETYPE_TIFF; + ImageInfo->FileType = IMAGE_FILETYPE_TIFF_II; ImageInfo->motorola_intel = 0; #ifdef EXIF_DEBUG php_error(E_NOTICE,"File(%s) has TIFF/II format", ImageInfo->FileName); #endif ImageInfo->sections_found |= FOUND_IFD0; - return exif_process_IFD_in_TIFF(ImageInfo,infile,8,SECTION_IFD0); + return exif_process_IFD_in_TIFF(ImageInfo,infile,php_ifd_get32u(file_header+4,ImageInfo->motorola_intel),SECTION_IFD0); } else - if ( !memcmp(file_header,"MM\x00\x2a\x00\x00\x00\x08", 8)) + if ( !memcmp(file_header,"MM\x00\x2a", 4)) { - ImageInfo->FileType = IMAGE_FILETYPE_TIFF; + ImageInfo->FileType = IMAGE_FILETYPE_TIFF_MM; ImageInfo->motorola_intel = 1; #ifdef EXIF_DEBUG php_error(E_NOTICE,"File(%s) has TIFF/MM format", ImageInfo->FileName); #endif ImageInfo->sections_found |= FOUND_IFD0; - return exif_process_IFD_in_TIFF(ImageInfo,infile,8,SECTION_IFD0); + return exif_process_IFD_in_TIFF(ImageInfo,infile,php_ifd_get32u(file_header+4,ImageInfo->motorola_intel),SECTION_IFD0); } } } @@ -2007,7 +2116,7 @@ int php_exif_read_file(image_info_type *ImageInfo, char *FileName, int read_thum php_error(E_WARNING, "Unable to open '%s'", FileName); return FALSE; } - /* php_error(E_WARNING,"EXIF: Process %s%s: %s", read_thumbnail?"thumbs ":"", read_all?"All ":"", FileName); /**/ + /* php_error(E_WARNING,"EXIF: Process %s%s: %s", read_thumbnail?"thumbs ":"", read_all?"All ":"", FileName); */ /* Start with an empty image information structure. */ memset(ImageInfo, 0, sizeof(*ImageInfo)); @@ -2028,6 +2137,7 @@ int php_exif_read_file(image_info_type *ImageInfo, char *FileName, int read_thum } /* Scan the JPEG headers. */ + ImageInfo->infile = infile; ret = exif_scan_FILE_header(ImageInfo, infile); if (!ret) { php_error(E_WARNING, "Invalid JPEG/TIFF file: '%s'", FileName); @@ -2045,7 +2155,6 @@ PHP_FUNCTION(exif_read_data) { pval **p_name, **p_sections_needed, **p_sub_arrays, **p_read_thumbnail, **p_read_all; int i, len, ac = ZEND_NUM_ARGS(), ret, sections_needed=0, sub_arrays=0, read_thumbnail=0, read_all=0; - int self_motorola_intel; image_info_type ImageInfo; char tmp[64], *sections_str, *s; @@ -2126,17 +2235,17 @@ PHP_FUNCTION(exif_read_data) /* now we can add our information */ exif_add_image_info( &ImageInfo, SECTION_FILE, "FileName", TAG_NONE, TAG_FMT_STRING, strlen(ImageInfo.FileName), ImageInfo.FileName); - exif_add_image_info( &ImageInfo, SECTION_FILE, "FileDateTime", TAG_NONE, TAG_FMT_SLONG, 1, &ImageInfo.FileDateTime); - exif_add_image_info( &ImageInfo, SECTION_FILE, "FileSize", TAG_NONE, TAG_FMT_SLONG, 1, &ImageInfo.FileSize); + exif_iif_add_int( &ImageInfo, SECTION_FILE, "FileDateTime", ImageInfo.FileDateTime); + exif_iif_add_int( &ImageInfo, SECTION_FILE, "FileSize", ImageInfo.FileSize); exif_add_image_info( &ImageInfo, SECTION_FILE, "SectionsFound", TAG_NONE, TAG_FMT_STRING, strlen(sections_str), sections_str); if (ImageInfo.Width>0 && ImageInfo.Height>0) { sprintf(tmp, "width=\"%d\" height=\"%d\"", ImageInfo.Width, ImageInfo.Height); exif_add_image_info( &ImageInfo, SECTION_COMPUTED, "html", TAG_NONE, TAG_FMT_STRING, strlen(tmp), tmp); - exif_add_image_info( &ImageInfo, SECTION_COMPUTED, "Height", TAG_NONE, TAG_FMT_SLONG, 1, &ImageInfo.Height); - exif_add_image_info( &ImageInfo, SECTION_COMPUTED, "Width", TAG_NONE, TAG_FMT_SLONG, 1, &ImageInfo.Width); + exif_iif_add_int( &ImageInfo, SECTION_COMPUTED, "Height", ImageInfo.Height); + exif_iif_add_int( &ImageInfo, SECTION_COMPUTED, "Width", ImageInfo.Width); } - exif_add_image_info( &ImageInfo, SECTION_COMPUTED, "IsColor", TAG_NONE, TAG_FMT_SLONG, 1, &ImageInfo.IsColor); + exif_iif_add_int( &ImageInfo, SECTION_COMPUTED, "IsColor", ImageInfo.IsColor); if (ImageInfo.FocalLength) { sprintf(tmp, "%4.1fmm", ImageInfo.FocalLength); exif_add_image_info( &ImageInfo, SECTION_COMPUTED, "FocalLength", TAG_NONE, TAG_FMT_STRING, strlen(tmp), tmp); @@ -2171,7 +2280,7 @@ PHP_FUNCTION(exif_read_data) } if (ImageInfo.UserComment) { exif_add_image_info( &ImageInfo, SECTION_COMPUTED, "UserComment", TAG_NONE, TAG_FMT_STRING, strlen(ImageInfo.UserComment), ImageInfo.UserComment); - if ( (len=ImageInfo.UserCommentEncoding[0])) { + if ( (len=strlen(ImageInfo.UserCommentEncoding))) { exif_add_image_info( &ImageInfo, SECTION_COMPUTED, "UserCommentEncoding", TAG_NONE, TAG_FMT_STRING, len, ImageInfo.UserCommentEncoding); } } diff --git a/ext/standard/image.c b/ext/standard/image.c index a27363e09b..87f05751e9 100644 --- a/ext/standard/image.c +++ b/ext/standard/image.c @@ -57,8 +57,8 @@ PHPAPI const char php_sig_swf[3] = {'F', 'W', 'S'}; PHPAPI const char php_sig_jpg[3] = {(char) 0xff, (char) 0xd8, (char) 0xff}; PHPAPI const char php_sig_png[8] = {(char) 0x89, (char) 0x50, (char) 0x4e, (char) 0x47, (char) 0x0d, (char) 0x0a, (char) 0x1a, (char) 0x0a}; -PHPAPI const char php_sig_tif_ii[8] = {'I','I', (char)0x2A, (char)0x00, (char)0x08, (char)0x00, (char)0x00, (char)0x00}; -PHPAPI const char php_sig_tif_mm[8] = {'M','M', (char)0x00, (char)0x2A, (char)0x00, (char)0x00, (char)0x00, (char)0x08}; +PHPAPI const char php_sig_tif_ii[4] = {'I','I', (char)0x2A, (char)0x00}; +PHPAPI const char php_sig_tif_mm[4] = {'M','M', (char)0x00, (char)0x2A}; /* return info as a struct, to make expansion easier */ @@ -260,32 +260,41 @@ static unsigned short php_read2(int socketd, FILE *fp, int issock) static unsigned int php_next_marker(int socketd, FILE *fp, int issock) /* get next marker byte from file */ { - int c; + int a, c; /* get marker byte, swallowing possible padding */ + a = 0; do { if ((c = FP_FGETC(socketd, fp, issock)) == EOF) return M_EOI; /* we hit EOF */ + if (++a >= 10) return M_EOI; } while (c == 0xff); - + if (a<2) c = M_EOI; /* at least one 0xff is needed before marker code */ return (unsigned int) c; } /* }}} */ -/* {{{ php_skip_variable - */ -static void php_skip_variable(int socketd, FILE *fp, int issock) - /* skip over a variable-length block; assumes proper length marker */ +/* {{{ php_skip_over + * skip over a block of specified length */ +static void php_skip_over(int socketd, FILE *fp, int issock, size_t length) { - unsigned short length; - char *tmp; + static char tmp[1024]; - length = php_read2(socketd, fp, issock); - length -= 2; /* length includes itself */ + while(length>=sizeof(tmp)) { + FP_FREAD(tmp, sizeof(tmp), socketd, fp, issock); + length -= sizeof(tmp); + } + if(length) { + FP_FREAD(tmp, length, socketd, fp, issock); + } +} +/* }}} */ - tmp = emalloc(length); - FP_FREAD(tmp, (long) length, socketd, fp, issock); /* skip the header */ - efree(tmp); +/* {{{ php_skip_variable + * skip over a variable-length block; assumes proper length marker */ +static void php_skip_variable(int socketd, FILE *fp, int issock) +{ + php_skip_over( socketd, fp, issock, php_read2(socketd, fp, issock)-2); } /* }}} */ @@ -302,6 +311,7 @@ static void php_read_APP(int socketd, FILE *fp, int issock, unsigned int marker, length -= 2; /* length includes itself */ buffer = emalloc(length); + if ( !buffer) return; if (FP_FREAD(buffer, (long) length, socketd, fp, issock) <= 0) { efree(buffer); @@ -325,7 +335,7 @@ static struct gfxinfo *php_handle_jpeg (int socketd, FILE *fp, int issock, pval { struct gfxinfo *result = NULL; unsigned int marker; - char tmp[2]; + size_t length; unsigned char a[4]; for (;;) { @@ -347,15 +357,15 @@ static struct gfxinfo *php_handle_jpeg (int socketd, FILE *fp, int issock, pval if (result == NULL) { /* handle SOFn block */ result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo)); - FP_FREAD(tmp, sizeof(tmp), socketd, fp, issock); + length = php_read2(socketd, fp, issock); result->bits = FP_FGETC(socketd, fp, issock); FP_FREAD(a, sizeof(a), socketd, fp, issock); result->height = (((unsigned short) a[ 0 ]) << 8) + ((unsigned short) a[ 1 ]); result->width = (((unsigned short) a[ 2 ]) << 8) + ((unsigned short) a[ 3 ]); result->channels = FP_FGETC(socketd, fp, issock); - - if (! info) /* if we don't want an extanded info -> return */ + if (!info || length<8) /* if we don't want an extanded info -> return */ return result; + php_skip_over( socketd, fp, issock, length-8); } else { php_skip_variable(socketd, fp, issock); } @@ -476,10 +486,13 @@ static struct gfxinfo *php_handle_tiff (int socketd, FILE *fp, int issock, pval int i, num_entries; unsigned char *dir_entry; - size_t ifd_size, dir_size, entry_value, entry_length, width, height; + size_t ifd_size, dir_size, entry_value, entry_length, width, height, ifd_addr; int entry_tag , entry_type; - char *ifd_data; + char *ifd_data, ifd_ptr[4]; + FP_FREAD(ifd_ptr, 4, socketd, fp, issock); + ifd_addr = php_ifd_get32u(ifd_ptr, motorola_intel); + php_skip_over(socketd, fp, issock, ifd_addr-8); ifd_size = 2; ifd_data = emalloc(ifd_size); FP_FREAD(ifd_data, 2, socketd, fp, issock); @@ -496,6 +509,10 @@ static struct gfxinfo *php_handle_tiff (int socketd, FILE *fp, int issock, pval entry_type = php_ifd_get16u(dir_entry+2, motorola_intel); entry_length = php_ifd_get32u(dir_entry+4, motorola_intel) * php_tiff_bytes_per_format[entry_type]; switch(entry_type) { + case TAG_FMT_BYTE: + case TAG_FMT_SBYTE: + entry_value = (size_t)(dir_entry[8]); + break; case TAG_FMT_USHORT: entry_value = php_ifd_get16u(dir_entry+8, motorola_intel); break; @@ -522,6 +539,7 @@ static struct gfxinfo *php_handle_tiff (int socketd, FILE *fp, int issock, pval break; } } + efree(ifd_data); if ( width && height) { /* not the same when in for-loop */ result = (struct gfxinfo *) ecalloc(1, sizeof(struct gfxinfo)); @@ -625,14 +643,14 @@ PHP_FUNCTION(getimagesize) result = php_handle_bmp(socketd, fp, issock); itype = IMAGE_FILETYPE_BMP; } else { - FP_FREAD(filetype+3, 5, socketd, fp, issock); - if (!memcmp(filetype, php_sig_tif_ii, 8)) { + FP_FREAD(filetype+3, 1, socketd, fp, issock); + if (!memcmp(filetype, php_sig_tif_ii, 4)) { result = php_handle_tiff(socketd, fp, issock, NULL, 0); - itype = IMAGE_FILETYPE_TIFF; + itype = IMAGE_FILETYPE_TIFF_II; } else - if (!memcmp(filetype, php_sig_tif_mm, 8)) { + if (!memcmp(filetype, php_sig_tif_mm, 4)) { result = php_handle_tiff(socketd, fp, issock, NULL, 1); - itype = IMAGE_FILETYPE_TIFF; + itype = IMAGE_FILETYPE_TIFF_MM; } } diff --git a/ext/standard/php_image.h b/ext/standard/php_image.h index d8a68efec7..5cc1485929 100644 --- a/ext/standard/php_image.h +++ b/ext/standard/php_image.h @@ -35,7 +35,8 @@ typedef enum IMAGE_FILETYPE_SWF, IMAGE_FILETYPE_PSD, IMAGE_FILETYPE_BMP, - IMAGE_FILETYPE_TIFF + IMAGE_FILETYPE_TIFF_II, /* intel */ + IMAGE_FILETYPE_TIFF_MM, /* motorola */ } image_filetype; /* }}} */ |