Skip to content

Commit 237604b

Browse files
committed
revise heifload EOF detection
VipsSource used a unix-style model where read() returns 0 to mean EOF. libheif uses a model where a separate call to wait_for_file_size() beforehand is used to check thaht the read will be OK, and then the read() is expected to never fail. We were trying to put EOF detection into libheif read(), but that's not the right way to do it. Instead, test for EOF in wait_for_file_size(). see #1833
1 parent 7829518 commit 237604b

File tree

2 files changed

+22
-28
lines changed

2 files changed

+22
-28
lines changed

ChangeLog

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
- allow gaussblur sigma zero, meaning no blur
1010
- better heif signature detection [lovell]
1111
- fix vips_fractsurf() typo [kleisauke]
12+
- better heif EOF detection [lovell]
1213

1314
9/8/20 started 8.10.1
1415
- fix markdown -> xml conversion in doc generation

libvips/foreign/heifload.c

Lines changed: 21 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,6 @@ typedef struct _VipsForeignLoadHeif {
173173
*/
174174
struct heif_reader *reader;
175175

176-
/* When we see EOF from read(), record the source length here.
177-
*/
178-
gint64 length;
179-
180176
} VipsForeignLoadHeif;
181177

182178
typedef struct _VipsForeignLoadHeifClass {
@@ -920,6 +916,11 @@ vips_foreign_load_heif_get_position( void *userdata )
920916
return( vips_source_seek( heif->source, 0L, SEEK_CUR ) );
921917
}
922918

919+
/* libheif read() does not work like unix read().
920+
*
921+
* This method is cannot return EOF. Instead, the separate wait_for_file_size()
922+
* is called beforehand to make sure that there's enough data there.
923+
*/
923924
static int
924925
vips_foreign_load_heif_read( void *data, size_t size, void *userdata )
925926
{
@@ -928,16 +929,6 @@ vips_foreign_load_heif_read( void *data, size_t size, void *userdata )
928929
gint64 result;
929930

930931
result = vips_source_read( heif->source, data, size );
931-
/* On EOF, make a note of the file length.
932-
*
933-
* libheif can sometimes ask for zero bytes, be careful not to
934-
* interpret that as EOF.
935-
*/
936-
if( size > 0 &&
937-
result == 0 &&
938-
heif->length == -1 )
939-
result = heif->length =
940-
vips_source_seek( heif->source, 0L, SEEK_CUR );
941932
if( result < 0 )
942933
return( -1 );
943934

@@ -954,30 +945,33 @@ vips_foreign_load_heif_seek( gint64 position, void *userdata )
954945
return( 0 );
955946
}
956947

948+
/* libheif calls this to mean "I intend to read() to this position, please
949+
* check it is OK".
950+
*/
957951
static enum heif_reader_grow_status
958952
vips_foreign_load_heif_wait_for_file_size( gint64 target_size, void *userdata )
959953
{
960954
VipsForeignLoadHeif *heif = (VipsForeignLoadHeif *) userdata;
961955

956+
gint64 old_position;
957+
gint64 result;
962958
enum heif_reader_grow_status status;
963959

964-
if( heif->source->data != NULL && target_size > heif->source->length )
965-
/* Target size is beyond known buffer length
960+
/* We seek the VipsSource to the position and check for errors.
961+
*/
962+
old_position = vips_source_seek( heif->source, 0L, SEEK_CUR );
963+
result = vips_source_seek( heif->source, target_size, SEEK_SET );
964+
vips_source_seek( heif->source, old_position, SEEK_SET );
965+
966+
if( result < 0 )
967+
/* Unable to seek to this point, so it's beyond EOF.
966968
*/
967969
status = heif_reader_grow_status_size_beyond_eof;
968-
else if( heif->length == -1 )
969-
/* We've not seen EOF yet, so seeking to any point is fine (as
970-
* far as we know).
971-
*/
972-
status = heif_reader_grow_status_size_reached;
973-
else if( target_size <= heif->length )
974-
/* We've seen EOF, and this target is less than that.
975-
*/
976-
status = heif_reader_grow_status_size_reached;
977970
else
978-
/* We've seen EOF, we know the length, and this is too far.
971+
/* Successfully read to the requested point, but the requested
972+
* point is not necessarily EOF.
979973
*/
980-
status = heif_reader_grow_status_size_beyond_eof;
974+
status = heif_reader_grow_status_size_reached;
981975

982976
return( status );
983977
}
@@ -986,7 +980,6 @@ static void
986980
vips_foreign_load_heif_init( VipsForeignLoadHeif *heif )
987981
{
988982
heif->n = 1;
989-
heif->length = -1;
990983

991984
heif->reader = VIPS_ARRAY( NULL, 1, struct heif_reader );
992985

0 commit comments

Comments
 (0)