Skip to content

Commit 33b6b67

Browse files
committed
[clang] Fix crash in __builtin_strncmp and other related builtin functions
The implementation of __builtin_strncmp and other related builtins function use getExtValue() to evaluate the size argument. This can cause a crash when the value does not fit into an int64_t value, which is can be expected since the type of the argument is size_t. The fix is to switch to using getZExtValue(). This fixes: #64876 Differential Revision: https://reviews.llvm.org/D158557
1 parent f0f53cb commit 33b6b67

File tree

4 files changed

+42
-2
lines changed

4 files changed

+42
-2
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,9 @@ Bug Fixes in This Version
179179
- Clang now prints unnamed members in diagnostic messages instead of giving an
180180
empty ''. Fixes
181181
(`#63759 <https://github.com/llvm/llvm-project/issues/63759>`_)
182+
- Fix crash in __builtin_strncmp and related builtins when the size value
183+
exceeded the maximum value representable by int64_t. Fixes
184+
(`#64876 <https://github.com/llvm/llvm-project/issues/64876>`_)
182185

183186
Bug Fixes to Compiler Builtins
184187
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/AST/ExprConstant.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9361,7 +9361,7 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
93619361
APSInt N;
93629362
if (!EvaluateInteger(E->getArg(2), N, Info))
93639363
return false;
9364-
MaxLength = N.getExtValue();
9364+
MaxLength = N.getZExtValue();
93659365
}
93669366
// We cannot find the value if there are no candidates to match against.
93679367
if (MaxLength == 0u)
@@ -12385,7 +12385,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
1238512385
APSInt N;
1238612386
if (!EvaluateInteger(E->getArg(2), N, Info))
1238712387
return false;
12388-
MaxLength = N.getExtValue();
12388+
MaxLength = N.getZExtValue();
1238912389
}
1239012390

1239112391
// Empty substrings compare equal by definition.

clang/test/CodeGen/gh64876.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: %clang_cc1 -triple x86_64 -S -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
2+
3+
void f(const char* C, const wchar_t *WC) {
4+
int x1 = __builtin_strncmp(C, "b", 0xffffffffffffffff);
5+
// CHECK: {{.*}}= call i32 @strncmp{{.*}}i64 noundef -1
6+
int x2 = __builtin_memcmp(C, "b", 0xffffffffffffffff);
7+
// CHECK: {{.*}}= call i32 @memcmp{{.*}}i64 noundef -1
8+
int x3 = __builtin_bcmp(C, "b", 0xffffffffffffffff);
9+
// CHECK: {{.*}}= call i32 @bcmp{{.*}}i64 noundef -1
10+
int x4 = __builtin_wmemcmp(WC, L"b", 0xffffffffffffffff);
11+
// CHECK: {{.*}}= call i32 @wmemcmp{{.*}}i64 noundef -1
12+
auto x5 = __builtin_memchr(C, (int)'a', 0xffffffffffffffff);
13+
// CHECK: {{.*}}= call ptr @memchr{{.*}}i64 noundef -1
14+
auto x6 = __builtin_wmemchr(WC, (int)'a', 0xffffffffffffffff);
15+
// CHECK: {{.*}}= call ptr @wmemchr{{.*}}i64 noundef -1
16+
}

clang/test/SemaCXX/constexpr-string.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,3 +676,24 @@ namespace MemcpyEtc {
676676
}
677677
static_assert(test_address_of_incomplete_struct_type()); // expected-error {{constant}} expected-note {{in call}}
678678
}
679+
680+
#pragma clang diagnostic push
681+
#pragma clang diagnostic ignored "-Wconstant-conversion"
682+
namespace GH64876 {
683+
void f() {
684+
__builtin_strncmp(0, 0, 0xffffffffffffffff);
685+
__builtin_memcmp(0, 0, 0xffffffffffffffff);
686+
__builtin_bcmp(0, 0, 0xffffffffffffffff);
687+
__builtin_wmemcmp(0, 0, 0xffffffffffffffff);
688+
__builtin_memchr((const void*)0, 1, 0xffffffffffffffff);
689+
__builtin_wmemchr((const wchar_t*)0, 1, 0xffffffffffffffff);
690+
691+
__builtin_strncmp(0, 0, -511LL);
692+
__builtin_memcmp(0, 0, -511LL);
693+
__builtin_bcmp(0, 0, -511LL);
694+
__builtin_wmemcmp(0, 0, -511LL);
695+
__builtin_memchr((const void*)0, 1, -511LL);
696+
__builtin_wmemchr((const wchar_t*)0, 1, -511LL);
697+
}
698+
}
699+
#pragma clang diagnostic pop

0 commit comments

Comments
 (0)