1
0
mirror of https://github.com/cdcseacave/TinyEXIF.git synced 2026-07-21 19:23:01 +04:00

2 Commits

Author SHA1 Message Date
cDc b6ea1b7bbe Fix possible integer overflow in parseString bounds check (#26)
* Fix integer overflow in parseString bounds check

Cast `base` to `uint64_t` in the parseString bounds check
`base+data+num_components <= len` to prevent unsigned integer overflow.

When `data` is attacker-controlled (e.g. 0xffffffff), the 32-bit
unsigned addition wraps around, causing the check to pass even though
the computed offset is far beyond the buffer. This leads to an
out-of-bounds heap read or segfault when dereferencing the resulting
pointer.

Fixes #16

* Fix type casting for base pointer comparison
2026-03-19 06:55:25 +02:00
cDc 841e292929 Fix potential heap buffer overflow in EntryParser::Fetch methods (#25)
* Fix heap buffer overflow in EntryParser::Fetch methods

Add buffer bounds validation to indexed Fetch methods that compute
offsets from attacker-controlled EXIF data via GetSubIFD().

Previously, Fetch(uint16_t, idx), Fetch(double), and Fetch(double, idx)
would read from buf at offsets derived from parsed EXIF fields without
checking against the actual buffer length. A crafted JPEG with a
malicious SubjectArea length (tag 0x9214) could trigger a heap buffer
overflow via parse16() reads past the end of the buffer.

Fixes #24

* Fix include directive and simplify Fetch method
2026-03-19 06:26:24 +02:00
+9 -3
View File
@@ -205,7 +205,10 @@ public:
bool Fetch(uint16_t& val, uint32_t idx) const {
if (!IsShort() || length <= idx)
return false;
val = parse16(buf + GetSubIFD() + idx*2, alignIntel);
const uint32_t offset = GetSubIFD() + idx*2;
if (offset + 2 > len)
return false;
val = parse16(buf + offset, alignIntel);
return true;
}
bool Fetch(uint32_t& val) const {
@@ -229,7 +232,10 @@ public:
bool Fetch(double& val, uint32_t idx) const {
if (!IsRational() || length <= idx)
return false;
val = parseRational(buf + GetSubIFD() + idx*8, alignIntel, IsSRational());
const uint32_t offset = GetSubIFD() + idx*8;
if (offset + 8 > len)
return false;
val = parseRational(buf + offset, alignIntel, IsSRational());
return true;
}
@@ -295,7 +301,7 @@ public:
if (value[num_components-1] == '\0')
value.resize(num_components-1);
} else
if (base+data+num_components <= len) {
if ((uint64_t)base+data+num_components <= (uint64_t)len) {
const char* const sz((const char*)buf+base+data);
unsigned num(0);
while (num < num_components && sz[num] != '\0')