Skip to content

Commit a150e80

Browse files
Ayush3941tbaederr
andauthored
[clang][bytecode] Avoid crash in constexpr wcslen on invalid argument… (llvm#177891)
### What the problem ? Fix a clang bytecode constant interpreter crash when evaluating wcslen("x") in a constant-expression path. Previously we asserted on wchar element size mismatch and crashed in assertion builds. ### Why it happened The expression is already ill-typed (char[2] → const wchar_t*), clang correctly emits a diagnostic, but later ICE checking tries to fold the expression and reaches the builtin handler. That path must not crash. ### whats the Fix Replace the assert(ElemSize == wchar_t size) with a graceful failure (return false / emit appropriate diagnostic) when element sizes don’t match, so evaluation stops safely. ### how to Test it Add a regression test that triggers ICE checking with -fexperimental-new-constant-interpreter and ensures clang does not crash (verifies it reports the type error / static_assert failure instead). Fixes llvm#177844. <img width="1366" height="768" alt="Screenshot_2026-01-25_22_07_50" src="https://github.com/user-attachments/assets/488dd0b0-3c17-4f45-b2d0-9339b8fd3409" /> where wclen_crash.c is ` #include <wchar.h> static_assert(wcslen("x") == 'x'); int main() {} ` --------- Co-authored-by: Timm Baeder <tbaeder@redhat.com>
1 parent b0ce26c commit a150e80

2 files changed

Lines changed: 16 additions & 2 deletions

File tree

clang/lib/AST/ByteCode/InterpBuiltin.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -367,8 +367,10 @@ static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC,
367367
unsigned ElemSize = StrPtr.getFieldDesc()->getElemSize();
368368

369369
if (ID == Builtin::BI__builtin_wcslen || ID == Builtin::BIwcslen) {
370-
[[maybe_unused]] const ASTContext &AC = S.getASTContext();
371-
assert(ElemSize == AC.getTypeSizeInChars(AC.getWCharType()).getQuantity());
370+
const ASTContext &AC = S.getASTContext();
371+
unsigned WCharSize = AC.getTypeSizeInChars(AC.getWCharType()).getQuantity();
372+
if (ElemSize != WCharSize)
373+
return false;
372374
}
373375

374376
size_t Len = 0;

clang/test/AST/ByteCode/builtin-functions.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1903,3 +1903,15 @@ namespace NonBlockPointerStore {
19031903
void foo(void) { a *= __builtin_sadd_overflow(1, 2, 0); }
19041904
void foo2(void) { a *= __builtin_addc(1, 2, 0, 0); }
19051905
}
1906+
1907+
namespace WcslenInvalidArg {
1908+
1909+
static_assert(__builtin_wcslen("x") == 'x'); // both-error {{cannot initialize a parameter of type 'const wchar_t *' with an lvalue of type 'const char[2]'}}
1910+
static_assert(__builtin_wcslen((const wchar_t *)"x") == 1); // both-error {{static assertion expression is not an integral constant expression}} \
1911+
// both-note {{cast that performs the conversions of a reinterpret_cast}}
1912+
const unsigned char u8s[] = "hi";
1913+
static_assert(__builtin_wcslen((const wchar_t *)u8s) == 2); // both-error {{static assertion expression is not an integral constant expression}} \
1914+
// both-note {{cast that performs the conversions of a reinterpret_cast}}
1915+
static_assert(__builtin_wcslen(L"x") == 1);
1916+
1917+
}

0 commit comments

Comments
 (0)