-
Notifications
You must be signed in to change notification settings - Fork 14.5k
Description
Reproducer:
struct t1 {};
struct t2 {
t1 b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15, b16,
b17, b18, b19, b20, b21, b22, b23, b24, b25, b26, b27, b28, b29, b30, b31,
b32, b33, b34, b35, b36, b37, b38, b39, b40, b41, b42, b43, b44, b45, b46,
b47, b48, b49, b50, b51;
int v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16,
v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31,
v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42;
};
void aj(...);
void f1(t2 w) { __builtin_dump_struct(&w, aj); }
Analysis of cause from @dwblaikie:
The data read in https://github.com/llvm/llvm-project/blob/main/clang/lib/AST/ComputeDependence.cpp#L682 is invalid and causes the crash. This is due to the unsigned:8
at https://github.com/llvm/llvm-project/blob/main/clang/include/clang/AST/Stmt.h#L597 overflowing:
// These don't need to be particularly wide, because they're
// strictly limited by the forms of expressions we permit.
unsigned NumSubExprs : 8;
unsigned ResultIndex : 32 - 8 - NumExprBits;
Removing an element from the repro (either of the struct or int member variables) the length of the range is 254 (so getNumSubExprs
in 255)
Adding one element, it's not that it's /good/ at NumSubExprs
256 - it still has the same problem, the value gets truncated to fit in the unsigned:8
bitfield, but because it overflows to 1 (rather than zero) at least the range is valid (empty (the -1 doesn't create the end<begin)) so it doesn't crash - but probably isn't doing the right things either (because it's not visiting all the subexprs - it's visiting none of them).
What the code is /meant/ to do when the size is too large... is there a bail out?
Side notes for debugging:
An assertion in the llvm::iterator_range
ctor (also, this code should probably use llvm::ArrayRef
since its iterators are just pointers anyway - and a similar assertion should go in the llvm::ArrayRef
ctor), at least for iterators that support op<=
that begin <=
end would've caught this.
Also a more specific assertion in PseudoObjectExpr::PseudoObjectExpr
ctors that asserts that NumSubExprs
actually can/does store the value (without truncation/overflow/etc) that it's intended to.
Both of those assertions would probably be worth adding once (the iterator_range
/arrayref
one might be a harder sell if it's too expensive/may have to go under LLVM's EXPENSIVE_CHECKS
category) the bug is fixed.