Skip to content

Validate constant type preconditions in the LLVMValueRef Create* wrappers - #259

Merged
tannergooding merged 4 commits into
dotnet:mainfrom
tannergooding:tannergooding-native-packaging-triage
Jul 15, 2026
Merged

Validate constant type preconditions in the LLVMValueRef Create* wrappers#259
tannergooding merged 4 commits into
dotnet:mainfrom
tannergooding:tannergooding-native-packaging-triage

Conversation

@tannergooding

Copy link
Copy Markdown
Member

Fixes #194.

The LLVMValueRef.Create* helpers are billed as the "safer (but still lowlevel)" wrappers over the raw bindings, but several of the constant creators pass a mistyped operand straight through to libLLVM, where it either silently produces corrupt IR or -- on a release libLLVM with asserts compiled out -- access-violates. #194 is the canonical example: CreateConstReal on an i32 reinterpreted the type as ppc_fp128 on LLVM 14 and hard-crashes on current libLLVM. The module verifier can't cover this, since the raw binding faults before you can verify.

This mirrors libLLVM's own C++ asserts in the wrappers so the mistake surfaces as a clear ArgumentException pointing at the right helper, while the raw LLVM.* bindings stay unchecked by design.


CreateConstReal / CreateConstRealOfString / CreateConstRealOfStringAndSize now require a floating-point (scalar or vector) type, matching ConstantFP::get.


CreateConstInt / CreateConstIntOfArbitraryPrecision / CreateConstIntOfString / CreateConstIntOfStringAndSize now require an integer type, matching ConstantInt::get via unwrap<IntegerType>. Without this, CreateConstInt(Double, 8) silently returns i0 0.


CreateConstIntToPtr / CreateConstPtrToInt now require the operand and target to be int-or-int-vector / ptr-or-ptr-vector on the correct sides, matching the asserts in ConstantExpr::getIntToPtr / getPtrToInt. Swapping the two is an easy footgun.

The checks are factored through a shared GetScalarType helper so scalar and vector types are handled the same way libLLVM does.

Intentionally left alone: CreateConstBitCast -- its contract is CastInst::castIsValid, which isn't a trivial type-kind check, so approximating it would be worse than deferring to the verifier -- and the IRBuilder Build* surface, which is deliberately lowlevel and covered by Verify/TryVerify.

Tests: added tests/LLVMSharp.UnitTests/Constants.cs covering each guard's reject and accept paths. Full suite is green (2596 passed, 0 warnings).

tannergooding and others added 4 commits July 15, 2026 10:09
The ConstReal family maps onto ConstantFP::get, which requires a
floating-point (or floating-point vector) type. Passing an integer type
previously produced corrupt IR (ppc_fp128) or crashed the raw binding.
Surface a clear ArgumentException from the safer wrapper instead.

Addresses dotnet#194.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
ConstInt maps onto ConstantInt::get via unwrap<IntegerType>, so a
non-integer type silently produces corrupt IR (e.g. 'i0 0' for a double)
rather than erroring -- the integer-side analogue of the ConstReal issue
in dotnet#194. Surface a clear ArgumentException instead.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…get types

ConstantExpr::getIntToPtr/getPtrToInt assert the operand and target are
int-or-int-vector / ptr-or-ptr-vector respectively; swapping them is an
easy footgun that the unchecked bindings pass straight through. Mirror
those asserts in the safer wrappers via a shared scalar-type helper.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
… throwers

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@tannergooding
tannergooding merged commit f15e455 into dotnet:main Jul 15, 2026
12 checks passed
@tannergooding
tannergooding deleted the tannergooding-native-packaging-triage branch July 15, 2026 17:42
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

Successfully merging this pull request may close these issues.

LLVM converts integer types to floats

1 participant