summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Boerger <helly@php.net>2002-03-11 19:04:29 +0000
committerMarcus Boerger <helly@php.net>2002-03-11 19:04:29 +0000
commit8ec3b4740247030db06890875eb683fff37f3148 (patch)
tree07b69bdbca0777efd2d6320778191313453d037e
parentf893cc65e1dcf08e4d1a3958b1c39e26758b761a (diff)
downloadphp-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.c223
-rw-r--r--ext/standard/image.c70
-rw-r--r--ext/standard/php_image.h3
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;
/* }}} */