@@ -215,6 +215,26 @@ zend_module_entry exif_module_entry = {
215
215
ZEND_GET_MODULE (exif )
216
216
#endif
217
217
218
+ /* php_stream_read() may return early without reading all data, depending on the chunk size
219
+ * and whether it's a URL stream or not. This helper keeps reading until the requested amount
220
+ * is read or until there is no more data available to read. */
221
+ /* FIXME: perhaps this should be moved to some more general place? */
222
+ static ssize_t read_from_stream_looped (php_stream * stream , char * buf , size_t count )
223
+ {
224
+ ssize_t total_read = 0 ;
225
+ while (total_read < count ) {
226
+ ssize_t ret = php_stream_read (stream , buf + total_read , count - total_read );
227
+ if (ret == -1 ) {
228
+ return -1 ;
229
+ }
230
+ if (ret == 0 ) {
231
+ break ;
232
+ }
233
+ total_read += ret ;
234
+ }
235
+ return total_read ;
236
+ }
237
+
218
238
/* {{{ php_strnlen
219
239
* get length of string if buffer if less than buffer size or buffer size */
220
240
static size_t php_strnlen (char * str , size_t maxlen ) {
@@ -3311,7 +3331,7 @@ static bool exif_process_IFD_TAG_impl(image_info_type *ImageInfo, char *dir_entr
3311
3331
exif_error_docref (NULL EXIFERR_CC , ImageInfo , E_WARNING , "Wrong file pointer: 0x%08X != 0x%08X" , fgot , displacement + offset_val );
3312
3332
return false;
3313
3333
}
3314
- fgot = php_stream_read (ImageInfo -> infile , value_ptr , byte_count );
3334
+ fgot = read_from_stream_looped (ImageInfo -> infile , value_ptr , byte_count );
3315
3335
php_stream_seek (ImageInfo -> infile , fpos , SEEK_SET );
3316
3336
if (fgot != byte_count ) {
3317
3337
EFREE_IF (outside );
@@ -3844,7 +3864,7 @@ static bool exif_scan_JPEG_header(image_info_type *ImageInfo)
3844
3864
Data [0 ] = (uchar )lh ;
3845
3865
Data [1 ] = (uchar )ll ;
3846
3866
3847
- got = php_stream_read (ImageInfo -> infile , (char * )(Data + 2 ), itemlen - 2 ); /* Read the whole section. */
3867
+ got = read_from_stream_looped (ImageInfo -> infile , (char * )(Data + 2 ), itemlen - 2 ); /* Read the whole section. */
3848
3868
if (got != itemlen - 2 ) {
3849
3869
exif_error_docref (NULL EXIFERR_CC , ImageInfo , E_WARNING , "Error reading from file: got=x%04X(=%d) != itemlen-2=x%04X(=%d)" , got , got , itemlen - 2 , itemlen - 2 );
3850
3870
return false;
@@ -3862,7 +3882,7 @@ static bool exif_scan_JPEG_header(image_info_type *ImageInfo)
3862
3882
size = ImageInfo -> FileSize - fpos ;
3863
3883
sn = exif_file_sections_add (ImageInfo , M_PSEUDO , size , NULL );
3864
3884
Data = ImageInfo -> file .list [sn ].data ;
3865
- got = php_stream_read (ImageInfo -> infile , (char * )Data , size );
3885
+ got = read_from_stream_looped (ImageInfo -> infile , (char * )Data , size );
3866
3886
if (got != size ) {
3867
3887
EXIF_ERRLOG_FILEEOF (ImageInfo )
3868
3888
return false ;
@@ -4039,7 +4059,7 @@ static bool exif_process_IFD_in_TIFF_impl(image_info_type *ImageInfo, size_t dir
4039
4059
exif_error_docref (NULL EXIFERR_CC , ImageInfo , E_NOTICE , "Read from TIFF: filesize(x%04X), IFD dir(x%04X + x%04X)" , ImageInfo -> FileSize , dir_offset , 2 );
4040
4060
#endif
4041
4061
php_stream_seek (ImageInfo -> infile , dir_offset , SEEK_SET ); /* we do not know the order of sections */
4042
- php_stream_read (ImageInfo -> infile , (char * )ImageInfo -> file .list [sn ].data , 2 );
4062
+ read_from_stream_looped (ImageInfo -> infile , (char * )ImageInfo -> file .list [sn ].data , 2 );
4043
4063
num_entries = php_ifd_get16u (ImageInfo -> file .list [sn ].data , ImageInfo -> motorola_intel );
4044
4064
dir_size = 2 /*num dir entries*/ + 12 /*length of entry*/ * (size_t )num_entries + 4 /* offset to next ifd (points to thumbnail or NULL)*/ ;
4045
4065
if (ImageInfo -> FileSize >= dir_size && ImageInfo -> FileSize - dir_size >= dir_offset ) {
@@ -4049,7 +4069,7 @@ static bool exif_process_IFD_in_TIFF_impl(image_info_type *ImageInfo, size_t dir
4049
4069
if (exif_file_sections_realloc (ImageInfo , sn , dir_size )) {
4050
4070
return false;
4051
4071
}
4052
- php_stream_read (ImageInfo -> infile , (char * )(ImageInfo -> file .list [sn ].data + 2 ), dir_size - 2 );
4072
+ read_from_stream_looped (ImageInfo -> infile , (char * )(ImageInfo -> file .list [sn ].data + 2 ), dir_size - 2 );
4053
4073
next_offset = php_ifd_get32u (ImageInfo -> file .list [sn ].data + dir_size - 4 , ImageInfo -> motorola_intel );
4054
4074
#ifdef EXIF_DEBUG
4055
4075
exif_error_docref (NULL EXIFERR_CC , ImageInfo , E_NOTICE , "Read from TIFF done, next offset x%04X" , next_offset );
@@ -4137,7 +4157,7 @@ static bool exif_process_IFD_in_TIFF_impl(image_info_type *ImageInfo, size_t dir
4137
4157
#ifdef EXIF_DEBUG
4138
4158
exif_error_docref (NULL EXIFERR_CC , ImageInfo , E_NOTICE , "Read from TIFF: filesize(x%04X), IFD(x%04X + x%04X)" , ImageInfo -> FileSize , dir_offset , ifd_size );
4139
4159
#endif
4140
- php_stream_read (ImageInfo -> infile , (char * )(ImageInfo -> file .list [sn ].data + dir_size ), ifd_size - dir_size );
4160
+ read_from_stream_looped (ImageInfo -> infile , (char * )(ImageInfo -> file .list [sn ].data + dir_size ), ifd_size - dir_size );
4141
4161
#ifdef EXIF_DEBUG
4142
4162
exif_error_docref (NULL EXIFERR_CC , ImageInfo , E_NOTICE , "Read from TIFF , done ");
4143
4163
#endif
@@ -4188,7 +4208,7 @@ static bool exif_process_IFD_in_TIFF_impl(image_info_type *ImageInfo, size_t dir
4188
4208
if (!ImageInfo -> Thumbnail .data ) {
4189
4209
ImageInfo -> Thumbnail .data = safe_emalloc (ImageInfo -> Thumbnail .size , 1 , 0 );
4190
4210
php_stream_seek (ImageInfo -> infile , ImageInfo -> Thumbnail .offset , SEEK_SET );
4191
- fgot = php_stream_read (ImageInfo -> infile , ImageInfo -> Thumbnail .data , ImageInfo -> Thumbnail .size );
4211
+ fgot = read_from_stream_looped (ImageInfo -> infile , ImageInfo -> Thumbnail .data , ImageInfo -> Thumbnail .size );
4192
4212
if (fgot != ImageInfo -> Thumbnail .size ) {
4193
4213
EXIF_ERRLOG_THUMBEOF (ImageInfo )
4194
4214
efree (ImageInfo -> Thumbnail .data );
@@ -4228,7 +4248,7 @@ static bool exif_process_IFD_in_TIFF_impl(image_info_type *ImageInfo, size_t dir
4228
4248
if (!ImageInfo -> Thumbnail .data && ImageInfo -> Thumbnail .offset && ImageInfo -> Thumbnail .size && ImageInfo -> read_thumbnail ) {
4229
4249
ImageInfo -> Thumbnail .data = safe_emalloc (ImageInfo -> Thumbnail .size , 1 , 0 );
4230
4250
php_stream_seek (ImageInfo -> infile , ImageInfo -> Thumbnail .offset , SEEK_SET );
4231
- fgot = php_stream_read (ImageInfo -> infile , ImageInfo -> Thumbnail .data , ImageInfo -> Thumbnail .size );
4251
+ fgot = read_from_stream_looped (ImageInfo -> infile , ImageInfo -> Thumbnail .data , ImageInfo -> Thumbnail .size );
4232
4252
if (fgot != ImageInfo -> Thumbnail .size ) {
4233
4253
EXIF_ERRLOG_THUMBEOF (ImageInfo )
4234
4254
efree (ImageInfo -> Thumbnail .data );
@@ -4283,7 +4303,7 @@ static bool exif_scan_FILE_header(image_info_type *ImageInfo)
4283
4303
4284
4304
if (ImageInfo -> FileSize >= 2 ) {
4285
4305
php_stream_seek (ImageInfo -> infile , 0 , SEEK_SET );
4286
- if (php_stream_read (ImageInfo -> infile , (char * )file_header , 2 ) != 2 ) {
4306
+ if (read_from_stream_looped (ImageInfo -> infile , (char * )file_header , 2 ) != 2 ) {
4287
4307
return false;
4288
4308
}
4289
4309
if ((file_header [0 ]== 0xff ) && (file_header [1 ]== M_SOI )) {
@@ -4294,7 +4314,7 @@ static bool exif_scan_FILE_header(image_info_type *ImageInfo)
4294
4314
exif_error_docref (NULL EXIFERR_CC , ImageInfo , E_WARNING , "Invalid JPEG file ");
4295
4315
}
4296
4316
} else if (ImageInfo -> FileSize >= 8 ) {
4297
- if (php_stream_read (ImageInfo -> infile , (char * )(file_header + 2 ), 6 ) != 6 ) {
4317
+ if (read_from_stream_looped (ImageInfo -> infile , (char * )(file_header + 2 ), 6 ) != 6 ) {
4298
4318
return false;
4299
4319
}
4300
4320
if (!memcmp (file_header , "II\x2A\x00" , 4 )) {
0 commit comments