mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
HLS: Ignore empty NALU to avoid error. v6.0.65 (#3750)
For the DJI M30, there is a bug where empty NALU packets with a size of zero are causing issues with HLS streaming. This bug leads to random unpublish events due to the SRS disconnecting the connection for the HLS module when it fails to handle empty NALU packets. To address this bug, we have patched the system to ignore any empty NALU packets with a size of zero. Additionally, we have created a tool in the srs-bench to replay pcapng files captured by tcpdump or Wireshark. We have also added utest using mprotect and asan to detect any memory corruption. It is important to note that this bug has been fixed in versions 4.0.2716477f31004
and 5.0.170939f6b484b
. This patch specifically addresses the issue in SRS 6.0. Please be aware that there is another commit related to this bug that partially fixes the issue but still leaves a small problem for asan to detect memory corruption. This commit,577cd299e1
, only ignores empty NALU packets but still reads beyond the memory. --------- Co-authored-by: chundonglinlin <chundonglinlin@163.com>
This commit is contained in:
parent
e19efe0bcd
commit
73dd8af4c9
182 changed files with 46111 additions and 3914 deletions
|
@ -9,6 +9,6 @@
|
|||
|
||||
#define VERSION_MAJOR 4
|
||||
#define VERSION_MINOR 0
|
||||
#define VERSION_REVISION 270
|
||||
#define VERSION_REVISION 271
|
||||
|
||||
#endif
|
||||
|
|
|
@ -9,6 +9,6 @@
|
|||
|
||||
#define VERSION_MAJOR 5
|
||||
#define VERSION_MINOR 0
|
||||
#define VERSION_REVISION 169
|
||||
#define VERSION_REVISION 170
|
||||
|
||||
#endif
|
||||
|
|
|
@ -9,6 +9,6 @@
|
|||
|
||||
#define VERSION_MAJOR 6
|
||||
#define VERSION_MINOR 0
|
||||
#define VERSION_REVISION 64
|
||||
#define VERSION_REVISION 65
|
||||
|
||||
#endif
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#ifdef SRS_SRT
|
||||
#include <srs_app_srt_server.hpp>
|
||||
#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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include <srs_kernel_error.hpp>
|
||||
#include <srs_kernel_buffer.hpp>
|
||||
#include <srs_kernel_rtc_rtcp.hpp>
|
||||
#include <srs_app_gb28181.hpp>
|
||||
#include <srs_app_utility.hpp>
|
||||
|
||||
VOID TEST(KernelPSTest, PsPacketDecodeNormal)
|
||||
|
@ -483,3 +482,47 @@ VOID TEST(KernelRTMPExtTest, ExtRTMPTest)
|
|||
}
|
||||
}
|
||||
|
||||
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)));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue