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).
This commit is contained in:
parent
544722f8e0
commit
dba728e0c4
38
tools/info.h
38
tools/info.h
|
@ -96,8 +96,9 @@ struct tiffer {
|
||||||
static bool
|
static bool
|
||||||
tiffer_u32(struct tiffer *self, uint32_t *u)
|
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;
|
return false;
|
||||||
|
|
||||||
*u = self->un->u32(self->p);
|
*u = self->un->u32(self->p);
|
||||||
self->p += 4;
|
self->p += 4;
|
||||||
return true;
|
return true;
|
||||||
|
@ -106,8 +107,9 @@ tiffer_u32(struct tiffer *self, uint32_t *u)
|
||||||
static bool
|
static bool
|
||||||
tiffer_u16(struct tiffer *self, uint16_t *u)
|
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;
|
return false;
|
||||||
|
|
||||||
*u = self->un->u16(self->p);
|
*u = self->un->u16(self->p);
|
||||||
self->p += 2;
|
self->p += 2;
|
||||||
return true;
|
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 jv parse_exif_ifd(struct tiffer *T, const struct tiff_entry *info);
|
||||||
|
|
||||||
static jv
|
static bool
|
||||||
parse_exif_subifds(struct tiffer *T, const struct tiffer_entry *entry,
|
parse_exif_subifds_entry(struct tiffer *T, const struct tiffer_entry *entry,
|
||||||
struct tiff_entry *info)
|
struct tiffer *subT)
|
||||||
{
|
{
|
||||||
int64_t offset = 0;
|
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, struct tiffer_entry *entry,
|
||||||
|
struct tiff_entry *info)
|
||||||
|
{
|
||||||
struct tiffer subT = {};
|
struct tiffer subT = {};
|
||||||
if (!tiffer_integer(T, entry, &offset) ||
|
if (!parse_exif_subifds_entry(T, entry, &subT))
|
||||||
offset < 0 || offset > UINT32_MAX || !tiffer_subifd(T, offset, &subT))
|
|
||||||
return jv_null();
|
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();
|
jv a = jv_array();
|
||||||
do a = jv_array_append(a, parse_exif_ifd(&subT, info));
|
do a = jv_array_append(a, parse_exif_ifd(&subT, info));
|
||||||
while (tiffer_next_ifd(&subT));
|
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;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,8 +490,9 @@ static jv
|
||||||
parse_exif_entry(jv o, struct tiffer *T, struct tiffer_entry *entry,
|
parse_exif_entry(jv o, struct tiffer *T, struct tiffer_entry *entry,
|
||||||
const struct tiff_entry *info)
|
const struct tiff_entry *info)
|
||||||
{
|
{
|
||||||
|
static struct tiff_entry empty[] = {{}};
|
||||||
if (!info)
|
if (!info)
|
||||||
info = (struct tiff_entry[]) {{}};
|
info = empty;
|
||||||
|
|
||||||
for (; info->name; info++)
|
for (; info->name; info++)
|
||||||
if (info->tag == entry->tag)
|
if (info->tag == entry->tag)
|
||||||
|
|
Loading…
Reference in New Issue