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)));
+}