diff options
| author | Přemysl Eric Janouch <p@janouch.name> | 2023-05-22 20:48:59 +0200 | 
|---|---|---|
| committer | Přemysl Eric Janouch <p@janouch.name> | 2023-05-22 20:56:28 +0200 | 
| commit | dba728e0c4ddcb2fda91b019ab420b6081757c2e (patch) | |
| tree | c9fd6a8e250c4c618e6a490a8bfd8f3af9a2b35d /tools | |
| parent | 544722f8e01a6408db00aecdcec4d842e481b7e2 (diff) | |
| download | fiv-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).
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/info.h | 36 | 
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)  | 
