mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2026-07-28 13:04:07 +08:00
修复mp4异常视频尺寸可能导致的未定义行为 (#4785)
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 轨道信息。
This commit is contained in:
@@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
#if defined(ENABLE_MP4)
|
#if defined(ENABLE_MP4)
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
#include "MP4Muxer.h"
|
#include "MP4Muxer.h"
|
||||||
#include "Common/config.h"
|
#include "Common/config.h"
|
||||||
|
|
||||||
@@ -18,6 +20,15 @@ using namespace toolkit;
|
|||||||
|
|
||||||
namespace mediakit {
|
namespace mediakit {
|
||||||
|
|
||||||
|
static constexpr int kMaxMovVideoDimension = (std::numeric_limits<int>::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() {
|
MP4Muxer::~MP4Muxer() {
|
||||||
try {
|
try {
|
||||||
closeMP4();
|
closeMP4();
|
||||||
@@ -182,7 +193,14 @@ bool MP4MuxerInterface::addTrack(const Track::Ptr &track) {
|
|||||||
if (track->getTrackType() == TrackVideo) {
|
if (track->getTrackType() == TrackVideo) {
|
||||||
auto video_track = dynamic_pointer_cast<VideoTrack>(track);
|
auto video_track = dynamic_pointer_cast<VideoTrack>(track);
|
||||||
CHECK(video_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) {
|
if (track_id < 0) {
|
||||||
WarnL << "mp4_writer_add_video failed: " << video_track->getCodecName();
|
WarnL << "mp4_writer_add_video failed: " << video_track->getCodecName();
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user