@@ -215,6 +215,25 @@ zend_module_entry exif_module_entry = {
215215ZEND_GET_MODULE (exif )
216216#endif
217217
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+
218237/* {{{ php_strnlen
219238 * get length of string if buffer if less than buffer size or buffer size */
220239static 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
33213340 exif_error_docref (NULL EXIFERR_CC , ImageInfo , E_WARNING , "Wrong file pointer: 0x%08X != 0x%08X" , fgot , displacement + offset_val );
33223341 return false;
33233342 }
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 );
33253344 php_stream_seek (ImageInfo -> infile , fpos , SEEK_SET );
33263345 if (fgot != byte_count ) {
33273346 EFREE_IF (outside );
@@ -3854,7 +3873,7 @@ static bool exif_scan_JPEG_header(image_info_type *ImageInfo)
38543873 Data [0 ] = (uchar )lh ;
38553874 Data [1 ] = (uchar )ll ;
38563875
3857- got = php_stream_read (ImageInfo -> infile , (char * )(Data + 2 ), itemlen - 2 ); /* Read the whole section. */
3876+ got = exif_read_from_stream_file_looped (ImageInfo -> infile , (char * )(Data + 2 ), itemlen - 2 ); /* Read the whole section. */
38583877 if (got != itemlen - 2 ) {
38593878 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 );
38603879 return false;
@@ -3872,7 +3891,7 @@ static bool exif_scan_JPEG_header(image_info_type *ImageInfo)
38723891 size = ImageInfo -> FileSize - fpos ;
38733892 sn = exif_file_sections_add (ImageInfo , M_PSEUDO , size , NULL );
38743893 Data = ImageInfo -> file .list [sn ].data ;
3875- got = php_stream_read (ImageInfo -> infile , (char * )Data , size );
3894+ got = exif_read_from_stream_file_looped (ImageInfo -> infile , (char * )Data , size );
38763895 if (got != size ) {
38773896 EXIF_ERRLOG_FILEEOF (ImageInfo )
38783897 return false ;
@@ -4049,7 +4068,9 @@ static bool exif_process_IFD_in_TIFF_impl(image_info_type *ImageInfo, size_t dir
40494068 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 );
40504069#endif
40514070 php_stream_seek (ImageInfo -> infile , dir_offset , SEEK_SET ); /* we do not know the order of sections */
4052- php_stream_read (ImageInfo -> infile , (char * )ImageInfo -> file .list [sn ].data , 2 );
4071+ if (UNEXPECTED (exif_read_from_stream_file_looped (ImageInfo -> infile , (char * )ImageInfo -> file .list [sn ].data , 2 ) != 2 )) {
4072+ return false;
4073+ }
40534074 num_entries = php_ifd_get16u (ImageInfo -> file .list [sn ].data , ImageInfo -> motorola_intel );
40544075 dir_size = 2 /*num dir entries*/ + 12 /*length of entry*/ * (size_t )num_entries + 4 /* offset to next ifd (points to thumbnail or NULL)*/ ;
40554076 if (ImageInfo -> FileSize >= dir_size && ImageInfo -> FileSize - dir_size >= dir_offset ) {
@@ -4059,7 +4080,9 @@ static bool exif_process_IFD_in_TIFF_impl(image_info_type *ImageInfo, size_t dir
40594080 if (exif_file_sections_realloc (ImageInfo , sn , dir_size )) {
40604081 return false;
40614082 }
4062- php_stream_read (ImageInfo -> infile , (char * )(ImageInfo -> file .list [sn ].data + 2 ), dir_size - 2 );
4083+ if (UNEXPECTED (exif_read_from_stream_file_looped (ImageInfo -> infile , (char * )(ImageInfo -> file .list [sn ].data + 2 ), dir_size - 2 ) != dir_size - 2 )) {
4084+ return false;
4085+ }
40634086 next_offset = php_ifd_get32u (ImageInfo -> file .list [sn ].data + dir_size - 4 , ImageInfo -> motorola_intel );
40644087#ifdef EXIF_DEBUG
40654088 exif_error_docref (NULL EXIFERR_CC , ImageInfo , E_NOTICE , "Read from TIFF done, next offset x%04X" , next_offset );
@@ -4147,7 +4170,7 @@ static bool exif_process_IFD_in_TIFF_impl(image_info_type *ImageInfo, size_t dir
41474170#ifdef EXIF_DEBUG
41484171 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 );
41494172#endif
4150- php_stream_read (ImageInfo -> infile , (char * )(ImageInfo -> file .list [sn ].data + dir_size ), ifd_size - dir_size );
4173+ exif_read_from_stream_file_looped (ImageInfo -> infile , (char * )(ImageInfo -> file .list [sn ].data + dir_size ), ifd_size - dir_size );
41514174#ifdef EXIF_DEBUG
41524175 exif_error_docref (NULL EXIFERR_CC , ImageInfo , E_NOTICE , "Read from TIFF , done ");
41534176#endif
@@ -4198,7 +4221,7 @@ static bool exif_process_IFD_in_TIFF_impl(image_info_type *ImageInfo, size_t dir
41984221 if (!ImageInfo -> Thumbnail .data ) {
41994222 ImageInfo -> Thumbnail .data = safe_emalloc (ImageInfo -> Thumbnail .size , 1 , 0 );
42004223 php_stream_seek (ImageInfo -> infile , ImageInfo -> Thumbnail .offset , SEEK_SET );
4201- fgot = php_stream_read (ImageInfo -> infile , ImageInfo -> Thumbnail .data , ImageInfo -> Thumbnail .size );
4224+ fgot = exif_read_from_stream_file_looped (ImageInfo -> infile , ImageInfo -> Thumbnail .data , ImageInfo -> Thumbnail .size );
42024225 if (fgot != ImageInfo -> Thumbnail .size ) {
42034226 EXIF_ERRLOG_THUMBEOF (ImageInfo )
42044227 efree (ImageInfo -> Thumbnail .data );
@@ -4238,7 +4261,7 @@ static bool exif_process_IFD_in_TIFF_impl(image_info_type *ImageInfo, size_t dir
42384261 if (!ImageInfo -> Thumbnail .data && ImageInfo -> Thumbnail .offset && ImageInfo -> Thumbnail .size && ImageInfo -> read_thumbnail ) {
42394262 ImageInfo -> Thumbnail .data = safe_emalloc (ImageInfo -> Thumbnail .size , 1 , 0 );
42404263 php_stream_seek (ImageInfo -> infile , ImageInfo -> Thumbnail .offset , SEEK_SET );
4241- fgot = php_stream_read (ImageInfo -> infile , ImageInfo -> Thumbnail .data , ImageInfo -> Thumbnail .size );
4264+ fgot = exif_read_from_stream_file_looped (ImageInfo -> infile , ImageInfo -> Thumbnail .data , ImageInfo -> Thumbnail .size );
42424265 if (fgot != ImageInfo -> Thumbnail .size ) {
42434266 EXIF_ERRLOG_THUMBEOF (ImageInfo )
42444267 efree (ImageInfo -> Thumbnail .data );
@@ -4293,7 +4316,7 @@ static bool exif_scan_FILE_header(image_info_type *ImageInfo)
42934316
42944317 if (ImageInfo -> FileSize >= 2 ) {
42954318 php_stream_seek (ImageInfo -> infile , 0 , SEEK_SET );
4296- if (php_stream_read (ImageInfo -> infile , (char * )file_header , 2 ) != 2 ) {
4319+ if (exif_read_from_stream_file_looped (ImageInfo -> infile , (char * )file_header , 2 ) != 2 ) {
42974320 return false;
42984321 }
42994322 if ((file_header [0 ]== 0xff ) && (file_header [1 ]== M_SOI )) {
@@ -4304,7 +4327,7 @@ static bool exif_scan_FILE_header(image_info_type *ImageInfo)
43044327 exif_error_docref (NULL EXIFERR_CC , ImageInfo , E_WARNING , "Invalid JPEG file ");
43054328 }
43064329 } else if (ImageInfo -> FileSize >= 8 ) {
4307- if (php_stream_read (ImageInfo -> infile , (char * )(file_header + 2 ), 6 ) != 6 ) {
4330+ if (exif_read_from_stream_file_looped (ImageInfo -> infile , (char * )(file_header + 2 ), 6 ) != 6 ) {
43084331 return false;
43094332 }
43104333 if (!memcmp (file_header , "II\x2A\x00" , 4 )) {
0 commit comments