Skip any remaining "dimg" box byte
As it is done for "ipma" boxes.
Also shorten 'is_parsable' assignment.
Also declare AVIFINFO_MAX_VALUE as a constant with the others.
Change-Id: I480cc9e8984504d7dc767302d88e926a4eb56c83
diff --git a/avifinfo.c b/avifinfo.c
index 5b93d19..90e02bf 100644
--- a/avifinfo.c
+++ b/avifinfo.c
@@ -34,14 +34,15 @@
// uint32_t is used everywhere in this file. It is unlikely to be insufficient
// to parse AVIF headers.
#define AVIFINFO_MAX_SIZE UINT32_MAX
-// AvifInfoInternalFeatures uses uint8_t to store values and the number of
-// values is clamped to 32 to limit the stack size.
+// Be reasonable. Avoid timeouts and out-of-memory.
+#define AVIFINFO_MAX_NUM_BOXES 4096
+// AvifInfoInternalFeatures uses uint8_t to store values.
#define AVIFINFO_MAX_VALUE UINT8_MAX
-#define AVIFINFO_UNDEFINED 0
// Maximum number of stored associations. Past that, they are skipped.
#define AVIFINFO_MAX_TILES 16
#define AVIFINFO_MAX_PROPS 32
#define AVIFINFO_MAX_FEATURES 8
+#define AVIFINFO_UNDEFINED 0
// Reads an unsigned integer from 'input' with most significant bits first.
// 'input' must be at least 'num_bytes'-long.
@@ -286,7 +287,7 @@
box->content_size = box->size - box_header_size;
// Avoid timeouts. The maximum number of parsed boxes is arbitrary.
++*num_parsed_boxes;
- AVIFINFO_CHECK(*num_parsed_boxes < 4096, kAborted);
+ AVIFINFO_CHECK(*num_parsed_boxes < AVIFINFO_MAX_NUM_BOXES, kAborted);
box->version = 0;
box->flags = 0;
@@ -297,14 +298,14 @@
// See AV1 Image File Format (AVIF) 8.1
// at https://aomediacodec.github.io/av1-avif/#avif-boxes (available when
// https://github.com/AOMediaCodec/av1-avif/pull/170 is merged).
- uint32_t is_parsable = 1;
- if (!memcmp(box->type, "meta", 4)) is_parsable = (box->version <= 0);
- if (!memcmp(box->type, "pitm", 4)) is_parsable = (box->version <= 1);
- if (!memcmp(box->type, "ipma", 4)) is_parsable = (box->version <= 1);
- if (!memcmp(box->type, "ispe", 4)) is_parsable = (box->version <= 0);
- if (!memcmp(box->type, "pixi", 4)) is_parsable = (box->version <= 0);
- if (!memcmp(box->type, "iref", 4)) is_parsable = (box->version <= 1);
- if (!memcmp(box->type, "auxC", 4)) is_parsable = (box->version <= 0);
+ const uint32_t is_parsable =
+ (!memcmp(box->type, "meta", 4) && box->version <= 0) ||
+ (!memcmp(box->type, "pitm", 4) && box->version <= 1) ||
+ (!memcmp(box->type, "ipma", 4) && box->version <= 1) ||
+ (!memcmp(box->type, "ispe", 4) && box->version <= 0) ||
+ (!memcmp(box->type, "pixi", 4) && box->version <= 0) ||
+ (!memcmp(box->type, "iref", 4) && box->version <= 1) ||
+ (!memcmp(box->type, "auxC", 4) && box->version <= 0);
// Instead of considering this file as invalid, skip unparsable boxes.
if (!is_parsable) memcpy(box->type, "\0skp", 4); // \0 so not a valid type
}
@@ -503,6 +504,7 @@
AVIFINFO_CHECK_NOT_FOUND(
AvifInfoInternalGetPrimaryItemFeatures(features));
+ // Mostly if 'data_was_skipped'.
AVIFINFO_CHECK_FOUND(
AvifInfoInternalSkip(stream, box.content_size - num_read_bytes));
} else {
@@ -566,6 +568,10 @@
// If all features are available now, do not look further.
AVIFINFO_CHECK_NOT_FOUND(
AvifInfoInternalGetPrimaryItemFeatures(features));
+
+ // Mostly if 'data_was_skipped'.
+ AVIFINFO_CHECK_FOUND(
+ AvifInfoInternalSkip(stream, box.content_size - num_read_bytes));
} else {
AVIFINFO_CHECK_FOUND(AvifInfoInternalSkip(stream, box.content_size));
}
diff --git a/avifinfo.php b/avifinfo.php
index d46be59..84a2e93 100644
--- a/avifinfo.php
+++ b/avifinfo.php
@@ -18,12 +18,13 @@
const ABORTED = 3; // Input correctly parsed until stopped to avoid timeout or crash.
const INVALID = 4; // Input incorrectly parsed.
-const MAX_SIZE = 4294967295; // Unlikely to be insufficient to parse AVIF headers.
-const MAX_VALUE = 255; // Be reasonable. Avoid timeouts and out-of-memory.
-const MAX_TILES = 16; // Be reasonable.
-const MAX_PROPS = 32; // Be reasonable.
-const MAX_FEATURES = 8; // Be reasonable.
-const UNDEFINED = 0; // Value was not yet parsed.
+const MAX_SIZE = 4294967295; // Unlikely to be insufficient to parse AVIF headers.
+const MAX_NUM_BOXES = 4096; // Be reasonable. Avoid timeouts and out-of-memory.
+const MAX_VALUE = 255;
+const MAX_TILES = 16;
+const MAX_PROPS = 32;
+const MAX_FEATURES = 8;
+const UNDEFINED = 0; // Value was not yet parsed.
/**
* Reads an unsigned integer with most significant bits first.
@@ -271,7 +272,7 @@
$this->content_size = $this->size - $header_size;
// Avoid timeouts. The maximum number of parsed boxes is arbitrary.
++$num_parsed_boxes;
- if ( $num_parsed_boxes >= 4096 ) {
+ if ( $num_parsed_boxes >= MAX_NUM_BOXES ) {
return ABORTED;
}
@@ -286,22 +287,13 @@
// See AV1 Image File Format (AVIF) 8.1
// at https://aomediacodec.github.io/av1-avif/#avif-boxes (available when
// https://github.com/AOMediaCodec/av1-avif/pull/170 is merged).
- $is_parsable = true;
- if ( $this->type == 'meta' ) {
- $is_parsable = ( $this->version <= 0 );
- } else if ( $this->type == 'pitm' ) {
- $is_parsable = ( $this->version <= 1 );
- } else if ( $this->type == 'ipma' ) {
- $is_parsable = ( $this->version <= 1 );
- } else if ( $this->type == 'ispe' ) {
- $is_parsable = ( $this->version <= 0 );
- } else if ( $this->type == 'pixi' ) {
- $is_parsable = ( $this->version <= 0 );
- } else if ( $this->type == 'iref' ) {
- $is_parsable = ( $this->version <= 1 );
- } else if ( $this->type == 'auxC' ) {
- $is_parsable = ( $this->version <= 0 );
- }
+ $is_parsable = ( $this->type == 'meta' && $this->version <= 0 ) ||
+ ( $this->type == 'pitm' && $this->version <= 1 ) ||
+ ( $this->type == 'ipma' && $this->version <= 1 ) ||
+ ( $this->type == 'ispe' && $this->version <= 0 ) ||
+ ( $this->type == 'pixi' && $this->version <= 0 ) ||
+ ( $this->type == 'iref' && $this->version <= 1 ) ||
+ ( $this->type == 'auxC' && $this->version <= 0 );
// Instead of considering this file as invalid, skip unparsable boxes.
if ( !$is_parsable ) {
$this->type = 'unknownversion';