let loader = BuiltinProgram::new_loader(
Config::default(),
FunctionRegistry::default(),
);
let mut executable = Executable::<TestContextObject>::from_text_bytes(
&[0x7b, 0x21, 0x00, 0x80, 0, 0, 0, 0],
std::sync::Arc::new(loader),
solana_rbpf::program::SBPFVersion::V2,
FunctionRegistry::default(),
).unwrap();
let analysis = Analysis::from_executable(&executable).unwrap();
let mut reasm = Vec::new();
analysis.disassemble(&mut reasm).unwrap();
Running it in debug mode would encounter:
attempt to negate with overflow
thread 'test_store_negate' panicked at 'attempt to negate with overflow', src/disassembler.rs:48:27
stack backtrace:
0: rust_begin_unwind
at /rustc/*/library/std/src/panicking.rs:593:5
1: core::panicking::panic_fmt
at /rustc/*/library/core/src/panicking.rs:67:14
2: core::panicking::panic
at /rustc/*/library/core/src/panicking.rs:117:5
3: solana_rbpf::disassembler::signed_off_str
at ./src/disassembler.rs:48:27
4: solana_rbpf::disassembler::st_reg_str
at ./src/disassembler.rs:82:9
5: solana_rbpf::disassembler::disassemble_instruction
at ./src/disassembler.rs:142:58
In release mode, the disassembler result would be stxdw [r1-0x8000], r2, which doesn't necessarily pose the wrong result.
However, to enhance the robustness of the disassembler, the negate logic of i16 could be restructured in signed_off_str function.
When overflow-check is enabled, the disassembler would panic in
signed_off_str
when it tries to negate the0x8000i16
value in https://github.com/solana-labs/rbpf/blob/b503a1867a9cfa13f93b4d99679a17fe219831de/src/disassembler.rs#L46-L52The text bytes PoC to trigger it:
The test code to reproduce:
Running it in debug mode would encounter:
In release mode, the disassembler result would be
stxdw [r1-0x8000], r2
, which doesn't necessarily pose the wrong result.However, to enhance the robustness of the disassembler, the negate logic of
i16
could be restructured insigned_off_str
function.