Null pointer dereference caused segmentation fault
version
./bin/gcc/MP4Box -version
MP4Box - GPAC version 2.1-DEV-rev65-g718843df4-master
(c) 2000-2022 Telecom Paris distributed under LGPL v2.1+ - http://gpac.io
Please cite our work in your research:
GPAC Filters: https://doi.org/10.1145/3339825.3394929
GPAC: https://doi.org/10.1145/1291233.1291452
GPAC Configuration: --enable-debug
Features: GPAC_CONFIG_LINUX GPAC_64_BITS GPAC_HAS_IPV6 GPAC_HAS_SSL GPAC_HAS_SOCK_UN GPAC_MINIMAL_ODF GPAC_HAS_QJS GPAC_HAS_PNG GPAC_HAS_LINUX_DVB GPAC_DISABLE_3D
Command: ./bin/gcc/MP4Box -xmt poc
Result: Segmentation fault
bt:
Starting program: /home/ubuntu/fuzz/gpac/bin/gcc/MP4Box -xmt ./poc
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[iso file] Unknown box type url@ in parent dref
[iso file] Unknown box type mp1Dv in parent stsd
[iso file] extra box maxr found in hinf, deleting
[iso file] Unknown box type t0E18 in parent trak
[iso file] extra box maxr found in hinf, deleting
[iso file] Unknown box type 80rak in parent moov
[iso file] Incomplete box mdat - start 11495 size 803701
[iso file] Incomplete file while reading for dump - aborting parsing
[iso file] Unknown box type url@ in parent dref
[iso file] Unknown box type mp1Dv in parent stsd
[iso file] extra box maxr found in hinf, deleting
[iso file] Unknown box type t0E18 in parent trak
[iso file] extra box maxr found in hinf, deleting
[iso file] Unknown box type 80rak in parent moov
[iso file] Incomplete box mdat - start 11495 size 803701
[iso file] Incomplete file while reading for dump - aborting parsing
MPEG-4 BIFS Scene Parsing
[ODF] Reading bifs config: shift in sizes (not supported)
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7240bc7 in BS_ReadByte (bs=0x5555557d29b0) at utils/bitstream.c:362
362 res = bs->original[bs->position++];
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā[ REGISTERS ]āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
RAX 0x0
RBX 0x0
RCX 0x1
RDX 0x5555557d29b0 āā 0x0
RDI 0x5555557d29b0 āā 0x0
RSI 0x0
R8 0x0
R9 0x0
R10 0x9
R11 0x7ffff72aa158 (gf_node_get_graph) āā push rbp
R12 0x5555557d4890 āāø 0x5555557d4460 āā 0x0
R13 0x5555557d4460 āā 0x0
R14 0x1
R15 0x0
RBP 0x7fffffff8730 āāø 0x7fffffff8760 āāø 0x7fffffff8790 āāø 0x7fffffff87e0 āāø 0x7fffffff8850 āā ...
RSP 0x7fffffff8700 āā 0x0
RIP 0x7ffff7240bc7 (BS_ReadByte+166) āā movzx eax, byte ptr [rax]
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā[ DISASM ]āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
āŗ 0x7ffff7240bc7 <BS_ReadByte+166> movzx eax, byte ptr [rax]
0x7ffff7240bca <BS_ReadByte+169> mov byte ptr [rbp - 0x13], al
0x7ffff7240bcd <BS_ReadByte+172> mov rax, qword ptr [rbp - 0x28]
0x7ffff7240bd1 <BS_ReadByte+176> mov eax, dword ptr [rax + 0x50]
0x7ffff7240bd4 <BS_ReadByte+179> test eax, eax
0x7ffff7240bd6 <BS_ReadByte+181> je BS_ReadByte+336 <BS_ReadByte+336>
ā
0x7ffff7240c71 <BS_ReadByte+336> movzx eax, byte ptr [rbp - 0x13]
0x7ffff7240c75 <BS_ReadByte+340> jmp BS_ReadByte+896 <BS_ReadByte+896>
ā
0x7ffff7240ea1 <BS_ReadByte+896> mov rcx, qword ptr [rbp - 8]
0x7ffff7240ea5 <BS_ReadByte+900> xor rcx, qword ptr fs:[0x28]
0x7ffff7240eae <BS_ReadByte+909> je BS_ReadByte+916 <BS_ReadByte+916>
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā[ SOURCE (CODE) ]āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
In file: /home/ubuntu/fuzz/gpac/src/utils/bitstream.c
357 if (bs->position >= bs->size) {
358 if (bs->EndOfStream) bs->EndOfStream(bs->par);
359 if (!bs->overflow_state) bs->overflow_state = 1;
360 return 0;
361 }
āŗ 362 res = bs->original[bs->position++];
363
364 if (bs->remove_emul_prevention_byte) {
365 if ((bs->nb_zeros==2) && (res==0x03) && (bs->position<bs->size) && (bs->original[bs->position]<0x04)) {
366 bs->nb_zeros = 0;
367 res = bs->original[bs->position++];
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā[ STACK ]āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
00:0000ā rsp 0x7fffffff8700 āā 0x0
01:0008ā 0x7fffffff8708 āāø 0x5555557d29b0 āā 0x0
02:0010ā 0x7fffffff8710 āā 0x0
... ā 2 skipped
05:0028ā 0x7fffffff8728 āā 0xe537f499f4c1e900
06:0030ā rbp 0x7fffffff8730 āāø 0x7fffffff8760 āāø 0x7fffffff8790 āāø 0x7fffffff87e0 āāø 0x7fffffff8850 āā ...
07:0038ā 0x7fffffff8738 āāø 0x7ffff7240edb (gf_bs_read_bit+36) āā movzx edx, al
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā[ BACKTRACE ]āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
āŗ f 0 0x7ffff7240bc7 BS_ReadByte+166
f 1 0x7ffff7240edb gf_bs_read_bit+36
f 2 0x7ffff7240f67 gf_bs_read_int+64
f 3 0x7ffff73d9f47 BM_ParseCommand+87
f 4 0x7ffff73da181 gf_bifs_flush_command_list+296
f 5 0x7ffff73da561 gf_bifs_decode_command_list+339
f 6 0x7ffff75c1189 gf_sm_load_run_isom+1987
f 7 0x7ffff75a3123 gf_sm_load_run+42
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
pwndbg> where
#0 0x00007ffff7240bc7 in BS_ReadByte (bs=0x5555557d29b0) at utils/bitstream.c:362
#1 0x00007ffff7240edb in gf_bs_read_bit (bs=0x5555557d29b0) at utils/bitstream.c:428
#2 0x00007ffff7240f67 in gf_bs_read_int (bs=0x5555557d29b0, nBits=1) at utils/bitstream.c:461
#3 0x00007ffff73d9f47 in BM_ParseCommand (codec=0x5555557def00, bs=0x5555557d29b0, com_list=0x5555557f3960) at bifs/memory_decoder.c:898
#4 0x00007ffff73da181 in gf_bifs_flush_command_list (codec=0x5555557def00) at bifs/memory_decoder.c:956
#5 0x00007ffff73da561 in gf_bifs_decode_command_list (codec=0x5555557def00, ESID=8, data=0x5555557df340 '\314' <repeats 102 times>, "Ģ\224\224\224\224\224\224\224", <incomplete sequence \341>, data_length=8208, com_list=0x5555557df2c0) at bifs/memory_decoder.c:1036
#6 0x00007ffff75c1189 in gf_sm_load_run_isom (load=0x7fffffff89c0) at scene_manager/loader_isom.c:303
#7 0x00007ffff75a3123 in gf_sm_load_run (load=0x7fffffff89c0) at scene_manager/scene_manager.c:719
#8 0x0000555555582280 in dump_isom_scene ()
#9 0x00005555555789de in mp4boxMain ()
#10 0x00007ffff6dcdbf7 in __libc_start_main (main=0x55555556c140 <main>, argc=3, argv=0x7fffffffe458, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe448) at ../csu/libc-start.c:310
#11 0x000055555556c17a in _start ()
After Debugging,I found
src/bifs/memory_decoder.c:953
GF_Err gf_bifs_flush_command_list(GF_BifsDecoder *codec)
if (cbi->cb->bufferSize) {
bs = gf_bs_new((char*)cbi->cb->buffer, cbi->cb->bufferSize, GF_BITSTREAM_READ);
gf_bs_set_eos_callback(bs, BM_EndOfStream, codec);
e = BM_ParseCommand(codec, bs, cbi->cb->commandList);
gf_bs_del(bs);
}
after called gf_bs_new
, sets bs->origin to null
then using BM_ParseCommand
function
src/bifs/memory_decoder.c:887
GF_Err BM_ParseCommand(GF_BifsDecoder *codec, GF_BitStream *bs, GF_List *com_list)
{
u8 go, type;
GF_Err e;
go = 1;
e = GF_OK;
GF_SceneGraph *cur_graph = codec->current_graph;
GF_Proto *cur_proto = codec->pCurrentProto;
codec->LastError = GF_OK;
while (go) {
type = gf_bs_read_int(bs, 2);
switch (type) {
case 0:
e = BM_ParseInsert(codec, bs, com_list);
break;
case 1:
e = BM_ParseDelete(codec, bs, com_list);
break;
case 2:
e = BM_ParseReplace(codec, bs, com_list);
break;
case 3:
e = BM_SceneReplace(codec, bs, com_list);
break;
}
if (e) break;
go = gf_bs_read_int(bs, 1);
}
while (gf_list_count(codec->QPs)) {
gf_bifs_dec_qp_remove(codec, GF_TRUE);
}
codec->current_graph = cur_graph;
codec->pCurrentProto = cur_proto;
return e;
}
in type = gf_bs_read_int(bs, 2);
src/utils/bitstream.c
GF_EXPORT
u32 gf_bs_read_int(GF_BitStream *bs, u32 nBits)
{
u32 ret;
bs->total_bits_read+= nBits;
#ifndef NO_OPTS
if (nBits + bs->nbBits <= 8) {
bs->nbBits += nBits;
ret = (bs->current >> (8 - bs->nbBits) ) & bits_mask[nBits];
return ret;
}
#endif
ret = 0;
while (nBits-- > 0) {
ret <<= 1;
ret |= gf_bs_read_bit(bs);
}
return ret;
}
In gf_bs_read_bit
using BS_ReadByte
function
GF_EXPORT
u8 gf_bs_read_bit(GF_BitStream *bs)
{
if (bs->nbBits == 8) {
bs->current = BS_ReadByte(bs);
bs->nbBits = 0;
}
#ifdef NO_OPTS
{
s32 ret;
bs->current <<= 1;
bs->nbBits++;
ret = (bs->current & 0x100) >> 8;
return (u8) ret;
}
#else
return (u8) (bs->current & bit_mask[bs->nbBits++]) ? 1 : 0;
#endif
}
In src/utils/bitstream.c BS_ReadByte
/*fetch a new byte in the bitstream switch between packets*/
static u8 BS_ReadByte(GF_BitStream *bs)
{
Bool is_eos;
if (bs->bsmode == GF_BITSTREAM_READ) {
u8 res;
if (bs->position >= bs->size) {
if (bs->EndOfStream) bs->EndOfStream(bs->par);
if (!bs->overflow_state) bs->overflow_state = 1;
return 0;
}
res = bs->original[bs->position++];
if (bs->remove_emul_prevention_byte) {
if ((bs->nb_zeros==2) && (res==0x03) && (bs->position<bs->size) && (bs->original[bs->position]<0x04)) {
bs->nb_zeros = 0;
res = bs->original[bs->position++];
}
if (!res) bs->nb_zeros++;
else bs->nb_zeros = 0;
}
return res;
}
if (bs->cache_write)
bs_flush_write_cache(bs);
is_eos = gf_feof(bs->stream);
/*we are in FILE mode, test for end of file*/
if (!is_eos || bs->cache_read) {
u8 res;
Bool loc_eos=GF_FALSE;
assert(bs->position<=bs->size);
bs->position++;
res = gf_bs_load_byte(bs, &loc_eos);
if (loc_eos) goto bs_eof;
if (bs->remove_emul_prevention_byte) {
if ((bs->nb_zeros==2) && (res==0x03) && (bs->position<bs->size)) {
u8 next = gf_bs_load_byte(bs, &loc_eos);
if (next < 0x04) {
bs->nb_zeros = 0;
res = next;
bs->position++;
} else {
gf_bs_seek(bs, bs->position);
}
}
if (!res) bs->nb_zeros++;
else bs->nb_zeros = 0;
}
return res;
}
bs_eof:
if (bs->EndOfStream) {
bs->EndOfStream(bs->par);
if (!bs->overflow_state) bs->overflow_state = 1;
} else {
GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[BS] Attempt to overread bitstream\n"));
}
assert(bs->position <= 1+bs->size);
return 0;
}
res = bs->original[bs->position++];
Here using bs->original which is a null pointer, dereference this null pointer caused segmentation fault
itās very similar to https://huntr.dev/bounties/851942a4-1d64-4553-8fdc-9fccd167864b/