rust icon indicating copy to clipboard operation
rust copied to clipboard

Fix 32-bit overflows in LLVM composite constants

Open erer1243 opened this issue 1 year ago • 9 comments

Inspired by #121868. Fixes unsoundness created when constructing constant arrays, strings, and structs with 2^32 or more elements on x86_64. This introduces copies of a few LLVM functions that have their signatures updated to use size_t in place of unsigned int. Alternatively we could just add overflow checks and just disallow huge composite constants. That introduces less code, but maybe a huge static block of memory is useful in embedded/no-os situations?

erer1243 avatar Mar 04 '24 21:03 erer1243

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @nnethercote (or someone else) some time within the next two weeks.

Please see the contribution instructions for more information. Namely, in order to ensure the minimum review times lag, PR authors and assigned reviewers should ensure that the review label (S-waiting-on-review and S-waiting-on-author) stays updated, invoking these commands when appropriate:

  • @rustbot author: the review is finished, PR author should check the comments and take action accordingly
  • @rustbot review: the author is ready for a review, this PR will be queued again in the reviewer's queue

rustbot avatar Mar 04 '24 21:03 rustbot

Not my area of expertise, let's try r? @nikic

nnethercote avatar Mar 05 '24 06:03 nnethercote

Would you be interested in upstreaming the new APIs to LLVM? If you do that, then we can directly start using them by providing shims like this:

// Or whatever version it was added
#if LLVM_VERSION_LE(17, 0)
LLVMValueRef LLVMConstArray2(LLVMTypeRef ElementTy, LLVMValueRef *ConstantVals,
                             uint64_t Length) {
  ArrayRef<Constant *> V(unwrap<Constant>(ConstantVals, Length), Length);
  return wrap(ConstantArray::get(ArrayType::get(unwrap(ElementTy), Length), V));
}
#endif

That way we'll automatically switch to using the upstream APIs as soon as we can.

nikic avatar Mar 05 '24 13:03 nikic

@nikic Yeah, I was planning on doing that. I'm not sure how long it would take to get through, so I'm not sure which version we would put in the version macro.

erer1243 avatar Mar 05 '24 21:03 erer1243

Having 64bit APIs for structs and vectors did not make sense, because LLVM stores 32bit lengths for them anyway. Now we just assert for overflows before calling those functions. I made a pr to LLVM for 64bit ConstantString constructors and used your idea @nikic to create shims to delete later. If the LLVM patch gets through quickly we can update the LLVM_VERSION_LT check to be 19.

erer1243 avatar Mar 08 '24 05:03 erer1243

Barring the LLVM patch being rescinded, this is now finished.

erer1243 avatar Mar 09 '24 04:03 erer1243

The job mingw-check failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
#13 3.641 Building wheels for collected packages: reuse
#13 3.642   Building wheel for reuse (pyproject.toml): started
#13 3.970   Building wheel for reuse (pyproject.toml): finished with status 'done'
#13 3.970   Created wheel for reuse: filename=reuse-1.1.0-cp310-cp310-manylinux_2_35_x86_64.whl size=181117 sha256=f5f58750481f69515c2c0d1d503daf565e2565c370d07fc6aeb95fe3498b4269
#13 3.971   Stored in directory: /tmp/pip-ephem-wheel-cache-y_7etvq_/wheels/c2/3c/b9/1120c2ab4bd82694f7e6f0537dc5b9a085c13e2c69a8d0c76d
#13 3.973 Installing collected packages: boolean-py, binaryornot, setuptools, reuse, python-debian, markupsafe, license-expression, jinja2, chardet
#13 3.995   Attempting uninstall: setuptools
#13 3.995     Found existing installation: setuptools 59.6.0
#13 3.996     Not uninstalling setuptools at /usr/lib/python3/dist-packages, outside environment /usr
---
    Checking rustc_ast_lowering v0.0.0 (/checkout/compiler/rustc_ast_lowering)
error[E0308]: mismatched types
   --> compiler/rustc_codegen_llvm/src/common.rs:98:59
    |
98  |         unsafe { llvm::LLVMConstArray2(ty, elts.as_ptr(), elts.len()) }
    |                  ---------------------                    ^^^^^^^^^^ expected `u64`, found `usize`
    |                  arguments to this function are incorrect
    |
note: function defined here
   --> compiler/rustc_codegen_llvm/src/llvm/ffi.rs:939:12
   --> compiler/rustc_codegen_llvm/src/llvm/ffi.rs:939:12
    |
939 |     pub fn LLVMConstArray2<'a>(
    |            ^^^^^^^^^^^^^^^
help: you can convert a `usize` to a `u64` and panic if the converted value doesn't fit
    |
98  |         unsafe { llvm::LLVMConstArray2(ty, elts.as_ptr(), elts.len().try_into().unwrap()) }

For more information about this error, try `rustc --explain E0308`.
error: could not compile `rustc_codegen_llvm` (lib) due to 1 previous error
warning: build failed, waiting for other jobs to finish...

rust-log-analyzer avatar Mar 09 '24 16:03 rust-log-analyzer

@bors r+

nikic avatar Mar 11 '24 19:03 nikic

:pushpin: Commit 3af28f0b7094046a190acc7e823b170694f085b9 has been approved by nikic

It is now in the queue for this repository.

bors avatar Mar 11 '24 19:03 bors