From 1681864d79409191417dec4f3fc86ec1d35da39f Mon Sep 17 00:00:00 2001 From: YuLi Date: Thu, 23 Jul 2026 20:21:33 -0700 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dmp4=E5=BC=82=E5=B8=B8?= =?UTF-8?q?=E8=A7=86=E9=A2=91=E5=B0=BA=E5=AF=B8=E5=8F=AF=E8=83=BD=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E7=9A=84=E6=9C=AA=E5=AE=9A=E4=B9=89=E8=A1=8C=E4=B8=BA?= =?UTF-8?q?=20(#4785)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit libmov 的 `mov_add_video()` 接收 `int` 类型的视频宽高,并直接执行: ```c track->tkhd.width = width << 16; track->tkhd.height = height << 16; ``` 这是为了生成 MP4 Track Header 使用的 16.16 定点数。 当输入轨道包含异常视频尺寸,例如负数或在 32 位 int 平台上大于 32767 的值时,左移操作会产生有符号整数溢出,构成未定义行为,可能导致程序异常终止或生成错误的 MP4 轨道信息。 --- src/Record/MP4Muxer.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/Record/MP4Muxer.cpp b/src/Record/MP4Muxer.cpp index 35dec7fd..8941f383 100644 --- a/src/Record/MP4Muxer.cpp +++ b/src/Record/MP4Muxer.cpp @@ -10,6 +10,8 @@ #if defined(ENABLE_MP4) +#include + #include "MP4Muxer.h" #include "Common/config.h" @@ -18,6 +20,15 @@ using namespace toolkit; namespace mediakit { +static constexpr int kMaxMovVideoDimension = (std::numeric_limits::max)() >> 16; + +static bool isMovVideoDimensionSafe(int width, int height) { + // libmov 将有符号 int 类型的视频宽高左移 16 位写入 16.16 定点数字段,超出此范围会触发未定义行为。 + // libmov shifts signed int video dimensions left by 16 for a 16.16 fixed-point field; values outside this range cause undefined behavior. + return width >= 0 && height >= 0 && + width <= kMaxMovVideoDimension && height <= kMaxMovVideoDimension; +} + MP4Muxer::~MP4Muxer() { try { closeMP4(); @@ -182,7 +193,14 @@ bool MP4MuxerInterface::addTrack(const Track::Ptr &track) { if (track->getTrackType() == TrackVideo) { auto video_track = dynamic_pointer_cast(track); CHECK(video_track); - auto track_id = mp4_writer_add_video(_mov_writter.get(), mp4_object, video_track->getVideoWidth(), video_track->getVideoHeight(), extra_data, extra_size); + auto width = video_track->getVideoWidth(); + auto height = video_track->getVideoHeight(); + if (!isMovVideoDimensionSafe(width, height)) { + WarnL << "Unsafe MP4 video dimensions: " << width << "x" << height + << ", safe range for each dimension: [0, " << kMaxMovVideoDimension << "]"; + return false; + } + auto track_id = mp4_writer_add_video(_mov_writter.get(), mp4_object, width, height, extra_data, extra_size); if (track_id < 0) { WarnL << "mp4_writer_add_video failed: " << video_track->getCodecName(); return false;