-
Notifications
You must be signed in to change notification settings - Fork 251
Closed
Labels
bugSomething isn't workingSomething isn't workingcriticalRequires urgent fixingRequires urgent fixing
Description
To Reproduce
Environment
- OS: Ubuntu 22.04 LTS
- Compiler: gcc version 11.4.0
- version: latest commit 5eae178
poc: poc
Steps to reproduce the behavior:
CFLAGS="-g -O0" CXXFLAGS="-g -O0" cmake ..
make
run valgrind ./furnace -console -vgmout out.vgm $POC
Expected behavior
user@c3ae4d510abb:$ valgrind ./furnace -console -vgmout out.vgm $POC
==2476279== Invalid read of size 2
==2476279== at 0x7C9C3E: DivPlatformYM2610::dispatch(DivCommand) (ym2610.cpp:1434)
==2476279== by 0x6CE1DB: DivEngine::dispatchCmd(DivCommand) (playback.cpp:436)
==2476279== by 0x6CE6D4: DivEngine::perSystemPostEffect(int, unsigned char, unsigned char) (playback.cpp:472)
==2476279== by 0x6D60A0: DivEngine::processRow(int, bool) (playback.cpp:1296)
==2476279== by 0x6D6BE8: DivEngine::nextRow() (playback.cpp:1399)
==2476279== by 0x6D887B: DivEngine::nextTick(bool, bool) (playback.cpp:1658)
==2476279== by 0x734D27: DivEngine::saveVGM(bool*, bool, int, bool, bool, int) (vgmOps.cpp:2604)
==2476279== by 0x9362C9: main (main.cpp:865)
==2476279== Address 0x6802ac8 is 0 bytes after a block of size 141,960 alloc'd
==2476279== at 0x4849013: operator new(unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==2476279== by 0x66760D: DivDispatchContainer::init(DivSystem, DivEngine*, int, double, DivConfig const&, bool) (dispatchContainer.cpp:362)
==2476279== by 0x693CBD: DivEngine::initDispatch(bool) (engine.cpp:3689)
==2476279== by 0x6971D4: DivEngine::init() (engine.cpp:4082)
==2476279== by 0x935F19: main (main.cpp:821)
==2476279==
Here is some debug info in gdb:
Thread 1 "furnace" hit Breakpoint 1, DivPlatformYM2610::dispatch (this=0x55555743ed10, c=...) at ym2610.cpp:1434
1434 unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
(gdb) p c.chan
$1 = 12 '\f'
(gdb) p chanOffs
$2 = {1, 2, 257, 258}
(gdb) p psgChanOffs
$3 = 4
(gdb) p chanOffs[12]
$4 = 33
It seems that c.chan
is not checked against psgChanOffs
.
furnace/src/engine/platform/ym2610.cpp
Lines 1429 to 1444 in 5eae178
case DIV_CMD_FM_RS: { | |
if (c.value<0) { | |
for (int i=0; i<4; i++) { | |
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i]; | |
op.rs=c.value2&3; | |
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i]; | |
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6)); | |
} | |
} else if (c.value<4) { | |
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]]; | |
op.rs=c.value2&3; | |
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]]; | |
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6)); | |
} | |
break; | |
} |
A similar overflow issue also occurs at line 1520. Here is the poc.
furnace/src/engine/platform/ym2610.cpp
Lines 1509 to 1524 in 5eae178
case DIV_CMD_FM_D2R: { | |
if (c.value<0) { | |
for (int i=0; i<4; i++) { | |
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i]; | |
op.d2r=c.value2&31; | |
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i]; | |
rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31); | |
} | |
} else if (c.value<4) { | |
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]]; | |
op.d2r=c.value2&31; | |
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]]; | |
rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31); | |
} | |
break; | |
} |
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't workingcriticalRequires urgent fixingRequires urgent fixing