Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unsafe::reinterpret_cast can cause valgrind errors #1175

Closed
jdm opened this issue Nov 14, 2011 · 3 comments
Closed

unsafe::reinterpret_cast can cause valgrind errors #1175

jdm opened this issue Nov 14, 2011 · 3 comments

Comments

@jdm
Copy link
Contributor

jdm commented Nov 14, 2011

Sorry for the vague summary, but I've reduced this testcase about as far as I can.

import std::{str, option, unsafe};
use std;

type metadata<T> = {node: int, data: @T};
type compile_unit_md = {path: str};
type metadata_cache = [@debug_metadata];

tag debug_metadata {
    compile_unit_metadata(@metadata<compile_unit_md>);
}

fn get_compile_unit_metadata(cache: metadata_cache, full_path: str)
    -> @metadata<compile_unit_md> unsafe {
    ret alt *cache[0] {
      compile_unit_metadata(md) { unsafe::reinterpret_cast(md) }
    };
}

fn main() {
    let cache = [@compile_unit_metadata(@{node: 1, data: @{path: "test/a"}})];
    get_compile_unit_metadata(cache, "test/a/b");
}

When running the above, I get output like:

godot:build jdm$ ~/src/rustbug
rustbug(24826,0xb0305000) malloc: *** error for object 0x11001a0: incorrect checksum for freed object - object was probably modified after being freed.
*** set a breakpoint in malloc_error_break to debug

and valgrind has lots of entries for glue_drop15:

==24813== Invalid read of size 4
==24813==    at 0x30A6: glue_drop15 (in /Users/jdm/src/rustbug)
==24813==    by 0x232A: main::_e820af82886e4814 (in /Users/jdm/src/rustbug)
==24813==    by 0x259A: _rust_main (in /Users/jdm/src/rustbug)
==24813==    by 0x34E717: task_start_wrapper (in /Users/jdm/src/rust/build/stage2/lib/rustc/i686-apple-darwin/lib/librustrt.dylib)
==24813==    by 0xDEADBEEE: ???
==24813==  Address 0x1c08d60 is 0 bytes inside a block of size 12 free'd
==24813==    at 0x1243A: free (vg_replace_malloc.c:430)
==24813==    by 0x351B79: upcall_free (in /Users/jdm/src/rust/build/stage2/lib/rustc/i686-apple-darwin/lib/librustrt.dylib)
==24813==    by 0x3165: glue_free16 (in /Users/jdm/src/rustbug)
==24813==    by 0x30E3: glue_drop15 (in /Users/jdm/src/rustbug)
==24813==    by 0x2201: main::_e820af82886e4814 (in /Users/jdm/src/rustbug)
==24813==    by 0x259A: _rust_main (in /Users/jdm/src/rustbug)
==24813==    by 0x34E717: task_start_wrapper (in /Users/jdm/src/rust/build/stage2/lib/rustc/i686-apple-darwin/lib/librustrt.dylib)
==24813==    by 0xDEADBEEE: ???

If I assign the result of get_compile_metadata to a local var valgrind still complains, but the malloc error doesn't seem to show up any more.

@jdm
Copy link
Contributor Author

jdm commented Nov 14, 2011

fn get_compile_unit_metadata(cache: metadata_cache, full_path: str)
    -> @metadata<compile_unit_md> unsafe {
    ret alt *cache[0] {
      compile_unit_metadata(md) { unsafe::reinterpret_cast(md) }
    };
}

Looks like the unsafe::reinterpret_cast here is the catalyst. This version of get_compile_unit_metadata displays the valgrind errors, and the one that just returns md without the cast does not.

@jdm
Copy link
Contributor Author

jdm commented Nov 14, 2011

import std::unsafe;
use std;

tag test {
    a(@int);
}

fn main() unsafe {
    let val = a(@1);
    log_err alt val {
      a(i) { unsafe::reinterpret_cast::<@int, @int>(i) }
    };
}

16:08 13:06 < brson> jdm: the problem is thaht when you reinterpret cast that box, now you have two typed pointers to a box, but you didn't ever bump the refcount, so you ending up dropping the ref twice
16:08 13:06 < brson> the solution here is that after you do the reinterpret cast, run unsafe::leak on the old pointer

@jdm
Copy link
Contributor Author

jdm commented Nov 14, 2011

Brian's suggestion resolved the valgrind messages.

@jdm jdm closed this as completed Nov 14, 2011
coastalwhite pushed a commit to coastalwhite/rust that referenced this issue Aug 5, 2023
This changes wasm simd intrisnics which deal with memory to match clang
where they all are emitted with an alignment of 1. This is expected to
not impact performance since wasm engines generally ignore alignment as
it's just a hint. Otherwise this can increase safety slightly when used
from Rust since if an unaligned pointer was previously passed in that
could result in UB on the LLVM side. This means that the intrinsics are
slighly more usable in more situations than before.

It's expected that if higher alignment is desired then programs will not
use these intrinsics but rather the component parts. For example instead
of `v128_load` you'd just load the pointer itself (and loading from a
pointer in Rust automatically assumes correct alignment). For
`v128_load64_splat` you'd do a load followed by a splat operation, which
LLVM should optimized into a `v128.load64_splat` instruction with the
desired alignment. LLVM doesn't fully support some optimizations (such
as optimizing `v128.load16_lane` from component parts) but that's
expected to be a temporary issue. Additionally we don't have a way of
configuring the alignment on operations that otherwise can't be
decomposed into their portions (such as with `i64x2_load_extend_u32x2`),
but we can ideally cross such a bridge when we get there if anyone ever
needs the alignment configured there.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant