Skip to content
This repository has been archived by the owner on Jun 16, 2020. It is now read-only.

[panic] Index out of bounds in operators_validator::OperatorValidator::check_select #126

Closed
pventuzelo opened this issue Aug 26, 2019 · 0 comments · Fixed by #127
Closed

Comments

@pventuzelo
Copy link

An index out of bound panic occurs after subtraction overflow in wasmparser::operators_validator::OperatorValidator::check_select method.

This issue have been found during fuzzing of the wasmer project.

Describe the bugs

Subtraction between func_state.stack_types.len() and last_block.stack_starts_at values generate an overflow value. The value func_state.stack_types.len() substrates with an hardcoded value is then used as an index array leading the program to panic with an index out of bound error.

https://github.com/yurydelendik/wasmparser.rs/blob/b56f91d251055eb7787e7e5c42926a61635ca00a/src/operators_validator.rs#L615-L636

Expected behavior

Proper check of the subtraction result should be done, ensuring that func_state.stack_types.len() is valid and return an error otherwise.

Status of my environment

wasmparser version: commit b56f91d
wasmparser version: 0.37.0

Steps to reproduce

Download
panic_wasmparser_index_oob_check_select.zip

Basic testing program:

extern crate wasmparser;

use std::env;
use std::fs;
use std::str;

use std::io;
use std::io::prelude::*;
use std::fs::File;

use wasmparser::WasmDecoder;
use wasmparser::Parser;
use wasmparser::ParserState;

fn get_name(bytes: &[u8]) -> &str {
  str::from_utf8(bytes).ok().unwrap()
}

fn main()-> Result<(), String> {

  let args: Vec<String> = env::args().collect();
  let filename = &args[1];

let mut f = File::open(filename).map_err(|e| format!("err: {}", e))?;
      let mut wasm= Vec::new();
      f.read_to_end(&mut wasm);

     use wasmparser::WasmDecoder;
    let config = wasmparser::ValidatingParserConfig {
        operator_config: wasmparser::OperatorValidatorConfig {
            enable_simd: false,
            enable_bulk_memory: false,
            enable_multi_value: false,
            enable_reference_types: false,
            enable_threads: false,
        },
        //mutable_global_imports: false,
    };
    let mut parser = wasmparser::ValidatingParser::new(&wasm, Some(config));
    let res =  loop {
        let state = parser.read();
        match *state {
            wasmparser::ParserState::EndWasm => break Ok(()),
            wasmparser::ParserState::Error(e) => break Err(format!("{}", e)),
            _ => {}
        }
    };
    println!("res: {:?}", res);
    Ok(())
}

Build and run:

$ cargo build --release
$ ./target/release/parse panic_wasmparser_index_oob_check_select.wasm
thread 'main' panicked at 'index out of bounds: the len is 0 but the index is 18446744073709551613', /rustc/ad7c55e1fc55d9af4787b285cec1c64e3480ae84/src/libcore/slice/mod.rs:2704:10

$ cargo build --debug
$ ./target/debug/parse panic_wasmparser_index_oob_check_select.wasm
thread 'main' panicked at 'attempt to subtract with overflow', /home/scop/Documents/webassembly/wasmparser.rs/src/operators_validator.rs:616:19

Detailed behavior (debug build)

$ RUST_BACKTRACE=1 ./target/debug/parse panic_wasmparser_index_oob_check_select.wasm
thread 'main' panicked at 'attempt to subtract with overflow', /home/scop/Documents/webassembly/wasmparser.rs/src/operators_validator.rs:616:19
stack backtrace:
   0: backtrace::backtrace::libunwind::trace
             at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.34/src/backtrace/libunwind.rs:88
   1: backtrace::backtrace::trace_unsynchronized
             at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.34/src/backtrace/mod.rs:66
   2: std::sys_common::backtrace::_print
             at src/libstd/sys_common/backtrace.rs:47
   3: std::sys_common::backtrace::print
             at src/libstd/sys_common/backtrace.rs:36
   4: std::panicking::default_hook::{{closure}}
             at src/libstd/panicking.rs:200
   5: std::panicking::default_hook
             at src/libstd/panicking.rs:214
   6: std::panicking::rust_panic_with_hook
             at src/libstd/panicking.rs:477
   7: std::panicking::continue_panic_fmt
             at src/libstd/panicking.rs:384
   8: rust_begin_unwind
             at src/libstd/panicking.rs:311
   9: core::panicking::panic_fmt
             at src/libcore/panicking.rs:85
  10: core::panicking::panic
             at src/libcore/panicking.rs:49
  11: wasmparser::operators_validator::OperatorValidator::check_select
             at /home/scop/Documents/webassembly/wasmparser.rs/src/operators_validator.rs:616
  12: wasmparser::operators_validator::OperatorValidator::process_operator
             at /home/scop/Documents/webassembly/wasmparser.rs/src/operators_validator.rs:750
  13: wasmparser::validator::ValidatingParser::process_state
             at /home/scop/Documents/webassembly/wasmparser.rs/src/validator.rs:551
  14: <wasmparser::validator::ValidatingParser as wasmparser::parser::WasmDecoder>::read
             at /home/scop/Documents/webassembly/wasmparser.rs/src/validator.rs:641
  15: parse::main
             at src/main.rs:41
  16: std::rt::lang_start::{{closure}}
             at /rustc/ad7c55e1fc55d9af4787b285cec1c64e3480ae84/src/libstd/rt.rs:64
  17: std::rt::lang_start_internal::{{closure}}
             at src/libstd/rt.rs:49
  18: std::panicking::try::do_call
             at src/libstd/panicking.rs:296
  19: __rust_maybe_catch_panic
             at src/libpanic_unwind/lib.rs:80
  20: std::panicking::try
             at src/libstd/panicking.rs:275
  21: std::panic::catch_unwind
             at src/libstd/panic.rs:394
  22: std::rt::lang_start_internal
             at src/libstd/rt.rs:48
  23: std::rt::lang_start
             at /rustc/ad7c55e1fc55d9af4787b285cec1c64e3480ae84/src/libstd/rt.rs:64
  24: main
  25: __libc_start_main
  26: _start
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

Detailed behavior (release build)

$ RUST_BACKTRACE=1 ./target/release/parse panic_wasmparser_index_oob_check_select.wasm
thread 'main' panicked at 'index out of bounds: the len is 0 but the index is 18446744073709551613', /rustc/ad7c55e1fc55d9af4787b285cec1c64e3480ae84/src/libcore/slice/mod.rs:2704:10
stack backtrace:
   0: backtrace::backtrace::libunwind::trace
             at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.34/src/backtrace/libunwind.rs:88
   1: backtrace::backtrace::trace_unsynchronized
             at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.34/src/backtrace/mod.rs:66
   2: std::sys_common::backtrace::_print
             at src/libstd/sys_common/backtrace.rs:47
   3: std::sys_common::backtrace::print
             at src/libstd/sys_common/backtrace.rs:36
   4: std::panicking::default_hook::{{closure}}
             at src/libstd/panicking.rs:200
   5: std::panicking::default_hook
             at src/libstd/panicking.rs:214
   6: std::panicking::rust_panic_with_hook
             at src/libstd/panicking.rs:477
   7: std::panicking::continue_panic_fmt
             at src/libstd/panicking.rs:384
   8: rust_begin_unwind
             at src/libstd/panicking.rs:311
   9: core::panicking::panic_fmt
             at src/libcore/panicking.rs:85
  10: core::panicking::panic_bounds_check
             at src/libcore/panicking.rs:61
  11: wasmparser::operators_validator::OperatorValidator::process_operator
  12: <wasmparser::validator::ValidatingParser as wasmparser::parser::WasmDecoder>::read
  13: parse::main
  14: std::rt::lang_start::{{closure}}
  15: std::rt::lang_start_internal::{{closure}}
             at src/libstd/rt.rs:49
  16: std::panicking::try::do_call
             at src/libstd/panicking.rs:296
  17: __rust_maybe_catch_panic
             at src/libpanic_unwind/lib.rs:80
  18: std::panicking::try
             at src/libstd/panicking.rs:275
  19: std::panic::catch_unwind
             at src/libstd/panic.rs:394
  20: std::rt::lang_start_internal
             at src/libstd/rt.rs:48
  21: main
  22: __libc_start_main
  23: _start
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant