Skip to content

Unsoundness: ListVector is missing a lifetime specifier, allowing use-after-free #673

@t1mlange

Description

@t1mlange

Hi,

the following safe Rust snippet causes a use-after-free using your library:

use duckdb::core::{DataChunkHandle, LogicalTypeHandle, LogicalTypeId};

fn main() {
    let mut vec;
    {
        let list_type = LogicalTypeHandle::list(&LogicalTypeId::Integer.into());
        let chunk = DataChunkHandle::new(&[list_type]);
        chunk.set_len(1);

        vec = chunk.list_vector(0);

        vec.set_entry(0, 0, 2);

        println!("{:?}", vec.get_entry(0));
    }
    println!("{:?}", vec.get_entry(0));
}
$ RUSTFLAGS="-Zsanitizer=address" cargo r --release  --target x86_64-unknown-linux-gnu
(0, 2)
=================================================================
==920050==ERROR: AddressSanitizer: heap-use-after-free on address 0x7e26183e0400 at pc 0x55d3d2d55b20 bp 0x7ffc380d3c50 sp 0x7ffc380d3c48
READ of size 8 at 0x7e26183e0400 thread T0

To ensure that the non-owned vector pointer within ListVector is valid, you can either

  1. refcount the owner within the ListVector, ensuring safety at runtime
  2. add an actual reference to the owner in the structure (probably not required)
  3. add a phantom lifetime PhantomData<&'a DataChunkHandle>, which only exists during borrow-checking

If I'm not mistaken FlatVector, ArrayVector and StructVector need the same treatment.

Kind regards
Tim

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