https://github.com/Ayush3941 updated https://github.com/llvm/llvm-project/pull/177891
>From 7679af9795c8a9769e4e2a298ca4ed9db5183ee8 Mon Sep 17 00:00:00 2001 From: Ayush3941 <[email protected]> Date: Sun, 25 Jan 2026 22:00:57 -0500 Subject: [PATCH 1/3] [clang][bytecode] Avoid crash in constexpr wcslen on invalid argument type --- clang/lib/AST/ByteCode/InterpBuiltin.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index d668fa118d3b9..e2517730e81ca 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -367,10 +367,18 @@ static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC, unsigned ElemSize = StrPtr.getFieldDesc()->getElemSize(); if (ID == Builtin::BI__builtin_wcslen || ID == Builtin::BIwcslen) { - [[maybe_unused]] const ASTContext &AC = S.getASTContext(); - assert(ElemSize == AC.getTypeSizeInChars(AC.getWCharType()).getQuantity()); + const ASTContext &AC = S.getASTContext(); + unsigned WCharSize = AC.getTypeSizeInChars(AC.getWCharType()).getQuantity(); + if (ElemSize != WCharSize) { + if (S.diagnosing()) { + // a dedicated diagnostic + diagnoseNonConstexprBuiltin(S, OpPC, ID); + } + return false; + } } + size_t Len = 0; for (size_t I = StrPtr.getIndex();; ++I, ++Len) { const Pointer &ElemPtr = StrPtr.atIndex(I); >From f54011c559787cb9e34c596739cdd54c86cee826 Mon Sep 17 00:00:00 2001 From: Ayush3941 <[email protected]> Date: Mon, 26 Jan 2026 05:28:07 -0500 Subject: [PATCH 2/3] [clang][bytecode] Added Test file to Avoid crash in constexpr wcslen on invalid argument type --- clang/lib/AST/ByteCode/InterpBuiltin.cpp | 4 ---- .../AST/ByteCode/interp_builtin_wclen.cpp | 24 +++++++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 clang/test/AST/ByteCode/interp_builtin_wclen.cpp diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index e2517730e81ca..69a9381615d52 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -370,10 +370,6 @@ static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC, const ASTContext &AC = S.getASTContext(); unsigned WCharSize = AC.getTypeSizeInChars(AC.getWCharType()).getQuantity(); if (ElemSize != WCharSize) { - if (S.diagnosing()) { - // a dedicated diagnostic - diagnoseNonConstexprBuiltin(S, OpPC, ID); - } return false; } } diff --git a/clang/test/AST/ByteCode/interp_builtin_wclen.cpp b/clang/test/AST/ByteCode/interp_builtin_wclen.cpp new file mode 100644 index 0000000000000..bc8adbd385094 --- /dev/null +++ b/clang/test/AST/ByteCode/interp_builtin_wclen.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -std=c++23 -fexperimental-new-constant-interpreter -verify=expected,both %s +// RUN: %clang_cc1 -std=c++23 -verify=ref,both %s + +namespace WcslenInvalidArg { + + // 1) Narrow string literal passed to wcslen builtin: hard error in C++. + static_assert(__builtin_wcslen("x") == 'x'); + // both-error@-1 {{cannot initialize a parameter of type 'const wchar_t *' with an lvalue of type 'const char[2]'}} + + // 2) Forced cast: should not crash, but not a constant expression. + static_assert(__builtin_wcslen((const wchar_t *)"x") == 1); + // both-error@-1 {{static assertion expression is not an integral constant expression}} + // both-note@-2 {{cast that performs the conversions of a reinterpret_cast}} + + // 3) Forced cast from unsigned char*. + const unsigned char u8s[] = "hi"; + static_assert(__builtin_wcslen((const wchar_t *)u8s) == 2); + // both-error@-1 {{static assertion expression is not an integral constant expression}} + // both-note@-2 {{cast that performs the conversions of a reinterpret_cast}} + + // 4) Correct wide string usage should constant-fold. + static_assert(__builtin_wcslen(L"x") == 1); + +} // namespace WcslenInvalidArg >From 2d16d9af7f079aec7d979f0b89a2e03961480edc Mon Sep 17 00:00:00 2001 From: Ayush3941 <[email protected]> Date: Mon, 26 Jan 2026 05:55:07 -0500 Subject: [PATCH 3/3] [clang][bytecode] Added Test file in clang/test/AST/ByteCode/builtin-functions.cpp to Avoid crash in constexpr wcslen on invalid argument type --- clang/test/AST/ByteCode/builtin-functions.cpp | 22 +++++++++++++++++ .../AST/ByteCode/interp_builtin_wclen.cpp | 24 ------------------- 2 files changed, 22 insertions(+), 24 deletions(-) delete mode 100644 clang/test/AST/ByteCode/interp_builtin_wclen.cpp diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp b/clang/test/AST/ByteCode/builtin-functions.cpp index 116d6aef8350a..1e0ea4ec60021 100644 --- a/clang/test/AST/ByteCode/builtin-functions.cpp +++ b/clang/test/AST/ByteCode/builtin-functions.cpp @@ -1903,3 +1903,25 @@ namespace NonBlockPointerStore { void foo(void) { a *= __builtin_sadd_overflow(1, 2, 0); } void foo2(void) { a *= __builtin_addc(1, 2, 0, 0); } } + +namespace WcslenInvalidArg { + + // 1) Narrow string literal passed to wcslen builtin: hard error in C++. + static_assert(__builtin_wcslen("x") == 'x'); + // both-error@-1 {{cannot initialize a parameter of type 'const wchar_t *' with an lvalue of type 'const char[2]'}} + + // 2) Forced cast: should not crash, but not a constant expression. + static_assert(__builtin_wcslen((const wchar_t *)"x") == 1); + // both-error@-1 {{static assertion expression is not an integral constant expression}} + // both-note@-2 {{cast that performs the conversions of a reinterpret_cast}} + + // 3) Forced cast from unsigned char*. + const unsigned char u8s[] = "hi"; + static_assert(__builtin_wcslen((const wchar_t *)u8s) == 2); + // both-error@-1 {{static assertion expression is not an integral constant expression}} + // both-note@-2 {{cast that performs the conversions of a reinterpret_cast}} + + // 4) Correct wide string usage should constant-fold. + static_assert(__builtin_wcslen(L"x") == 1); + +} // namespace WcslenInvalidArg diff --git a/clang/test/AST/ByteCode/interp_builtin_wclen.cpp b/clang/test/AST/ByteCode/interp_builtin_wclen.cpp deleted file mode 100644 index bc8adbd385094..0000000000000 --- a/clang/test/AST/ByteCode/interp_builtin_wclen.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// RUN: %clang_cc1 -std=c++23 -fexperimental-new-constant-interpreter -verify=expected,both %s -// RUN: %clang_cc1 -std=c++23 -verify=ref,both %s - -namespace WcslenInvalidArg { - - // 1) Narrow string literal passed to wcslen builtin: hard error in C++. - static_assert(__builtin_wcslen("x") == 'x'); - // both-error@-1 {{cannot initialize a parameter of type 'const wchar_t *' with an lvalue of type 'const char[2]'}} - - // 2) Forced cast: should not crash, but not a constant expression. - static_assert(__builtin_wcslen((const wchar_t *)"x") == 1); - // both-error@-1 {{static assertion expression is not an integral constant expression}} - // both-note@-2 {{cast that performs the conversions of a reinterpret_cast}} - - // 3) Forced cast from unsigned char*. - const unsigned char u8s[] = "hi"; - static_assert(__builtin_wcslen((const wchar_t *)u8s) == 2); - // both-error@-1 {{static assertion expression is not an integral constant expression}} - // both-note@-2 {{cast that performs the conversions of a reinterpret_cast}} - - // 4) Correct wide string usage should constant-fold. - static_assert(__builtin_wcslen(L"x") == 1); - -} // namespace WcslenInvalidArg _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
