diff options
author | Přemysl Eric Janouch <p@janouch.name> | 2023-05-28 03:22:36 +0200 |
---|---|---|
committer | Přemysl Eric Janouch <p@janouch.name> | 2023-05-28 08:12:22 +0200 |
commit | 902eaf5a015145c56894f21315420de29f28337c (patch) | |
tree | 9b01a3f5e04080dd7c0b9690d260b46c3236a9ee | |
parent | df7c7b9f6b12a80f3a1de01c35e77ef2f919d28e (diff) | |
download | fiv-902eaf5a015145c56894f21315420de29f28337c.tar.gz fiv-902eaf5a015145c56894f21315420de29f28337c.tar.xz fiv-902eaf5a015145c56894f21315420de29f28337c.zip |
Make TIFF parsing a bit safer
At least on 64-bit systems, 32-bit may still have holes.
-rw-r--r-- | fiv-io.c | 9 | ||||
-rw-r--r-- | tiffer.h | 15 | ||||
-rw-r--r-- | tools/info.h | 15 |
3 files changed, 23 insertions, 16 deletions
@@ -1844,11 +1844,10 @@ tiff_ep_find_jpeg_evaluate(const struct tiffer *T, struct tiff_ep_jpeg *out) } int64_t ipointer = 0, ilength = 0; - if (!tiffer_find_integer(T, tag_pointer, &ipointer) || - !tiffer_find_integer(T, tag_length, &ilength) || - ipointer <= 0 || ilength <= 0 || - (uint64_t) ilength > SIZE_MAX || - ipointer + ilength > (T->end - T->begin)) + if (!tiffer_find_integer(T, tag_pointer, &ipointer) || ipointer <= 0 || + !tiffer_find_integer(T, tag_length, &ilength) || ilength <= 0 || + ipointer > T->end - T->begin || + T->end - T->begin - ipointer < ilength) return; // Note that to get the largest JPEG, @@ -15,9 +15,10 @@ // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // +#include <stdbool.h> +#include <stddef.h> #include <stdint.h> #include <string.h> -#include <stdbool.h> // --- Utilities --------------------------------------------------------------- @@ -85,7 +86,7 @@ struct tiffer { static bool tiffer_u32(struct tiffer *self, uint32_t *u) { - if (self->p < self->begin || self->p + 4 > self->end) + if (self->end - self->p < 4) return false; *u = self->un->u32(self->p); @@ -96,7 +97,7 @@ tiffer_u32(struct tiffer *self, uint32_t *u) static bool tiffer_u16(struct tiffer *self, uint16_t *u) { - if (self->p < self->begin || self->p + 2 > self->end) + if (self->end - self->p < 2) return false; *u = self->un->u16(self->p); @@ -160,6 +161,9 @@ static bool tiffer_subifd( const struct tiffer *self, uint32_t offset, struct tiffer *subreader) { + if (self->end - self->begin < offset) + return false; + *subreader = *self; subreader->p = subreader->begin + offset; return tiffer_u16(subreader, &subreader->remaining_fields); @@ -323,14 +327,15 @@ tiffer_next_entry(struct tiffer *self, struct tiffer_entry *entry) if (values_size <= sizeof offset) { entry->p = self->p; self->p += sizeof offset; - } else if (tiffer_u32(self, &offset)) { + } else if (tiffer_u32(self, &offset) && self->end - self->begin >= offset) { entry->p = self->begin + offset; } else { return false; } // All entries are pre-checked not to overflow. - if (entry->p + values_size > self->end) + if (values_size > PTRDIFF_MAX || + self->end - entry->p < (ptrdiff_t) values_size) return false; // Setting it at the end may provide an indication while debugging. diff --git a/tools/info.h b/tools/info.h index 8dcd3d2..b15b1d5 100644 --- a/tools/info.h +++ b/tools/info.h @@ -92,8 +92,8 @@ static jv parse_jpeg(jv o, const uint8_t *p, size_t len); 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) +parse_exif_subifds_entry(const struct tiffer *T, + const struct tiffer_entry *entry, struct tiffer *subT) { int64_t offset = 0; return tiffer_integer(T, entry, &offset) && @@ -101,7 +101,7 @@ parse_exif_subifds_entry(struct tiffer *T, const struct tiffer_entry *entry, } static jv -parse_exif_subifds(struct tiffer *T, struct tiffer_entry *entry, +parse_exif_subifds(const struct tiffer *T, struct tiffer_entry *entry, struct tiff_entry *info) { struct tiffer subT = {}; @@ -173,7 +173,7 @@ parse_exif_extract_sole_array_element(jv a) } static jv -parse_exif_entry(jv o, struct tiffer *T, struct tiffer_entry *entry, +parse_exif_entry(jv o, const struct tiffer *T, struct tiffer_entry *entry, const struct tiff_entry *info) { static struct tiff_entry empty[] = {{}}; @@ -679,7 +679,7 @@ static struct tiff_entry mpf_entries[] = { }; static uint32_t -parse_mpf_mpentry(jv *a, const uint8_t *p, struct tiffer *T) +parse_mpf_mpentry(jv *a, const uint8_t *p, const struct tiffer *T) { uint32_t attrs = T->un->u32(p); uint32_t offset = T->un->u32(p + 8); @@ -725,7 +725,7 @@ parse_mpf_mpentry(jv *a, const uint8_t *p, struct tiffer *T) } static jv -parse_mpf_index_entry(jv o, const uint8_t ***offsets, struct tiffer *T, +parse_mpf_index_entry(jv o, const uint8_t ***offsets, const struct tiffer *T, struct tiffer_entry *entry) { // 5.2.3.3. MP Entry @@ -738,6 +738,9 @@ parse_mpf_index_entry(jv o, const uint8_t ***offsets, struct tiffer *T, jv a = jv_array_sized(count); const uint8_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; |