aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPřemysl Eric Janouch <p@janouch.name>2023-05-22 20:48:59 +0200
committerPřemysl Eric Janouch <p@janouch.name>2023-05-22 20:56:28 +0200
commitdba728e0c4ddcb2fda91b019ab420b6081757c2e (patch)
treec9fd6a8e250c4c618e6a490a8bfd8f3af9a2b35d
parent544722f8e01a6408db00aecdcec4d842e481b7e2 (diff)
downloadfiv-dba728e0c4ddcb2fda91b019ab420b6081757c2e.tar.gz
fiv-dba728e0c4ddcb2fda91b019ab420b6081757c2e.tar.xz
fiv-dba728e0c4ddcb2fda91b019ab420b6081757c2e.zip
Improve TIFF handling within tools
Nikon NEFs violate TIFF Tech Note 1, and it is easy to detect. Also guard against more pointer overflows, and fix a temporary array being used outside of its scope (found by a compiler).
-rw-r--r--tools/info.h36
1 files changed, 26 insertions, 10 deletions
diff --git a/tools/info.h b/tools/info.h
index 816c9cf..3853ae9 100644
--- a/tools/info.h
+++ b/tools/info.h
@@ -96,8 +96,9 @@ struct tiffer {
static bool
tiffer_u32(struct tiffer *self, uint32_t *u)
{
- if (self->p + 4 > self->end)
+ if (self->p < self->begin || self->p + 4 > self->end)
return false;
+
*u = self->un->u32(self->p);
self->p += 4;
return true;
@@ -106,8 +107,9 @@ tiffer_u32(struct tiffer *self, uint32_t *u)
static bool
tiffer_u16(struct tiffer *self, uint16_t *u)
{
- if (self->p + 2 > self->end)
+ if (self->p < self->begin || self->p + 2 > self->end)
return false;
+
*u = self->un->u16(self->p);
self->p += 2;
return true;
@@ -403,22 +405,35 @@ add_error(jv o, const char *message)
static jv parse_exif_ifd(struct tiffer *T, const struct tiff_entry *info);
+static bool
+parse_exif_subifds_entry(struct tiffer *T, const struct tiffer_entry *entry,
+ struct tiffer *subT)
+{
+ int64_t offset = 0;
+ return tiffer_integer(T, entry, &offset) &&
+ offset >= 0 && offset <= UINT32_MAX && tiffer_subifd(T, offset, subT);
+}
+
static jv
-parse_exif_subifds(struct tiffer *T, const struct tiffer_entry *entry,
+parse_exif_subifds(struct tiffer *T, struct tiffer_entry *entry,
struct tiff_entry *info)
{
- int64_t offset = 0;
struct tiffer subT = {};
- if (!tiffer_integer(T, entry, &offset) ||
- offset < 0 || offset > UINT32_MAX || !tiffer_subifd(T, offset, &subT))
+ if (!parse_exif_subifds_entry(T, entry, &subT))
return jv_null();
- // The chain should correspond to the values in the entry
- // (TIFF Technical Note 1), we are not going to verify it.
- // Note that Nikon NEFs do not follow this rule.
jv a = jv_array();
do a = jv_array_append(a, parse_exif_ifd(&subT, info));
while (tiffer_next_ifd(&subT));
+
+ // The chain should correspond to the values in the entry (see TIFF
+ // Technical Note 1: "the NextIFD value of Child #1 must point to Child #2,
+ // and so on"), but at least some Nikon NEFs do not follow this rule.
+ if (jv_array_length(jv_copy(a)) == 1) {
+ while (tiffer_next_value(entry) &&
+ parse_exif_subifds_entry(T, entry, &subT))
+ a = jv_array_append(a, parse_exif_ifd(&subT, info));
+ }
return a;
}
@@ -475,8 +490,9 @@ static jv
parse_exif_entry(jv o, struct tiffer *T, struct tiffer_entry *entry,
const struct tiff_entry *info)
{
+ static struct tiff_entry empty[] = {{}};
if (!info)
- info = (struct tiff_entry[]) {{}};
+ info = empty;
for (; info->name; info++)
if (info->tag == entry->tag)