@@ -105,6 +105,7 @@ ZEND_BEGIN_MODULE_GLOBALS(exif)
105
105
char * encode_jis ;
106
106
char * decode_jis_be ;
107
107
char * decode_jis_le ;
108
+ HashTable * tag_table_cache ;
108
109
ZEND_END_MODULE_GLOBALS (exif )
109
110
110
111
ZEND_DECLARE_MODULE_GLOBALS (exif )
@@ -170,6 +171,7 @@ static PHP_GINIT_FUNCTION(exif)
170
171
exif_globals -> encode_jis = NULL ;
171
172
exif_globals -> decode_jis_be = NULL ;
172
173
exif_globals -> decode_jis_le = NULL ;
174
+ exif_globals -> tag_table_cache = NULL ;
173
175
}
174
176
/* }}} */
175
177
@@ -192,6 +194,10 @@ PHP_MINIT_FUNCTION(exif)
192
194
PHP_MSHUTDOWN_FUNCTION (exif )
193
195
{
194
196
UNREGISTER_INI_ENTRIES ();
197
+ if (EXIF_G (tag_table_cache )) {
198
+ zend_hash_destroy (EXIF_G (tag_table_cache ));
199
+ free (EXIF_G (tag_table_cache ));
200
+ }
195
201
return SUCCESS ;
196
202
}
197
203
/* }}} */
@@ -694,7 +700,6 @@ static tag_info_array tag_table_IFD = {
694
700
{ 0x8773 , "ICC_Profile" },
695
701
{ 0x8822 , "ExposureProgram" },
696
702
{ 0x8824 , "SpectralSensity" },
697
- { 0x8828 , "OECF" },
698
703
{ 0x8825 , "GPS_IFD_Pointer" },
699
704
{ 0x8827 , "ISOSpeedRatings" },
700
705
{ 0x8828 , "OECF" },
@@ -1323,40 +1328,72 @@ static const maker_note_type maker_note_array[] = {
1323
1328
};
1324
1329
/* }}} */
1325
1330
1326
- /* {{{ exif_get_tagname
1327
- Get headername for tag_num or NULL if not defined */
1328
- static char * exif_get_tagname (int tag_num , char * ret , int len , tag_table_type tag_table )
1331
+ static HashTable * exif_make_tag_ht (tag_info_type * tag_table )
1329
1332
{
1330
- int i , t ;
1331
- char tmp [32 ];
1332
-
1333
- for (i = 0 ; (t = tag_table [i ].Tag ) != TAG_END_OF_LIST ; i ++ ) {
1334
- if (t == tag_num ) {
1335
- if (ret && len ) {
1336
- strlcpy (ret , tag_table [i ].Desc , abs (len ));
1337
- if (len < 0 ) {
1338
- memset (ret + strlen (ret ), ' ' , - len - strlen (ret ) - 1 );
1339
- ret [- len - 1 ] = '\0' ;
1340
- }
1341
- return ret ;
1342
- }
1343
- return tag_table [i ].Desc ;
1333
+ HashTable * ht = malloc (sizeof (HashTable ));
1334
+ zend_hash_init (ht , 0 , NULL , NULL , 1 );
1335
+ while (tag_table -> Tag != TAG_END_OF_LIST ) {
1336
+ if (!zend_hash_index_add_ptr (ht , tag_table -> Tag , tag_table -> Desc )) {
1337
+ zend_error (E_CORE_ERROR , "Duplicate tag %x" , tag_table -> Tag );
1344
1338
}
1339
+ tag_table ++ ;
1345
1340
}
1341
+ return ht ;
1342
+ }
1346
1343
1347
- if (ret && len ) {
1348
- snprintf (tmp , sizeof (tmp ), "UndefinedTag:0x%04X" , tag_num );
1349
- strlcpy (ret , tmp , abs (len ));
1350
- if (len < 0 ) {
1351
- memset (ret + strlen (ret ), ' ' , - len - strlen (ret ) - 1 );
1352
- ret [- len - 1 ] = '\0' ;
1353
- }
1354
- return ret ;
1344
+ static void exif_tag_ht_dtor (zval * zv )
1345
+ {
1346
+ HashTable * ht = Z_PTR_P (zv );
1347
+ zend_hash_destroy (ht );
1348
+ free (ht );
1349
+ }
1350
+
1351
+ static HashTable * exif_get_tag_ht (tag_info_type * tag_table )
1352
+ {
1353
+ HashTable * ht ;
1354
+
1355
+ if (!EXIF_G (tag_table_cache )) {
1356
+ EXIF_G (tag_table_cache ) = malloc (sizeof (HashTable ));
1357
+ zend_hash_init (EXIF_G (tag_table_cache ), 0 , NULL , exif_tag_ht_dtor , 1 );
1355
1358
}
1356
- return "" ;
1359
+
1360
+ ht = zend_hash_index_find_ptr (EXIF_G (tag_table_cache ), (uintptr_t ) tag_table );
1361
+ if (ht ) {
1362
+ return ht ;
1363
+ }
1364
+
1365
+ ht = exif_make_tag_ht (tag_table );
1366
+ zend_hash_index_add_new_ptr (EXIF_G (tag_table_cache ), (uintptr_t ) tag_table , ht );
1367
+ return ht ;
1368
+ }
1369
+
1370
+ /* {{{ exif_get_tagname
1371
+ Get headername for tag_num or NULL if not defined */
1372
+ static char * exif_get_tagname (int tag_num , tag_table_type tag_table )
1373
+ {
1374
+ return zend_hash_index_find_ptr (exif_get_tag_ht (tag_table ), tag_num );
1357
1375
}
1358
1376
/* }}} */
1359
1377
1378
+ static char * exif_get_tagname_debug (int tag_num , tag_table_type tag_table )
1379
+ {
1380
+ char * desc = zend_hash_index_find_ptr (exif_get_tag_ht (tag_table ), tag_num );
1381
+ if (desc ) {
1382
+ return desc ;
1383
+ }
1384
+ return "UndefinedTag" ;
1385
+ }
1386
+
1387
+ static char * exif_get_tagname_key (int tag_num , char * buf , size_t buf_size , tag_table_type tag_table )
1388
+ {
1389
+ char * desc = zend_hash_index_find_ptr (exif_get_tag_ht (tag_table ), tag_num );
1390
+ if (desc ) {
1391
+ return desc ;
1392
+ }
1393
+ snprintf (buf , buf_size , "UndefinedTag:0x%04X" , tag_num );
1394
+ return buf ;
1395
+ }
1396
+
1360
1397
/* {{{ exif_char_dump
1361
1398
* Do not use! This is a debug function... */
1362
1399
#ifdef EXIF_DEBUG
@@ -1912,16 +1949,29 @@ typedef struct {
1912
1949
int read_thumbnail ;
1913
1950
int read_all ;
1914
1951
int ifd_nesting_level ;
1952
+ int num_errors ;
1915
1953
/* internal */
1916
1954
file_section_list file ;
1917
1955
} image_info_type ;
1918
1956
/* }}} */
1919
1957
1958
+ #define EXIF_MAX_ERRORS 10
1959
+
1920
1960
/* {{{ exif_error_docref */
1921
- static void exif_error_docref (const char * docref EXIFERR_DC , const image_info_type * ImageInfo , int type , const char * format , ...)
1961
+ static void exif_error_docref (const char * docref EXIFERR_DC , image_info_type * ImageInfo , int type , const char * format , ...)
1922
1962
{
1923
1963
va_list args ;
1924
1964
1965
+ if (ImageInfo ) {
1966
+ if (++ ImageInfo -> num_errors > EXIF_MAX_ERRORS ) {
1967
+ if (ImageInfo -> num_errors == EXIF_MAX_ERRORS + 1 ) {
1968
+ php_error_docref (docref , type ,
1969
+ "Further exif parsing errors have been suppressed" );
1970
+ }
1971
+ return ;
1972
+ }
1973
+ }
1974
+
1925
1975
va_start (args , format );
1926
1976
#ifdef EXIF_DEBUG
1927
1977
{
@@ -2335,7 +2385,7 @@ static void add_assoc_image_info(zval *value, int sub_array, image_info_type *im
2335
2385
name = uname ;
2336
2386
}
2337
2387
#ifdef EXIF_DEBUG
2338
- /* php_error_docref(NULL, E_NOTICE, "Adding infos: tag(0x%04X,%12s,L=0x%04X): %s", info_tag, exif_get_tagname (info_tag, buffer, -12 , exif_get_tag_table(section_index)), info_data->length, info_data->format==TAG_FMT_STRING?(info_value&&info_value->s?info_value->s:"<no data>"):exif_get_tagformat(info_data->format));*/
2388
+ /* php_error_docref(NULL, E_NOTICE, "Adding infos: tag(0x%04X,%12s,L=0x%04X): %s", info_tag, exif_get_tagname_debug (info_tag, exif_get_tag_table(section_index)), info_data->length, info_data->format==TAG_FMT_STRING?(info_value&&info_value->s?info_value->s:"<no data>"):exif_get_tagformat(info_data->format));*/
2339
2389
#endif
2340
2390
if (info_data -> length == 0 ) {
2341
2391
add_assoc_null (& tmpi , name );
@@ -2655,9 +2705,8 @@ PHP_FUNCTION(exif_tagname)
2655
2705
return ;
2656
2706
}
2657
2707
2658
- szTemp = exif_get_tagname (tag , NULL , 0 , tag_table_IFD );
2659
-
2660
- if (tag < 0 || !szTemp || !szTemp [0 ]) {
2708
+ szTemp = exif_get_tagname (tag , tag_table_IFD );
2709
+ if (tag < 0 || !szTemp ) {
2661
2710
RETURN_FALSE ;
2662
2711
}
2663
2712
@@ -2798,7 +2847,7 @@ static void exif_thumbnail_build(image_info_type *ImageInfo) {
2798
2847
info_data = & info_list -> list [i ];
2799
2848
byte_count = php_tiff_bytes_per_format [info_data -> format ] * info_data -> length ;
2800
2849
#ifdef EXIF_DEBUG
2801
- exif_error_docref (NULL EXIFERR_CC , ImageInfo , E_NOTICE , "Thumbnail: process tag(x%04X=%s): %s%s (%d bytes)" , info_data -> tag , exif_get_tagname (info_data -> tag , tagname , -12 , tag_table_IFD ), (info_data -> length > 1 )&& info_data -> format != TAG_FMT_UNDEFINED && info_data -> format != TAG_FMT_STRING ?"ARRAY OF " :"" , exif_get_tagformat (info_data -> format ), byte_count );
2850
+ exif_error_docref (NULL EXIFERR_CC , ImageInfo , E_NOTICE , "Thumbnail: process tag(x%04X=%s): %s%s (%d bytes)" , info_data -> tag , exif_get_tagname_debug (info_data -> tag , tag_table_IFD ), (info_data -> length > 1 )&& info_data -> format != TAG_FMT_UNDEFINED && info_data -> format != TAG_FMT_STRING ?"ARRAY OF " :"" , exif_get_tagformat (info_data -> format ), byte_count );
2802
2851
#endif
2803
2852
if (info_data -> tag == TAG_STRIP_OFFSETS || info_data -> tag == TAG_JPEG_INTERCHANGE_FORMAT ) {
2804
2853
php_ifd_set16u (new_data + 0 , info_data -> tag , ImageInfo -> motorola_intel );
@@ -3143,7 +3192,7 @@ static int exif_process_IFD_in_MAKERNOTE(image_info_type *ImageInfo, char * valu
3143
3192
3144
3193
#define REQUIRE_NON_EMPTY () do { \
3145
3194
if (byte_count == 0) { \
3146
- exif_error_docref("exif_read_data#error_ifd" EXIFERR_CC, ImageInfo, E_WARNING, "Process tag(x%04X=%s): Cannot be empty", tag, exif_get_tagname (tag, tagname, -12 , tag_table)); \
3195
+ exif_error_docref("exif_read_data#error_ifd" EXIFERR_CC, ImageInfo, E_WARNING, "Process tag(x%04X=%s): Cannot be empty", tag, exif_get_tagname_debug (tag, tag_table)); \
3147
3196
return FALSE; \
3148
3197
} \
3149
3198
} while (0)
@@ -3177,15 +3226,15 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha
3177
3226
3178
3227
if (!format || format > NUM_FORMATS ) {
3179
3228
/* (-1) catches illegal zero case as unsigned underflows to positive large. */
3180
- exif_error_docref ("exif_read_data#error_ifd" EXIFERR_CC , ImageInfo , E_WARNING , "Process tag(x%04X=%s): Illegal format code 0x%04X, suppose BYTE" , tag , exif_get_tagname (tag , tagname , -12 , tag_table ), format );
3229
+ exif_error_docref ("exif_read_data#error_ifd" EXIFERR_CC , ImageInfo , E_WARNING , "Process tag(x%04X=%s): Illegal format code 0x%04X, suppose BYTE" , tag , exif_get_tagname_debug (tag , tag_table ), format );
3181
3230
format = TAG_FMT_BYTE ;
3182
3231
/*return TRUE;*/
3183
3232
}
3184
3233
3185
3234
byte_count_signed = (int64_t )components * php_tiff_bytes_per_format [format ];
3186
3235
3187
3236
if (byte_count_signed < 0 || (byte_count_signed > INT32_MAX )) {
3188
- exif_error_docref ("exif_read_data#error_ifd" EXIFERR_CC , ImageInfo , E_WARNING , "Process tag(x%04X=%s): Illegal byte_count" , tag , exif_get_tagname (tag , tagname , -12 , tag_table ));
3237
+ exif_error_docref ("exif_read_data#error_ifd" EXIFERR_CC , ImageInfo , E_WARNING , "Process tag(x%04X=%s): Illegal byte_count" , tag , exif_get_tagname_debug (tag , tag_table ));
3189
3238
return FALSE;
3190
3239
}
3191
3240
@@ -3208,11 +3257,11 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha
3208
3257
if (value_ptr < dir_entry ) {
3209
3258
/* we can read this if offset_val > 0 */
3210
3259
/* some files have their values in other parts of the file */
3211
- exif_error_docref ("exif_read_data#error_ifd" EXIFERR_CC , ImageInfo , E_WARNING , "Process tag(x%04X=%s): Illegal pointer offset(x%04X < x%04X)" , tag , exif_get_tagname (tag , tagname , -12 , tag_table ), offset_val , dir_entry );
3260
+ exif_error_docref ("exif_read_data#error_ifd" EXIFERR_CC , ImageInfo , E_WARNING , "Process tag(x%04X=%s): Illegal pointer offset(x%04X < x%04X)" , tag , exif_get_tagname_debug (tag , tag_table ), offset_val , dir_entry );
3212
3261
} else {
3213
3262
/* this is for sure not allowed */
3214
3263
/* exception are IFD pointers */
3215
- exif_error_docref ("exif_read_data#error_ifd" EXIFERR_CC , ImageInfo , E_WARNING , "Process tag(x%04X=%s): Illegal pointer offset(x%04X + x%04X = x%04X > x%04X)" , tag , exif_get_tagname (tag , tagname , -12 , tag_table ), offset_val , byte_count , offset_val + byte_count , IFDlength );
3264
+ exif_error_docref ("exif_read_data#error_ifd" EXIFERR_CC , ImageInfo , E_WARNING , "Process tag(x%04X=%s): Illegal pointer offset(x%04X + x%04X = x%04X > x%04X)" , tag , exif_get_tagname_debug (tag , tag_table ), offset_val , byte_count , offset_val + byte_count , IFDlength );
3216
3265
}
3217
3266
return FALSE;
3218
3267
}
@@ -3255,7 +3304,7 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha
3255
3304
ImageInfo -> sections_found |= FOUND_ANY_TAG ;
3256
3305
#ifdef EXIF_DEBUG
3257
3306
dump_data = exif_dump_data (& dump_free , format , components , length , ImageInfo -> motorola_intel , value_ptr );
3258
- exif_error_docref (NULL EXIFERR_CC , ImageInfo , E_NOTICE , "Process tag(x%04X=%s,@x%04X + x%04X(=%d)): %s%s %s" , tag , exif_get_tagname (tag , tagname , -12 , tag_table ), offset_val + displacement , byte_count , byte_count , (components > 1 )&& format != TAG_FMT_UNDEFINED && format != TAG_FMT_STRING ?"ARRAY OF " :"" , exif_get_tagformat (format ), dump_data );
3307
+ exif_error_docref (NULL EXIFERR_CC , ImageInfo , E_NOTICE , "Process tag(x%04X=%s,@x%04X + x%04X(=%d)): %s%s %s" , tag , exif_get_tagname_debug (tag , tag_table ), offset_val + displacement , byte_count , byte_count , (components > 1 )&& format != TAG_FMT_UNDEFINED && format != TAG_FMT_STRING ?"ARRAY OF " :"" , exif_get_tagformat (format ), dump_data );
3259
3308
if (dump_free ) {
3260
3309
efree (dump_data );
3261
3310
}
@@ -3484,7 +3533,7 @@ static int exif_process_IFD_TAG(image_info_type *ImageInfo, char *dir_entry, cha
3484
3533
}
3485
3534
}
3486
3535
}
3487
- exif_iif_add_tag (ImageInfo , section_index , exif_get_tagname (tag , tagname , sizeof (tagname ), tag_table ), tag , format , components , value_ptr , byte_count );
3536
+ exif_iif_add_tag (ImageInfo , section_index , exif_get_tagname_key (tag , tagname , sizeof (tagname ), tag_table ), tag , format , components , value_ptr , byte_count );
3488
3537
EFREE_IF (outside );
3489
3538
return TRUE;
3490
3539
}
@@ -3922,7 +3971,6 @@ static int exif_process_IFD_in_TIFF(image_info_type *ImageInfo, size_t dir_offse
3922
3971
{
3923
3972
int i , sn , num_entries , sub_section_index = 0 ;
3924
3973
unsigned char * dir_entry ;
3925
- char tagname [64 ];
3926
3974
size_t ifd_size , dir_size , entry_offset , next_offset , entry_length , entry_value = 0 , fgot ;
3927
3975
int entry_tag , entry_type ;
3928
3976
tag_table_type tag_table = exif_get_tag_table (section_index );
@@ -3960,7 +4008,7 @@ static int exif_process_IFD_in_TIFF(image_info_type *ImageInfo, size_t dir_offse
3960
4008
entry_tag = php_ifd_get16u (dir_entry + 0 , ImageInfo -> motorola_intel );
3961
4009
entry_type = php_ifd_get16u (dir_entry + 2 , ImageInfo -> motorola_intel );
3962
4010
if (entry_type > NUM_FORMATS ) {
3963
- exif_error_docref (NULL EXIFERR_CC , ImageInfo , E_NOTICE , "Read from TIFF: tag(0x%04X,%12s): Illegal format code 0x%04X, switching to BYTE" , entry_tag , exif_get_tagname (entry_tag , tagname , -12 , tag_table ), entry_type );
4011
+ exif_error_docref (NULL EXIFERR_CC , ImageInfo , E_NOTICE , "Read from TIFF: tag(0x%04X,%12s): Illegal format code 0x%04X, switching to BYTE" , entry_tag , exif_get_tagname_debug (entry_tag , tag_table ), entry_type );
3964
4012
/* Since this is repeated in exif_process_IFD_TAG make it a notice here */
3965
4013
/* and make it a warning in the exif_process_IFD_TAG which is called */
3966
4014
/* elsewhere. */
@@ -4310,6 +4358,7 @@ static int exif_read_from_impl(image_info_type *ImageInfo, php_stream *stream, i
4310
4358
4311
4359
4312
4360
ImageInfo -> ifd_nesting_level = 0 ;
4361
+ ImageInfo -> num_errors = 0 ;
4313
4362
4314
4363
/* Scan the headers */
4315
4364
ret = exif_scan_FILE_header (ImageInfo );
@@ -4517,7 +4566,7 @@ PHP_FUNCTION(exif_read_data)
4517
4566
exif_iif_add_str (& ImageInfo , SECTION_COMPUTED , "Copyright.Editor" , ImageInfo .CopyrightEditor );
4518
4567
4519
4568
for (i = 0 ; i < ImageInfo .xp_fields .count ; i ++ ) {
4520
- exif_iif_add_str (& ImageInfo , SECTION_WINXP , exif_get_tagname (ImageInfo .xp_fields .list [i ].tag , NULL , 0 , exif_get_tag_table (SECTION_WINXP )), ImageInfo .xp_fields .list [i ].value );
4569
+ exif_iif_add_str (& ImageInfo , SECTION_WINXP , exif_get_tagname_debug (ImageInfo .xp_fields .list [i ].tag , exif_get_tag_table (SECTION_WINXP )), ImageInfo .xp_fields .list [i ].value );
4521
4570
}
4522
4571
if (ImageInfo .Thumbnail .size ) {
4523
4572
if (read_thumbnail ) {
0 commit comments