diff --git a/trunk/configure b/trunk/configure index 5ec64fde8..ced5e6354 100755 --- a/trunk/configure +++ b/trunk/configure @@ -435,7 +435,7 @@ if [[ $SRS_UTEST == YES ]]; then MODULE_FILES=("srs_utest" "srs_utest_amf0" "srs_utest_kernel" "srs_utest_core" "srs_utest_config" "srs_utest_rtmp" "srs_utest_http" "srs_utest_avc" "srs_utest_reload" "srs_utest_mp4" "srs_utest_service" "srs_utest_app" "srs_utest_rtc" - "srs_utest_protocol" "srs_utest_protocol2") + "srs_utest_protocol" "srs_utest_protocol2" "srs_utest_kernel2") if [[ $SRS_SRT == YES ]]; then MODULE_FILES+=("srs_utest_srt") fi diff --git a/trunk/doc/CHANGELOG.md b/trunk/doc/CHANGELOG.md index a6bab0507..64735366d 100644 --- a/trunk/doc/CHANGELOG.md +++ b/trunk/doc/CHANGELOG.md @@ -7,6 +7,7 @@ The changelog for SRS. ## SRS 5.0 Changelog +* v5.0, 2023-08-02, HLS: Ignore empty NALU to avoid error. v5.0.170 * v5.0, 2023-07-26, Merge [#3699](https://github.com/ossrs/srs/pull/3699): Bugfix: Eliminate the redundant declaration of the _srs_rtc_manager variable.. v5.0.168 (#3699) * v5.0, 2023-07-21, Merge [#3695](https://github.com/ossrs/srs/pull/3695): API: Fix HTTPS callback issue using SNI in TLS client handshake. v5.0.168 (#3695) * v5.0, 2023-07-18, Merge [#3515](https://github.com/ossrs/srs/pull/3515): WebRTC: Support config the bitrate of transcoding AAC to Opus. v5.0.167 (#3515) diff --git a/trunk/src/core/srs_core_version4.hpp b/trunk/src/core/srs_core_version4.hpp index 21f2c75c0..fb041680a 100644 --- a/trunk/src/core/srs_core_version4.hpp +++ b/trunk/src/core/srs_core_version4.hpp @@ -9,6 +9,6 @@ #define VERSION_MAJOR 4 #define VERSION_MINOR 0 -#define VERSION_REVISION 270 +#define VERSION_REVISION 271 #endif diff --git a/trunk/src/core/srs_core_version5.hpp b/trunk/src/core/srs_core_version5.hpp index 8e8863f5a..2e3cd7915 100644 --- a/trunk/src/core/srs_core_version5.hpp +++ b/trunk/src/core/srs_core_version5.hpp @@ -9,6 +9,6 @@ #define VERSION_MAJOR 5 #define VERSION_MINOR 0 -#define VERSION_REVISION 169 +#define VERSION_REVISION 170 #endif diff --git a/trunk/src/kernel/srs_kernel_codec.cpp b/trunk/src/kernel/srs_kernel_codec.cpp index 727a14037..5ed65a6d4 100644 --- a/trunk/src/kernel/srs_kernel_codec.cpp +++ b/trunk/src/kernel/srs_kernel_codec.cpp @@ -599,6 +599,8 @@ srs_error_t SrsVideoFrame::add_sample(char* bytes, int size) if ((err = SrsFrame::add_sample(bytes, size)) != srs_success) { return srs_error_wrap(err, "add frame"); } + + if (!bytes || size <= 0) return err; // for video, parse the nalu type, set the IDR flag. SrsAvcNaluType nal_unit_type = (SrsAvcNaluType)(bytes[0] & 0x1f); diff --git a/trunk/src/utest/srs_utest.cpp b/trunk/src/utest/srs_utest.cpp index 24268b534..800d250e9 100644 --- a/trunk/src/utest/srs_utest.cpp +++ b/trunk/src/utest/srs_utest.cpp @@ -17,6 +17,9 @@ #include using namespace std; +#include +#include + #ifdef SRS_SRT #include #endif @@ -208,3 +211,39 @@ VOID TEST(SampleTest, ContextTest) cache[0] = cid; } +MockProtectedBuffer::MockProtectedBuffer() : size_(0), data_(NULL), raw_memory_(NULL) +{ +} + +MockProtectedBuffer::~MockProtectedBuffer() +{ + if (size_ && raw_memory_) { + long page_size = sysconf(_SC_PAGESIZE); + munmap(raw_memory_, page_size * 2); + } +} + +int MockProtectedBuffer::alloc(int size) +{ + srs_assert(!raw_memory_); + + long page_size = sysconf(_SC_PAGESIZE); + if (size >= page_size) return -1; + + char* data = (char*)mmap(NULL, page_size * 2, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + if (data == MAP_FAILED) { + return -1; + } + + size_ = size; + raw_memory_ = data; + data_ = data + page_size - size; + + int r0 = mprotect(data + page_size, page_size, PROT_NONE); + if (r0 < 0) { + return r0; + } + + return 0; +} + diff --git a/trunk/src/utest/srs_utest.hpp b/trunk/src/utest/srs_utest.hpp index 46de4af08..5a2a2fa65 100644 --- a/trunk/src/utest/srs_utest.hpp +++ b/trunk/src/utest/srs_utest.hpp @@ -95,5 +95,32 @@ public: virtual ~MockEmptyLog(); }; +// To test the memory corruption, we protect the memory by mprotect. +// MockProtectedBuffer buffer; +// if (buffer.alloc(8)) { EXPECT_TRUE(false); return; } +// Crash when write beyond the data: +// buffer.data_[0] = 0; // OK +// buffer.data_[7] = 0; // OK +// buffer.data_[8] = 0; // Crash +// Crash when read beyond the data: +// char v = buffer.data_[0]; // OK +// char v = buffer.data_[7]; // OK +// char v = buffer.data_[8]; // Crash +// @remark The size of memory to allocate, should smaller than page size, generally 4096 bytes. +class MockProtectedBuffer +{ +private: + char* raw_memory_; +public: + int size_; + // Should use this as data. + char* data_; +public: + MockProtectedBuffer(); + virtual ~MockProtectedBuffer(); + // Return 0 for success. + int alloc(int size); +}; + #endif diff --git a/trunk/src/utest/srs_utest_kernel2.cpp b/trunk/src/utest/srs_utest_kernel2.cpp index 44f617f1d..3600c02bc 100644 --- a/trunk/src/utest/srs_utest_kernel2.cpp +++ b/trunk/src/utest/srs_utest_kernel2.cpp @@ -411,3 +411,47 @@ VOID TEST(KernelFileWriterTest, RealfileTest) EXPECT_STREQ("HelloWorld", str.substr(20).c_str()); } +VOID TEST(KernelCodecTest, VideoFormatSepcialMProtect_DJI_M30) +{ + srs_error_t err; + + SrsFormat f; + HELPER_EXPECT_SUCCESS(f.initialize()); + + // Frame 80442, the sequence header, wireshark filter: + // rtmpt && rtmpt.video.type==1 && rtmpt.video.format==7 + HELPER_EXPECT_SUCCESS(f.on_video(0, (char*)"" + "\x17\x00\x00\x00\x00\x01\x64\x00\x28\xff\xe1\x00\x12\x67\x64\x00" \ + "\x28\xac\xb4\x03\xc0\x11\x34\xa4\x14\x18\x18\x1b\x42\x84\xd4\x01" \ + "\x00\x05\x68\xee\x06\xf2\xc0", 39)); + + MockProtectedBuffer buffer; + if (buffer.alloc(9)) { + EXPECT_TRUE(false) << "mmap failed, errno=" << errno; + return; + } + + // Frame 82749 + memcpy(buffer.data_, "\x27\x01\x00\x00\x00\x00\x00\x00\x00", buffer.size_); + HELPER_EXPECT_SUCCESS(f.on_video(0, buffer.data_, buffer.size_)); +} + +VOID TEST(KernelCodecTest, VideoFormatSepcialAsan_DJI_M30) +{ + srs_error_t err; + + SrsFormat f; + HELPER_EXPECT_SUCCESS(f.initialize()); + + // Frame 80442, the sequence header, wireshark filter: + // rtmpt && rtmpt.video.type==1 && rtmpt.video.format==7 + HELPER_EXPECT_SUCCESS(f.on_video(0, (char*)"" + "\x17\x00\x00\x00\x00\x01\x64\x00\x28\xff\xe1\x00\x12\x67\x64\x00" \ + "\x28\xac\xb4\x03\xc0\x11\x34\xa4\x14\x18\x18\x1b\x42\x84\xd4\x01" \ + "\x00\x05\x68\xee\x06\xf2\xc0", 39)); + + // Frame 82749 + char data[9]; + memcpy(data, "\x27\x01\x00\x00\x00\x00\x00\x00\x00", sizeof(data)); + HELPER_EXPECT_SUCCESS(f.on_video(0, data, sizeof(data))); +}