aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPřemysl Eric Janouch <p@janouch.name>2023-05-28 04:55:03 +0200
committerPřemysl Eric Janouch <p@janouch.name>2023-05-28 08:12:27 +0200
commit8668e85623e31fb742d2a38f061a82ee4d8fa5fc (patch)
treed27d7d4dcc227e43691e05bcd647e298c5634501
parent902eaf5a015145c56894f21315420de29f28337c (diff)
downloadfiv-8668e85623e31fb742d2a38f061a82ee4d8fa5fc.tar.gz
fiv-8668e85623e31fb742d2a38f061a82ee4d8fa5fc.tar.xz
fiv-8668e85623e31fb742d2a38f061a82ee4d8fa5fc.zip
Make MPF parsing a bit safer
-rw-r--r--tools/info.h49
1 files changed, 34 insertions, 15 deletions
diff --git a/tools/info.h b/tools/info.h
index b15b1d5..e28d153 100644
--- a/tools/info.h
+++ b/tools/info.h
@@ -725,7 +725,7 @@ parse_mpf_mpentry(jv *a, const uint8_t *p, const struct tiffer *T)
}
static jv
-parse_mpf_index_entry(jv o, const uint8_t ***offsets, const struct tiffer *T,
+parse_mpf_index_entry(jv o, uint32_t **offsets, const struct tiffer *T,
struct tiffer_entry *entry)
{
// 5.2.3.3. MP Entry
@@ -736,20 +736,18 @@ parse_mpf_index_entry(jv o, const uint8_t ***offsets, const struct tiffer *T,
uint32_t count = entry->remaining_count / 16;
jv a = jv_array_sized(count);
- const uint8_t **out = *offsets = calloc(sizeof *out, count + 1);
+ uint32_t *out = *offsets = calloc(sizeof *out, count + 1);
for (uint32_t i = 0; i < count; i++) {
// 5.2.3.3.3. Individual Image Data Offset
- // XXX: We might want to warn about out-of-bounds pointers,
- // however T->end is for the MPF segment and ends too early.
uint32_t offset = parse_mpf_mpentry(&a, entry->p + i * 16, T);
if (offset)
- *out++ = T->begin + offset;
+ *out++ = offset;
}
return jv_set(o, jv_string("MP Entry"), a);
}
static jv
-parse_mpf_index_ifd(const uint8_t ***offsets, struct tiffer *T)
+parse_mpf_index_ifd(uint32_t **offsets, struct tiffer *T)
{
jv ifd = jv_object();
struct tiffer_entry entry = {};
@@ -759,7 +757,8 @@ parse_mpf_index_ifd(const uint8_t ***offsets, struct tiffer *T)
}
static jv
-parse_mpf(jv o, const uint8_t ***offsets, const uint8_t *p, size_t len)
+parse_mpf(jv o, const uint8_t ***individuals, const uint8_t *p, size_t len,
+ const uint8_t *end)
{
struct tiffer T;
if (!tiffer_init(&T, p, len) || !tiffer_next_ifd(&T))
@@ -767,14 +766,34 @@ parse_mpf(jv o, const uint8_t ***offsets, const uint8_t *p, size_t len)
// First image: IFD0 is Index IFD, any IFD1 is Attribute IFD.
// Other images: IFD0 is Attribute IFD, there is no Index IFD.
- if (!*offsets) {
- o = add_to_subarray(o, "MPF", parse_mpf_index_ifd(offsets, &T));
+ uint32_t *offsets = NULL;
+ if (!*individuals) {
+ o = add_to_subarray(o, "MPF", parse_mpf_index_ifd(&offsets, &T));
if (!tiffer_next_ifd(&T))
- return o;
+ goto out;
}
// This isn't optimal, but it will do.
- return add_to_subarray(o, "MPF", parse_exif_ifd(&T, mpf_entries));
+ o = add_to_subarray(o, "MPF", parse_exif_ifd(&T, mpf_entries));
+
+out:
+ if (offsets) {
+ size_t count = 0;
+ for (const uint32_t *i = offsets; *i; i++)
+ count++;
+
+ free(*individuals);
+ const uint8_t **out = *individuals = calloc(sizeof *out, count + 1);
+ for (const uint32_t *i = offsets; *i; i++) {
+ if (*i > end - p)
+ o = add_warning(o, "MPF offset points past available data");
+ else
+ *out++ = p + *i;
+ }
+
+ free(offsets);
+ }
+ return o;
}
// --- JPEG --------------------------------------------------------------------
@@ -907,7 +926,7 @@ struct data {
uint8_t *exif, *icc, *psir;
size_t exif_len, icc_len, psir_len;
int icc_sequence, icc_done;
- const uint8_t **mpf_offsets, **mpf_next;
+ const uint8_t **mpf_individuals, **mpf_next;
};
static void
@@ -927,7 +946,7 @@ parse_marker(uint8_t marker, const uint8_t *p, const uint8_t *end,
// Found: Random metadata! Multi-Picture Format!
if ((data->ended = marker == EOI)) {
// TODO(p): Handle Exifs independently--flush the last one.
- if ((data->mpf_next || (data->mpf_next = data->mpf_offsets)) &&
+ if ((data->mpf_next || (data->mpf_next = data->mpf_individuals)) &&
*data->mpf_next)
return *data->mpf_next++;
if (p != end)
@@ -1034,7 +1053,7 @@ parse_marker(uint8_t marker, const uint8_t *p, const uint8_t *end,
// http://fileformats.archiveteam.org/wiki/Multi-Picture_Format
if (marker == APP2 && p - payload >= 8 && !memcmp(payload, "MPF\0", 4)) {
payload += 4;
- *o = parse_mpf(*o, &data->mpf_offsets, payload, p - payload);
+ *o = parse_mpf(*o, &data->mpf_individuals, payload, p - payload, end);
}
// CIPA DC-006 (Stereo Still Image Format for Digital Cameras)
@@ -1157,6 +1176,6 @@ parse_jpeg(jv o, const uint8_t *p, size_t len)
free(data.psir);
}
- free(data.mpf_offsets);
+ free(data.mpf_individuals);
return jv_set(o, jv_string("markers"), markers);
}