Skip to content

Potential Unsoundness: OOB #533

@xizheyin

Description

@xizheyin

Thanks for your crate! My team is developing a static analyzer to check Safe Rust code that may trigger UBs. After downloading the repo from crates.io, we ran our checker and received warnings, leading us to construct cases that can trigger UB in safe code.

I found a unsound bug.

Repro case:

use solana_account_info::AccountInfo;
use solana_address::Address;

fn main() {
    // Construct AccountInfo via safe API with ordinary standalone allocations.
    // This does NOT satisfy the hidden runtime layout assumptions required by resize().
    let key = Address::new_from_array([1u8; 32]);
    let owner = Address::new_from_array([2u8; 32]);
    let mut lamports: u64 = 0;

    // A small Vec-backed slice. data.as_mut_ptr().offset(-8) is OOB for this allocation.
    let mut data = vec![0u8; 16];

    let ai = AccountInfo::new(
        &key,
        false,
        true,
        &mut lamports,
        data.as_mut_slice(),
        &owner,
        false,
    );

    // Triggers the unsafe write: *(data_ptr.offset(-8) as *mut u64) = new_len as u64;
    // Run with ASan to deterministically abort on the OOB write.
    let _ = ai.resize(32);

    // If it didn't crash, still exit 0; the intended reproduction is ASan abort.
    println!("done");
}

cargo.toml:

[dependencies]
semilattice-database-session = "0.48.1"
futures = "0.3"

MIRI outputs:

error: Undefined Behavior: in-bounds pointer arithmetic failed: attempting to offset pointer by -4 bytes, but got alloc178 which is at the beginning of the allocation
  --> /Users/yxz/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/solana-account-info-3.1.0/src/lib.rs:94:37
   |
94 |         let original_data_len_ptr = key_ptr.offset(-4) as *const u32;
   |                                     ^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
   |
   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
help: alloc178 was allocated here:
  --> src/main.rs:7:9
   |
 7 |     let key = Address::new_from_array([1u8; 32]);
   |         ^^^
   = note: stack backtrace:
           0: solana_account_info::AccountInfo::<'_>::original_data_len
               at /Users/yxz/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/solana-account-info-3.1.0/src/lib.rs:94:37: 94:55
           1: solana_account_info::AccountInfo::<'_>::resize
               at /Users/yxz/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/solana-account-info-3.1.0/src/lib.rs:160:42: 160:66
           2: main
               at src/main.rs:26:13: 26:26

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

error: aborting due to 1 previous error

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions