- 
                Notifications
    You must be signed in to change notification settings 
- Fork 13.9k
Open
Labels
A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.A-codegenArea: Code generationArea: Code generationC-bugCategory: This is a bug.Category: This is a bug.I-crashIssue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics.Issue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics.P-mediumMedium priorityMedium priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.
Description
Meta
$ rustc --version
rustc 1.22.0-nightly (185cc5f26 2017-10-02)
STR
#![crate_type="rlib"]
#[no_mangle]
pub extern "C" fn foo(x: &(i8, i8, i8)) -> (i8, i8, i8) {
    *x
}target is x86_64-unknown-linux-gnu
Expected Result
Code generated should not have UB
Actual Result
The generated no-opt LLVM IR is:
; ModuleID = 'cast.cgu-0.rs'
source_filename = "cast.cgu-0.rs"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
; Function Attrs: nounwind uwtable
define i32 @foo({ i8, [0 x i8], i8, [0 x i8], i8, [0 x i8] }* noalias readonly dereferenceable(3)) unnamed_addr #0 {
start:
  %_3 = alloca { i8, [0 x i8], i8, [0 x i8], i8, [0 x i8] }
  ; COMMENT MINE: %_0 has size 3
  %_0 = alloca { i8, [0 x i8], i8, [0 x i8], i8, [0 x i8] }
  %1 = bitcast { i8, [0 x i8], i8, [0 x i8], i8, [0 x i8] }* %0 to i8*
  %2 = bitcast { i8, [0 x i8], i8, [0 x i8], i8, [0 x i8] }* %_3 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %2, i8* %1, i64 3, i32 1, i1 false)
  %3 = bitcast { i8, [0 x i8], i8, [0 x i8], i8, [0 x i8] }* %_3 to i8*
  %4 = bitcast { i8, [0 x i8], i8, [0 x i8], i8, [0 x i8] }* %_0 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %4, i8* %3, i64 3, i32 1, i1 false)
  ; COMMENT MINE it is cast to an i32 here
  %5 = bitcast { i8, [0 x i8], i8, [0 x i8], i8, [0 x i8] }* %_0 to i32*
  ; COMMENT MINE and then loaded as through it was size 4
  %6 = load i32, i32* %5, align 1
  ret i32 %6
}
; Function Attrs: argmemonly nounwind
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32, i1) #1
attributes #0 = { nounwind uwtable "probe-stack"="__rust_probestack" }
attributes #1 = { argmemonly nounwind }This loads 4 bytes of an alloca of size 3. I couldn't trivially turn this to an end-to-end mis-code-generation (this can't be used to load from anything but the return pointer, so you can't do the standard "load at end of page" trick), but I can't see how can oversize loads can be anything but UB.
cc @eddyb - I think one solution would be to pad the return pointer alloca to always have enough space for the cast, aka:
  %_0_store = alloca {{ i8, [0 x i8], i8, [0 x i8], i8, [0 x i8] }, [1 x i8]}
  %_0 = getelementptr inbounds {{ i8, [0 x i8], i8, [0 x i8], i8, [0 x i8] }, [1 x i8]}, {{ i8, [0 x i8], i8, [0 x i8], i8, [0 x i8] }, [1 x i8]}* %_0_store, i32 0, i32 1I think the problem load is the one in
rust/src/librustc_trans/mir/block.rs
Line 247 in e847f30
| let load = bcx.load( | 
Metadata
Metadata
Assignees
Labels
A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.A-codegenArea: Code generationArea: Code generationC-bugCategory: This is a bug.Category: This is a bug.I-crashIssue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics.Issue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics.P-mediumMedium priorityMedium priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.