From 490c7faa9d039496347d1bfd3c7586a34fca7fe5 Mon Sep 17 00:00:00 2001 From: serge-sans-paille Date: Wed, 13 Nov 2019 23:19:56 +0100 Subject: [PATCH 1/3] Setup default build action for llvm --- .github/workflows/llvm.yml | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 .github/workflows/llvm.yml diff --git a/.github/workflows/llvm.yml b/.github/workflows/llvm.yml new file mode 100644 index 0000000000000..c18b3c27d547c --- /dev/null +++ b/.github/workflows/llvm.yml @@ -0,0 +1,34 @@ +name: CI + +on: [push] + +jobs: + build_llvm: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: + - ubuntu-latest + - windows-latest + - macOS-latest + cmake_args: + - "" + steps: + - name: Setup Windows + if: startsWith(matrix.os, 'windows') + uses: tstellar/actions/setup-windows@master + with: + arch: amd64 + - uses: actions/checkout@v1 + with: + fetch-depth: 1 + - name: Install Ninja + uses: tstellar/actions/install-ninja@master + with: + os: ${{ runner.os }} + - name: Test LLVM + uses: tstellar/actions/build-test-llvm-project@master + with: + cmake_args: -G Ninja -DCMAKE_BUILD_TYPE=Release ${{ matrix.cmake_args }} + os: ${{ runner.os }} From 39951299f5c328065a05705219358b8cbc3d0d88 Mon Sep 17 00:00:00 2001 From: serge-sans-paille Date: Thu, 5 Dec 2019 20:54:46 +0100 Subject: [PATCH 2/3] Update cmake flags --- .github/workflows/llvm.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/llvm.yml b/.github/workflows/llvm.yml index c18b3c27d547c..e5541162064e0 100644 --- a/.github/workflows/llvm.yml +++ b/.github/workflows/llvm.yml @@ -13,7 +13,7 @@ jobs: - windows-latest - macOS-latest cmake_args: - - "" + - "-DLLVM_ENABLE_PROJECTS='clang'" steps: - name: Setup Windows if: startsWith(matrix.os, 'windows') From 32c8d139cde3abaf22ee514c0c94397d15bb5737 Mon Sep 17 00:00:00 2001 From: serge-sans-paille Date: Wed, 11 Dec 2019 21:30:10 +0100 Subject: [PATCH 3/3] Improve support of GNU mempcpy - Lower to the memcpy intrinsic - Raise warnings when size/bounds are known --- clang/include/clang/Basic/Builtins.def | 1 + clang/lib/AST/Decl.cpp | 7 +++++++ clang/lib/CodeGen/CGBuiltin.cpp | 10 ++++++++-- clang/lib/Sema/SemaChecking.cpp | 7 +++++-- clang/test/Analysis/bstring.c | 6 ++++++ clang/test/CodeGen/mempcpy-libcall.c | 12 ++++++++++++ 6 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 clang/test/CodeGen/mempcpy-libcall.c diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def index 8a102744700f6..e7a9e1531a96a 100644 --- a/clang/include/clang/Basic/Builtins.def +++ b/clang/include/clang/Basic/Builtins.def @@ -984,6 +984,7 @@ LIBBUILTIN(longjmp, "vJi", "fr", "setjmp.h", ALL_LANGUAGES) LIBBUILTIN(alloca, "v*z", "f", "stdlib.h", ALL_GNU_LANGUAGES) // POSIX string.h LIBBUILTIN(memccpy, "v*v*vC*iz", "f", "string.h", ALL_GNU_LANGUAGES) +LIBBUILTIN(mempcpy, "v*v*vC*z", "f", "string.h", ALL_GNU_LANGUAGES) LIBBUILTIN(stpcpy, "c*c*cC*", "f", "string.h", ALL_GNU_LANGUAGES) LIBBUILTIN(stpncpy, "c*c*cC*z", "f", "string.h", ALL_GNU_LANGUAGES) LIBBUILTIN(strdup, "c*cC*", "f", "string.h", ALL_GNU_LANGUAGES) diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 9f09898a957be..50fc69f5436ec 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -3866,6 +3866,11 @@ unsigned FunctionDecl::getMemoryFunctionKind() const { case Builtin::BImemcpy: return Builtin::BImemcpy; + case Builtin::BI__builtin_mempcpy: + case Builtin::BI__builtin___mempcpy_chk: + case Builtin::BImempcpy: + return Builtin::BImempcpy; + case Builtin::BI__builtin_memmove: case Builtin::BI__builtin___memmove_chk: case Builtin::BImemmove: @@ -3923,6 +3928,8 @@ unsigned FunctionDecl::getMemoryFunctionKind() const { return Builtin::BImemset; else if (FnInfo->isStr("memcpy")) return Builtin::BImemcpy; + else if (FnInfo->isStr("mempcpy")) + return Builtin::BImempcpy; else if (FnInfo->isStr("memmove")) return Builtin::BImemmove; else if (FnInfo->isStr("memcmp")) diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 8a53739626e12..0e914a9cd4ac2 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -2506,7 +2506,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, return RValue::get(nullptr); } case Builtin::BImemcpy: - case Builtin::BI__builtin_memcpy: { + case Builtin::BI__builtin_memcpy: + case Builtin::BImempcpy: + case Builtin::BI__builtin_mempcpy: { Address Dest = EmitPointerWithAlignment(E->getArg(0)); Address Src = EmitPointerWithAlignment(E->getArg(1)); Value *SizeVal = EmitScalarExpr(E->getArg(2)); @@ -2515,7 +2517,11 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, EmitNonNullArgCheck(RValue::get(Src.getPointer()), E->getArg(1)->getType(), E->getArg(1)->getExprLoc(), FD, 1); Builder.CreateMemCpy(Dest, Src, SizeVal, false); - return RValue::get(Dest.getPointer()); + if (BuiltinID == Builtin::BImempcpy || + BuiltinID == Builtin::BI__builtin_mempcpy) + return RValue::get(Builder.CreateInBoundsGEP(Dest.getPointer(), SizeVal)); + else + return RValue::get(Dest.getPointer()); } case Builtin::BI__builtin_char_memchr: diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index aff63aef29349..4d06fa9464d5c 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -340,7 +340,8 @@ void Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD, case Builtin::BI__builtin___strncat_chk: case Builtin::BI__builtin___strncpy_chk: case Builtin::BI__builtin___stpncpy_chk: - case Builtin::BI__builtin___memccpy_chk: { + case Builtin::BI__builtin___memccpy_chk: + case Builtin::BI__builtin___mempcpy_chk: { DiagID = diag::warn_builtin_chk_overflow; IsChkVariant = true; SizeIndex = TheCall->getNumArgs() - 2; @@ -379,7 +380,9 @@ void Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD, case Builtin::BImemmove: case Builtin::BI__builtin_memmove: case Builtin::BImemset: - case Builtin::BI__builtin_memset: { + case Builtin::BI__builtin_memset: + case Builtin::BImempcpy: + case Builtin::BI__builtin_mempcpy: { DiagID = diag::warn_fortify_source_overflow; SizeIndex = TheCall->getNumArgs() - 1; ObjectIndex = 0; diff --git a/clang/test/Analysis/bstring.c b/clang/test/Analysis/bstring.c index beabb0f0241e4..2e969c405d937 100644 --- a/clang/test/Analysis/bstring.c +++ b/clang/test/Analysis/bstring.c @@ -222,6 +222,9 @@ void mempcpy2 () { char dst[1]; mempcpy(dst, src, 4); // expected-warning{{Memory copy function overflows destination buffer}} +#ifndef VARIANT +// expected-warning@-2{{'mempcpy' will always overflow; destination buffer has size 1, but size argument is 4}} +#endif } void mempcpy3 () { @@ -243,6 +246,9 @@ void mempcpy5() { char dst[3]; mempcpy(dst+2, src+2, 2); // expected-warning{{Memory copy function overflows destination buffer}} +#ifndef VARIANT +// expected-warning@-2{{'mempcpy' will always overflow; destination buffer has size 1, but size argument is 2}} +#endif } void mempcpy6() { diff --git a/clang/test/CodeGen/mempcpy-libcall.c b/clang/test/CodeGen/mempcpy-libcall.c new file mode 100644 index 0000000000000..b88f494f164df --- /dev/null +++ b/clang/test/CodeGen/mempcpy-libcall.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -emit-llvm < %s| FileCheck %s + +typedef __SIZE_TYPE__ size_t; + +void *mempcpy(void *, void const *, size_t); + +char *test(char *d, char *s, size_t n) { + // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}} %[[REG1:[^ ]+]], i8* {{.*}} %1, i64 %[[REG2:[^ ]+]], i1 false) + // CHECK-NEXT: %[[REGr:[^ ]+]] = getelementptr inbounds i8, i8* %[[REG1]], i64 %[[REG2]] + // CHECK-NEXT: ret i8* %[[REGr]] + return mempcpy(d, s, n); +}