Skip to content

Memory safety bug in prqlc-c: Vec::from_raw_parts with wrong element type #5731

@prql-bot

Description

@prql-bot

In prqlc/bindings/prqlc-c/src/lib.rs (lines 238-242), the prqlc_destroy_compile_result function reconstructs a Vec<i8> from a pointer that originally pointed to Vec<Message>:

drop(Vec::from_raw_parts(
    res.messages as *mut i8,
    res.messages_len,
    res.messages_len,
));

This has two issues:

  1. Wrong element type: The pointer is cast to *mut i8 but the original allocation was for Message elements. When the Vec is dropped, dealloc is called with messages_len * size_of::<i8>() bytes, but the actual allocation size was capacity * size_of::<Message>() bytes. This is undefined behavior per the Vec::from_raw_parts safety contract.

  2. Capacity assumption: The capacity is set to messages_len, but the original Vec was created with Vec::with_capacity(err.inner.len()). While these should be equal in practice (the Vec is extended with exactly err.inner.len() items), the safety contract requires the exact capacity from the original allocation.

Suggested fix:

drop(Vec::from_raw_parts(
    res.messages as *mut Message,
    res.messages_len,
    res.messages_len,
));

The individual Message fields are already cleaned up in the loop above (lines 218-236), so the Vec destructor just needs to free the allocation with the correct layout.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugInvalid compiler output or panic

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions