[clang] [lldb] [Clang] Introduce OverflowBehaviorType for fine-grained overflow control (PR #148914)
Kees Cook via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 15 13:19:50 PDT 2025
kees wrote:
tl;dr: I think I understand what you're saying and I think I'm convinced...
We seem to be talking about different things. I'm trying to understand what you're describing. It looks like you're trying to say that values that are stored in an OBT variable carry their OB-ness permanently, such that the value cannot be stored to a non-matching OBT variable without being instrumented? I would absolutely love this approach except that I think it makes it unusable, see much further below for applying this to Linux.
But just to restate what I think you're saying, given:
```
int __ob_trap src = runtime_256;
u8 dest = src;
```
You're saying that the "256(stored in int, with OB trap)" value must trap when stored to "char dest" because bits will be lost. I am saying that the OB is only supposed to be checked when overflow happens for an annotated variable, i.e. when a value is stored to (or used as) an annotated variable. As in, you're saying we go through these steps:
- 256 (stored in int, with OB trap)
- 256(to be stored in u8, with OB trap)
- overflow! 256 truncated to 1 (traps)
- 1(stored in u8, no OB) (not performed, since we trapped)
Rather than what I'm imagining which is:
- 256 (stored in int, with OB trap)
- 256(to be stored in u8, no OB)
- overflow! 256 truncated to 1 (no trap)
- 1(stored in u8, no OB)
I'm saying that the _variable_ carries the OB, not the value.
You have a later example doing effectively:
```
void takes_u32(u32 value);
u64 unannoated; // 2
u32 __ob_trap trapping; // U32_MAX
...
takes_u32(trapping * unannotated);
```
Which you're saying needs the "OB follows the value" logic so that we get:
```
(u64 __ob_trap)(u32 __ob_trap)trapping * (u64 __ob_trap)(u64)unannotated // U32_MAX * 2 does not overflow u64
takes_u32((u64 __ob_trap)(U32_MAX * 2) -> u32) // trap because bits lost
```
To me, this is surprising because `u32 value` isn't `__ob_trap`.
The reason for doing store-only checking is because I don't think we'll be able to move a codebase to OBT if using an OBT pollutes everything it touches, specifically because current types are ambiguous about whether or not they expect overflow. I'm very worried I won't be able to port Linux to using OBTs (for example for `size_t` to be `unsigned long __ob_trap`) if assignments of non-OBT may start trapping. I think we're going to get a lot of push-back if "surprising" things start happening.
https://github.com/llvm/llvm-project/pull/148914
More information about the cfe-commits
mailing list