Skip to content

Can bypass repr(packed) checking by hiding it in a proc-macro-attribute #32

@Nemo157

Description

@Nemo157

Given a proc-macro crate like this:

extern crate proc_macro;

use proc_macro::TokenStream;

#[proc_macro_attribute]
pub fn hidden_repr(attr: TokenStream, item: TokenStream) -> TokenStream {
    format!("#[repr({})] {}", attr, item).parse().unwrap()
}

Using it along with pin-project in a project can cause a value to be pinned in one location and dropped in another:

use core::pin::Pin;
use hidden_repr::hidden_repr;
use pin_project::pin_projectable;

#[derive(Debug)]
struct Foo(u16);

impl Foo {
    fn foo(self: Pin<&mut Self>) {
        println!("{:?} at {:p}", self, self);
    }
}

impl Drop for Foo {
    fn drop(&mut self) {
        println!("{:?} dropped at {:p}", self, self);
    }
}

#[pin_projectable]
#[hidden_repr(packed)]
struct Bar {
    _bar: u8,
    #[pin]
    foo: Foo,
}

fn main() {
    let mut bar = Box::pin(Bar { _bar: 0, foo: Foo(0) });
    bar.as_mut().project().foo.foo();
}

output:

Foo(0) at 0x560220317a41
Foo(0) dropped at 0x7fff2b8510b6

(it appears proc-macro-attribute application order is not defined, so not guaranteed to reproduce, but this seems like the sane order for rustc to apply them in so it's likely to continue working).

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-pin-projectionArea: #[pin_project]C-bugCategory: related to a bug.I-unsoundA soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions