mirror of
https://github.com/taglib/taglib.git
synced 2026-08-27 12:47:01 -04:00
MP4: do not convert an out of range length to int
The mdhd duration is a signed 64 bit field in version 1 and the timescale sitting beside it is a 32 bit field that may be 1, so a 4 KB file can declare 2^62 units of a one-hertz clock. The millisecond length is then ~4.6e21 and the conversion to int is undefined: taglib/mp4/mp4properties.cpp:207:34: runtime error: 4.61169e+21 is outside the range of representable values of type 'int' The version 0 path reaches the same line with a 32 bit duration: taglib/mp4/mp4properties.cpp:207:34: runtime error: 4.29497e+12 is outside the range of representable values of type 'int' The mvhd fallback a few lines above feeds the same expression, so it is covered by the same guard. Leave the field at its default rather than converting. For the record, the other conversions in this file were checked and are not affected. The esds and alac nominal bitrates divide a 32 bit value by 1000.0, which cannot leave int's range, and the three calculateMdatLength() estimates are integer arithmetic on a long long rather than a double conversion. One report per file before the change, none after. The 18 MP4 files in tests/data report identical channels, sample rate, bitrate and length before and after, and the suite runs 576 tests either way. Assisted-By: Claude Code (Claude Opus 5)
This commit is contained in:
@@ -25,6 +25,8 @@
|
||||
|
||||
#include "mp4properties.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "tdebug.h"
|
||||
#include "tstring.h"
|
||||
#include "tmap.h"
|
||||
@@ -203,8 +205,15 @@ MP4::Properties::read(File *file, const Atoms *atoms)
|
||||
}
|
||||
}
|
||||
}
|
||||
if(unit > 0 && length > 0)
|
||||
d->length = static_cast<int>(static_cast<double>(length) * 1000.0 / static_cast<double>(unit) + 0.5);
|
||||
// The mdhd duration is a signed 64 bit field in version 1 and the timescale
|
||||
// beside it may be as low as 1, so the millisecond length can land outside
|
||||
// int. Converting a double the destination type cannot represent is
|
||||
// undefined, so leave the field at its default instead.
|
||||
if(unit > 0 && length > 0) {
|
||||
const double lengthMs = static_cast<double>(length) * 1000.0 / static_cast<double>(unit);
|
||||
if(lengthMs > 0.0 && lengthMs < static_cast<double>(std::numeric_limits<int>::max()))
|
||||
d->length = static_cast<int>(lengthMs + 0.5);
|
||||
}
|
||||
|
||||
MP4::Atom *atom = trak->find("mdia", "minf", "stbl", "stsd");
|
||||
if(!atom) {
|
||||
|
||||
Reference in New Issue
Block a user