Skip to content

Unsoundness in hassium-core #2598

@xizheyin

Description

@xizheyin

The following safe code will also trigger UB. This crate appears to have been downloaded frequently recently. Since the original repository is set to private, here cc @patchedsoul.

use hassium_core::fetch::{FetchEngine, FetchProcessReader, FetchStatus};

struct DummyEngine;

impl FetchEngine for DummyEngine {
    fn fetch(&mut self, _path: &str) -> Result<Box<dyn FetchProcessReader>, FetchStatus> {
        Err(FetchStatus::Empty)
    }
}

struct FakeReader;

impl FetchProcessReader for FakeReader {
    fn status(&self) -> FetchStatus {
        FetchStatus::Done
    }

    fn read(&self) -> Option<Vec<u8>> {
        None
    }

    fn box_clone(&self) -> Box<dyn FetchProcessReader> {
        Box::new(FakeReader)
    }
}

fn main() {
    // Safe API repro: cancel assumes the boxed reader is a FetchProcess,
    // but we can pass any FetchProcessReader implementation.
    let mut engine = DummyEngine;
    let reader: Box<dyn FetchProcessReader> = Box::new(FakeReader);
    engine.cancel(reader); // type confusion -> UB
    println!("ok");
}

miri outputs:

error: Undefined Behavior: pointer not dereferenceable: pointer must be dereferenceable for 24 bytes, but got 0x1[noalloc] which is a dangling pointer (it has no provenance)
   --> /Users/yxz/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/hassium-core-0.1.3/src/fetch/mod.rs:152:13
    |
152 |             (*ptr).cancel(FetchCancelReason::User);
    |             ^^^^^^ 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
    = note: stack backtrace:
            0: <DummyEngine as hassium_core::fetch::FetchEngine>::cancel
                at /Users/yxz/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/hassium-core-0.1.3/src/fetch/mod.rs:152:13: 152:19
            1: main
                at src/main.rs:32:5: 32: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