Skip to content
New issue

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

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

Already on GitHub? # to your account

Use the aligned size for alloca at args/ret when the pass mode is cast #127168

Merged
merged 3 commits into from
Jul 2, 2024

Conversation

DianQK
Copy link
Member

@DianQK DianQK commented Jun 30, 2024

Fixes #75839. Fixes #121028.

The load and store instructions in LLVM access the aligned size. For example, load { i64, i32 } accesses 16 bytes on x86_64: https://alive2.llvm.org/ce/z/n8CHAp.

BTW, this example is expected to be optimized to immediate UB by Alive2: https://rust.godbolt.org/z/b7xK7hv1c and https://alive2.llvm.org/ce/z/vZDtZH.

r? compiler

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jun 30, 2024
@DianQK DianQK changed the title Use the aligned size for alloca. Use the aligned size for alloca Jun 30, 2024
@workingjubilee
Copy link
Member

@DianQK what's the LLVMIR of the example after this patch?

@workingjubilee
Copy link
Member

The LLVMIR after this PR now seems to be this:

; ModuleID = 'miscompiled_arg.4dadb824ae4952c2-cgu.0'
source_filename = "miscompiled_arg.4dadb824ae4952c2-cgu.0"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

; Function Attrs: nounwind nonlazybind uwtable
define { i64, i32 } @foo({ i64, i32 } %0) unnamed_addr #0 {
start:
  %_0 = alloca [12 x i8], align 4
  %1 = alloca [16 x i8], align 8
  %arg = alloca [12 x i8], align 4
  store { i64, i32 } %0, ptr %1, align 8
  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %arg, ptr align 8 %1, i64 12, i1 false)
  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %_0, ptr align 4 %arg, i64 12, i1 false)
  %2 = load { i64, i32 }, ptr %_0, align 4
  ret { i64, i32 } %2
}

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) #1

attributes #0 = { nounwind nonlazybind uwtable "probe-stack"="inline-asm" "target-cpu"="x86-64" }
attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }

!llvm.module.flags = !{!0, !1}
!llvm.ident = !{!2}

!0 = !{i32 8, !"PIC Level", i32 2}
!1 = !{i32 2, !"RtLibUseGOT", i32 1}
!2 = !{!"rustc version 1.81.0-dev"}

But Alive2 still flags this as UB, and what needs to happen is this:

-  %_0 = alloca [12 x i8], align 4
+  %_0 = alloca [16 x i8], align 4

@DianQK
Copy link
Member Author

DianQK commented Jul 1, 2024

What was I thinking? @.@
I believe this must be a test case in tests/codegen/cast-target-abi.rs. I will update this PR tonight.

@rustbot author

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jul 1, 2024
@workingjubilee
Copy link
Member

Thank you for your work on this, and please don't feel bad about making a mistake. 💖 Code review is precisely for checking for errors, sometimes silly-seeming ones, and this is... certainly not the easiest part of rustc to work with.

@DianQK
Copy link
Member Author

DianQK commented Jul 1, 2024

Thank you for your work on this, and please don't feel bad about making a mistake. 💖 Code review is precisely for checking for errors, sometimes silly-seeming ones, and this is... certainly not the easiest part of rustc to work with.

Don't worry. I'm just complaining about I show a bug that I'm fixing in the PR. Probably because I simplified the code while debugging. :3

@DianQK DianQK changed the title Use the aligned size for alloca Use the aligned size for alloca at args/ret when the pass mode is cast Jul 1, 2024
@DianQK
Copy link
Member Author

DianQK commented Jul 1, 2024

Edit: Perhaps I should put the commit that updates the test cases at first. I'll consider updating it tomorrow. Time for bed.

I split the changes into three commits for review. The latest commit includes updates to the return value.

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jul 1, 2024
@workingjubilee
Copy link
Member

Everything seems in order. Confirmed the codegen passes Alive2 after pulling and building. If this PR needs further fixes, I think we can do it as a followup.

@bors r+

@bors
Copy link
Contributor

bors commented Jul 2, 2024

📌 Commit 2ef8280 has been approved by workingjubilee

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jul 2, 2024
bors added a commit to rust-lang-ci/rust that referenced this pull request Jul 2, 2024
Use the aligned size for alloca at args/ret when the pass mode is cast

Fixes rust-lang#75839. Fixes rust-lang#121028.

The `load` and `store` instructions in LLVM access the aligned size. For example, `load { i64, i32 }` accesses 16 bytes on x86_64: https://alive2.llvm.org/ce/z/n8CHAp.

BTW, this example is expected to be optimized to immediate UB by Alive2: https://rust.godbolt.org/z/b7xK7hv1c and https://alive2.llvm.org/ce/z/vZDtZH.

r? compiler
@bors
Copy link
Contributor

bors commented Jul 2, 2024

⌛ Testing commit 2ef8280 with merge 7a59bfd...

@bors
Copy link
Contributor

bors commented Jul 2, 2024

💔 Test failed - checks-actions

@bors bors added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Jul 2, 2024
@compiler-errors
Copy link
Member

@bors retry

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jul 2, 2024
@rust-log-analyzer
Copy link
Collaborator

A job failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
#14 0.422 
#14 0.422 gzip: stdin: not in gzip format
#14 0.423 tar: Child returned status 1
#14 0.423 tar: Error is not recoverable: exiting now
#14 ERROR: process "/bin/sh -c env HOST_CFLAGS=\"-O -fcommon\" /tmp/build-netbsd-toolchain.sh" did not complete successfully: exit code: 2
 > [6/8] RUN env HOST_CFLAGS="-O -fcommon" /tmp/build-netbsd-toolchain.sh:
0.035 + mkdir netbsd

100   245  100   245    0     0    647      0 --:--:-- --:--:-- --:--:--   648
---
  11 | >>> RUN env HOST_CFLAGS="-O -fcommon" /tmp/build-netbsd-toolchain.sh
  12 |     
  13 |     COPY scripts/sccache.sh /scripts/
--------------------
ERROR: failed to solve: process "/bin/sh -c env HOST_CFLAGS=\"-O -fcommon\" /tmp/build-netbsd-toolchain.sh" did not complete successfully: exit code: 2
#0 building with "jolly_gagarin" instance using docker-container driver

#1 [internal] load build definition from Dockerfile
#1 transferring dockerfile: 988B done
---
#11 0.182 
#11 0.182 gzip: stdin: not in gzip format
#11 0.182 tar: Child returned status 1
#11 0.182 tar: Error is not recoverable: exiting now
#11 ERROR: process "/bin/sh -c env HOST_CFLAGS=\"-O -fcommon\" /tmp/build-netbsd-toolchain.sh" did not complete successfully: exit code: 2
 > [6/8] RUN env HOST_CFLAGS="-O -fcommon" /tmp/build-netbsd-toolchain.sh:
:--:--  1737
0.182 
0.182 gzip: stdin: not in gzip format
---
  11 | >>> RUN env HOST_CFLAGS="-O -fcommon" /tmp/build-netbsd-toolchain.sh
  12 |     
  13 |     COPY scripts/sccache.sh /scripts/
--------------------
ERROR: failed to solve: process "/bin/sh -c env HOST_CFLAGS=\"-O -fcommon\" /tmp/build-netbsd-toolchain.sh" did not complete successfully: exit code: 2
#0 building with "jolly_gagarin" instance using docker-container driver

#1 [internal] load build definition from Dockerfile
#1 transferring dockerfile: 988B done
---
#11 0.453 
#11 0.453 gzip: stdin: not in gzip format
#11 0.453 tar: Child returned status 1
#11 0.453 tar: Error is not recoverable: exiting now
#11 ERROR: process "/bin/sh -c env HOST_CFLAGS=\"-O -fcommon\" /tmp/build-netbsd-toolchain.sh" did not complete successfully: exit code: 2
 > [6/8] RUN env HOST_CFLAGS="-O -fcommon" /tmp/build-netbsd-toolchain.sh:

100   245  100   245    0     0    592      0 --:--:-- --:--:-- --:--:--   593
0.453 
---
  11 | >>> RUN env HOST_CFLAGS="-O -fcommon" /tmp/build-netbsd-toolchain.sh
  12 |     
  13 |     COPY scripts/sccache.sh /scripts/
--------------------
ERROR: failed to solve: process "/bin/sh -c env HOST_CFLAGS=\"-O -fcommon\" /tmp/build-netbsd-toolchain.sh" did not complete successfully: exit code: 2
#0 building with "jolly_gagarin" instance using docker-container driver

#1 [internal] load build definition from Dockerfile
#1 transferring dockerfile: 988B done
---
#11 0.423 
#11 0.423 gzip: stdin: not in gzip format
#11 0.424 tar: Child returned status 1
#11 0.424 tar: Error is not recoverable: exiting now
#11 ERROR: process "/bin/sh -c env HOST_CFLAGS=\"-O -fcommon\" /tmp/build-netbsd-toolchain.sh" did not complete successfully: exit code: 2
 > [6/8] RUN env HOST_CFLAGS="-O -fcommon" /tmp/build-netbsd-toolchain.sh:

100   245  100   245    0     0    639      0 --:--:-- --:--:-- --:--:--   639
0.423 
---
  11 | >>> RUN env HOST_CFLAGS="-O -fcommon" /tmp/build-netbsd-toolchain.sh
  12 |     
  13 |     COPY scripts/sccache.sh /scripts/
--------------------
ERROR: failed to solve: process "/bin/sh -c env HOST_CFLAGS=\"-O -fcommon\" /tmp/build-netbsd-toolchain.sh" did not complete successfully: exit code: 2
#0 building with "jolly_gagarin" instance using docker-container driver

#1 [internal] load build definition from Dockerfile
#1 transferring dockerfile: 988B done
---
#11 0.344 
#11 0.344 gzip: stdin: not in gzip format
#11 0.344 tar: Child returned status 1
#11 0.344 tar: Error is not recoverable: exiting now
#11 ERROR: process "/bin/sh -c env HOST_CFLAGS=\"-O -fcommon\" /tmp/build-netbsd-toolchain.sh" did not complete successfully: exit code: 2
 > [6/8] RUN env HOST_CFLAGS="-O -fcommon" /tmp/build-netbsd-toolchain.sh:

100   245  100   245    0     0    805      0 --:--:-- --:--:-- --:--:--   808
0.344 
---
  11 | >>> RUN env HOST_CFLAGS="-O -fcommon" /tmp/build-netbsd-toolchain.sh
  12 |     
  13 |     COPY scripts/sccache.sh /scripts/
--------------------
ERROR: failed to solve: process "/bin/sh -c env HOST_CFLAGS=\"-O -fcommon\" /tmp/build-netbsd-toolchain.sh" did not complete successfully: exit code: 2
##[error]Process completed with exit code 1.
Post job cleanup.

@nikic
Copy link
Contributor

nikic commented Jul 2, 2024

I don't think that this is the right way to fix the issue. Instead of changing the alloca size, we should remove the use of aggregate loads/stores (load/store member-wise instead).

@DianQK
Copy link
Member Author

DianQK commented Jul 2, 2024

I don't think that this is the right way to fix the issue. Instead of changing the alloca size, we should remove the use of aggregate loads/stores (load/store member-wise instead).

But we always need to return a { i64, i32 }, so do we still need this alloca { i64, i32 }? It looks like clang generates similar IR: https://llvm.godbolt.org/z/bxbbrhjeY. Or I guess you mean insertvalue?

@nikic
Copy link
Contributor

nikic commented Jul 2, 2024

Yes, I mean using insertvalue. LLVM will ultimately convert it to that form, which is why this is not a problem with optimizations. But we should directly generate that instead of going through an aggregate load in the first place.

@DianQK
Copy link
Member Author

DianQK commented Jul 2, 2024

Yes, I mean using insertvalue. LLVM will ultimately convert it to that form, which is why this is not a problem with optimizations. But we should directly generate that instead of going through an aggregate load in the first place.

This makes sense to me. I think that as a bugfix PR, the current changes can make the sanitizers work correctly and LLVM can also optimize most of it with insertvalue. I prefer to treat insertvalue as a separate PR for improving compilation time.

bors added a commit to rust-lang-ci/rust that referenced this pull request Jul 2, 2024
…iaskrgr

Rollup of 10 pull requests

Successful merges:

 - rust-lang#126883 (Parenthesize break values containing leading label)
 - rust-lang#127136 (Fix `FnMut::call_mut`/`Fn::call` shim for async closures that capture references)
 - rust-lang#127146 (Uplift fast rejection to new solver)
 - rust-lang#127152 (Bootstrap: Try renaming the file if removing fails)
 - rust-lang#127168 (Use the aligned size for alloca at args/ret when the pass mode is cast)
 - rust-lang#127203 (Fix import suggestion error when path segment failed not from starting)
 - rust-lang#127212 (Update books)
 - rust-lang#127224 (Make `FloatTy` checks exhaustive in pretty print)
 - rust-lang#127230 (chore: remove duplicate words)
 - rust-lang#127243 (Add test for adt_const_params)

r? `@ghost`
`@rustbot` modify labels: rollup
bors added a commit to rust-lang-ci/rust that referenced this pull request Jul 2, 2024
…iaskrgr

Rollup of 10 pull requests

Successful merges:

 - rust-lang#126883 (Parenthesize break values containing leading label)
 - rust-lang#127136 (Fix `FnMut::call_mut`/`Fn::call` shim for async closures that capture references)
 - rust-lang#127146 (Uplift fast rejection to new solver)
 - rust-lang#127152 (Bootstrap: Try renaming the file if removing fails)
 - rust-lang#127168 (Use the aligned size for alloca at args/ret when the pass mode is cast)
 - rust-lang#127203 (Fix import suggestion error when path segment failed not from starting)
 - rust-lang#127212 (Update books)
 - rust-lang#127224 (Make `FloatTy` checks exhaustive in pretty print)
 - rust-lang#127230 (chore: remove duplicate words)
 - rust-lang#127243 (Add test for adt_const_params)

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit 33b0238 into rust-lang:master Jul 2, 2024
6 of 7 checks passed
@rustbot rustbot added this to the 1.81.0 milestone Jul 2, 2024
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Jul 2, 2024
Rollup merge of rust-lang#127168 - DianQK:cast-size, r=workingjubilee

Use the aligned size for alloca at args/ret when the pass mode is cast

Fixes rust-lang#75839. Fixes rust-lang#121028.

The `load` and `store` instructions in LLVM access the aligned size. For example, `load { i64, i32 }` accesses 16 bytes on x86_64: https://alive2.llvm.org/ce/z/n8CHAp.

BTW, this example is expected to be optimized to immediate UB by Alive2: https://rust.godbolt.org/z/b7xK7hv1c and https://alive2.llvm.org/ce/z/vZDtZH.

r? compiler
@DianQK DianQK deleted the cast-size branch July 2, 2024 22:30
@workingjubilee
Copy link
Member

yes, I assumed that we already intended to remove our aggregate load/stores and that this not doing so is because fixing "emitting LLVMIR with UB" is a smaller patch worth independently addressing.

@DianQK
Copy link
Member Author

DianQK commented Jul 3, 2024

I'll give it a try. :)
This is a P-high issue and the only known real problem is ASAN, but I'm worried that this might cause runtime errors in some edge cases.

@rustbot label +beta-nominated

@rustbot rustbot added the beta-nominated Nominated for backporting to the compiler in the beta channel. label Jul 3, 2024
@apiraino
Copy link
Contributor

apiraino commented Jul 4, 2024

Beta backport declined as per compiler team on Zulip, since the issue fixed is quite old and ASAN is not stable.

@rustbot label -beta-nominated

@rustbot rustbot removed the beta-nominated Nominated for backporting to the compiler in the beta channel. label Jul 4, 2024
@DianQK
Copy link
Member Author

DianQK commented Aug 11, 2024

Follow-up PR: #128969.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

possible ASAN miscompile llvm lint: buffer overflow in src/test/ui/foreign/foreign-truncated-arguments.rs
9 participants