@@ -215,6 +215,25 @@ 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
+ static ssize_t exif_read_from_stream_file_looped (php_stream * stream , char * buf , size_t count )
222
+ {
223
+ ssize_t total_read = 0 ;
224
+ while (total_read < count ) {
225
+ ssize_t ret = php_stream_read (stream , buf + total_read , count - total_read );
226
+ if (ret == -1 ) {
227
+ return -1 ;
228
+ }
229
+ if (ret == 0 ) {
230
+ break ;
231
+ }
232
+ total_read += ret ;
233
+ }
234
+ return total_read ;
235
+ }
236
+
218
237
/* {{{ php_strnlen
219
238
* get length of string if buffer if less than buffer size or buffer size */
220
239
static size_t php_strnlen (char * str , size_t maxlen ) {
@@ -3321,7 +3340,7 @@ static bool exif_process_IFD_TAG_impl(image_info_type *ImageInfo, char *dir_entr
3321
3340
exif_error_docref (NULL EXIFERR_CC , ImageInfo , E_WARNING , "Wrong file pointer: 0x%08X != 0x%08X" , fgot , displacement + offset_val );
3322
3341
return false;
3323
3342
}
3324
- fgot = php_stream_read (ImageInfo -> infile , value_ptr , byte_count );
3343
+ fgot = exif_read_from_stream_file_looped (ImageInfo -> infile , value_ptr , byte_count );
3325
3344
php_stream_seek (ImageInfo -> infile , fpos , SEEK_SET );
3326
3345
if (fgot != byte_count ) {
3327
3346
EFREE_IF (outside );
@@ -3846,7 +3865,7 @@ static bool exif_scan_JPEG_header(image_info_type *ImageInfo)
3846
3865
Data [0 ] = (uchar )lh ;
3847
3866
Data [1 ] = (uchar )ll ;
3848
3867
3849
- got = php_stream_read (ImageInfo -> infile , (char * )(Data + 2 ), itemlen - 2 ); /* Read the whole section. */
3868
+ got = exif_read_from_stream_file_looped (ImageInfo -> infile , (char * )(Data + 2 ), itemlen - 2 ); /* Read the whole section. */
3850
3869
if (got != itemlen - 2 ) {
3851
3870
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 );
3852
3871
return false;
@@ -3864,7 +3883,7 @@ static bool exif_scan_JPEG_header(image_info_type *ImageInfo)
3864
3883
size = ImageInfo -> FileSize - fpos ;
3865
3884
sn = exif_file_sections_add (ImageInfo , M_PSEUDO , size , NULL );
3866
3885
Data = ImageInfo -> file .list [sn ].data ;
3867
- got = php_stream_read (ImageInfo -> infile , (char * )Data , size );
3886
+ got = exif_read_from_stream_file_looped (ImageInfo -> infile , (char * )Data , size );
3868
3887
if (got != size ) {
3869
3888
EXIF_ERRLOG_FILEEOF (ImageInfo )
3870
3889
return false ;
@@ -4041,7 +4060,9 @@ static bool exif_process_IFD_in_TIFF_impl(image_info_type *ImageInfo, size_t dir
4041
4060
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 );
4042
4061
#endif
4043
4062
php_stream_seek (ImageInfo -> infile , dir_offset , SEEK_SET ); /* we do not know the order of sections */
4044
- php_stream_read (ImageInfo -> infile , (char * )ImageInfo -> file .list [sn ].data , 2 );
4063
+ if (UNEXPECTED (exif_read_from_stream_file_looped (ImageInfo -> infile , (char * )ImageInfo -> file .list [sn ].data , 2 ) != 2 )) {
4064
+ return false;
4065
+ }
4045
4066
num_entries = php_ifd_get16u (ImageInfo -> file .list [sn ].data , ImageInfo -> motorola_intel );
4046
4067
dir_size = 2 /*num dir entries*/ + 12 /*length of entry*/ * (size_t )num_entries + 4 /* offset to next ifd (points to thumbnail or NULL)*/ ;
4047
4068
if (ImageInfo -> FileSize >= dir_size && ImageInfo -> FileSize - dir_size >= dir_offset ) {
@@ -4051,7 +4072,9 @@ static bool exif_process_IFD_in_TIFF_impl(image_info_type *ImageInfo, size_t dir
4051
4072
if (exif_file_sections_realloc (ImageInfo , sn , dir_size )) {
4052
4073
return false;
4053
4074
}
4054
- php_stream_read (ImageInfo -> infile , (char * )(ImageInfo -> file .list [sn ].data + 2 ), dir_size - 2 );
4075
+ if (UNEXPECTED (exif_read_from_stream_file_looped (ImageInfo -> infile , (char * )(ImageInfo -> file .list [sn ].data + 2 ), dir_size - 2 ) != dir_size - 2 )) {
4076
+ return false;
4077
+ }
4055
4078
next_offset = php_ifd_get32u (ImageInfo -> file .list [sn ].data + dir_size - 4 , ImageInfo -> motorola_intel );
4056
4079
#ifdef EXIF_DEBUG
4057
4080
exif_error_docref (NULL EXIFERR_CC , ImageInfo , E_NOTICE , "Read from TIFF done, next offset x%04X" , next_offset );
@@ -4139,7 +4162,7 @@ static bool exif_process_IFD_in_TIFF_impl(image_info_type *ImageInfo, size_t dir
4139
4162
#ifdef EXIF_DEBUG
4140
4163
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 );
4141
4164
#endif
4142
- php_stream_read (ImageInfo -> infile , (char * )(ImageInfo -> file .list [sn ].data + dir_size ), ifd_size - dir_size );
4165
+ exif_read_from_stream_file_looped (ImageInfo -> infile , (char * )(ImageInfo -> file .list [sn ].data + dir_size ), ifd_size - dir_size );
4143
4166
#ifdef EXIF_DEBUG
4144
4167
exif_error_docref (NULL EXIFERR_CC , ImageInfo , E_NOTICE , "Read from TIFF , done ");
4145
4168
#endif
@@ -4190,7 +4213,7 @@ static bool exif_process_IFD_in_TIFF_impl(image_info_type *ImageInfo, size_t dir
4190
4213
if (!ImageInfo -> Thumbnail .data ) {
4191
4214
ImageInfo -> Thumbnail .data = safe_emalloc (ImageInfo -> Thumbnail .size , 1 , 0 );
4192
4215
php_stream_seek (ImageInfo -> infile , ImageInfo -> Thumbnail .offset , SEEK_SET );
4193
- fgot = php_stream_read (ImageInfo -> infile , ImageInfo -> Thumbnail .data , ImageInfo -> Thumbnail .size );
4216
+ fgot = exif_read_from_stream_file_looped (ImageInfo -> infile , ImageInfo -> Thumbnail .data , ImageInfo -> Thumbnail .size );
4194
4217
if (fgot != ImageInfo -> Thumbnail .size ) {
4195
4218
EXIF_ERRLOG_THUMBEOF (ImageInfo )
4196
4219
efree (ImageInfo -> Thumbnail .data );
@@ -4230,7 +4253,7 @@ static bool exif_process_IFD_in_TIFF_impl(image_info_type *ImageInfo, size_t dir
4230
4253
if (!ImageInfo -> Thumbnail .data && ImageInfo -> Thumbnail .offset && ImageInfo -> Thumbnail .size && ImageInfo -> read_thumbnail ) {
4231
4254
ImageInfo -> Thumbnail .data = safe_emalloc (ImageInfo -> Thumbnail .size , 1 , 0 );
4232
4255
php_stream_seek (ImageInfo -> infile , ImageInfo -> Thumbnail .offset , SEEK_SET );
4233
- fgot = php_stream_read (ImageInfo -> infile , ImageInfo -> Thumbnail .data , ImageInfo -> Thumbnail .size );
4256
+ fgot = exif_read_from_stream_file_looped (ImageInfo -> infile , ImageInfo -> Thumbnail .data , ImageInfo -> Thumbnail .size );
4234
4257
if (fgot != ImageInfo -> Thumbnail .size ) {
4235
4258
EXIF_ERRLOG_THUMBEOF (ImageInfo )
4236
4259
efree (ImageInfo -> Thumbnail .data );
@@ -4285,7 +4308,7 @@ static bool exif_scan_FILE_header(image_info_type *ImageInfo)
4285
4308
4286
4309
if (ImageInfo -> FileSize >= 2 ) {
4287
4310
php_stream_seek (ImageInfo -> infile , 0 , SEEK_SET );
4288
- if (php_stream_read (ImageInfo -> infile , (char * )file_header , 2 ) != 2 ) {
4311
+ if (exif_read_from_stream_file_looped (ImageInfo -> infile , (char * )file_header , 2 ) != 2 ) {
4289
4312
return false;
4290
4313
}
4291
4314
if ((file_header [0 ]== 0xff ) && (file_header [1 ]== M_SOI )) {
@@ -4296,7 +4319,7 @@ static bool exif_scan_FILE_header(image_info_type *ImageInfo)
4296
4319
exif_error_docref (NULL EXIFERR_CC , ImageInfo , E_WARNING , "Invalid JPEG file ");
4297
4320
}
4298
4321
} else if (ImageInfo -> FileSize >= 8 ) {
4299
- if (php_stream_read (ImageInfo -> infile , (char * )(file_header + 2 ), 6 ) != 6 ) {
4322
+ if (exif_read_from_stream_file_looped (ImageInfo -> infile , (char * )(file_header + 2 ), 6 ) != 6 ) {
4300
4323
return false;
4301
4324
}
4302
4325
if (!memcmp (file_header , "II\x2A\x00" , 4 )) {
0 commit comments