From: Matt Beaumont-Gay Date: Fri, 5 Aug 2011 00:22:34 +0000 (+0000) Subject: Extend memset/memcpy/memmove checking to include memcmp X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cc2f30c4ed7770b6005bd55b529a55c1fcc250fc;p=clang Extend memset/memcpy/memmove checking to include memcmp git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@136950 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index c08df35dbb..5363b50368 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -5992,16 +5992,16 @@ private: bool isPrintf); /// \brief Enumeration used to describe which of the memory setting or copying - /// functions is being checked by \c CheckMemsetcpymoveArguments(). + /// functions is being checked by \c CheckMemaccessArguments(). enum CheckedMemoryFunction { CMF_Memset, CMF_Memcpy, - CMF_Memmove + CMF_Memmove, + CMF_Memcmp }; - void CheckMemsetcpymoveArguments(const CallExpr *Call, - CheckedMemoryFunction CMF, - IdentifierInfo *FnName); + void CheckMemaccessArguments(const CallExpr *Call, CheckedMemoryFunction CMF, + IdentifierInfo *FnName); void CheckReturnStackAddr(Expr *RetValExp, QualType lhsType, SourceLocation ReturnLoc); diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 81ae7b3afb..af6141e3ae 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -319,7 +319,7 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) { TheCall->getCallee()->getLocStart()); } - // Memset/memcpy/memmove handling + // Memset/memcpy/memmove/memcmp handling int CMF = -1; switch (FDecl->getBuiltinID()) { case Builtin::BI__builtin_memset: @@ -340,6 +340,10 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) { CMF = CMF_Memmove; break; + case Builtin::BI__builtin_memcmp: + CMF = CMF_Memcmp; + break; + default: if (FDecl->getLinkage() == ExternalLinkage && (!getLangOptions().CPlusPlus || FDecl->isExternC())) { @@ -349,12 +353,14 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) { CMF = CMF_Memcpy; else if (FnInfo->isStr("memmove")) CMF = CMF_Memmove; + else if (FnInfo->isStr("memcmp")) + CMF = CMF_Memcmp; } break; } if (CMF != -1) - CheckMemsetcpymoveArguments(TheCall, CheckedMemoryFunction(CMF), FnInfo); + CheckMemaccessArguments(TheCall, CheckedMemoryFunction(CMF), FnInfo); return false; } @@ -1881,12 +1887,13 @@ static QualType getSizeOfArgType(const Expr* E) { /// \brief Check for dangerous or invalid arguments to memset(). /// /// This issues warnings on known problematic, dangerous or unspecified -/// arguments to the standard 'memset', 'memcpy', and 'memmove' function calls. +/// arguments to the standard 'memset', 'memcpy', 'memmove', and 'memcmp' +/// function calls. /// /// \param Call The call expression to diagnose. -void Sema::CheckMemsetcpymoveArguments(const CallExpr *Call, - CheckedMemoryFunction CMF, - IdentifierInfo *FnName) { +void Sema::CheckMemaccessArguments(const CallExpr *Call, + CheckedMemoryFunction CMF, + IdentifierInfo *FnName) { // It is possible to have a non-standard definition of memset. Validate // we have enough arguments, and if not, abort further checking. if (Call->getNumArgs() < 3) diff --git a/test/SemaCXX/warn-memset-bad-sizeof.cpp b/test/SemaCXX/warn-memset-bad-sizeof.cpp index 90ac50472e..f4876ab442 100644 --- a/test/SemaCXX/warn-memset-bad-sizeof.cpp +++ b/test/SemaCXX/warn-memset-bad-sizeof.cpp @@ -3,6 +3,7 @@ extern "C" void *memset(void *, int, unsigned); extern "C" void *memmove(void *s1, const void *s2, unsigned n); extern "C" void *memcpy(void *s1, const void *s2, unsigned n); +extern "C" void *memcmp(void *s1, const void *s2, unsigned n); struct S {int a, b, c, d;}; typedef S* PS; @@ -51,6 +52,11 @@ void f(Mat m, const Foo& const_foo, char *buffer) { memcpy(0, &s, sizeof(&s)); // \ // expected-warning {{argument to 'sizeof' in 'memcpy' call is the same expression as the source}} + memmove(ps, 0, sizeof(ps)); // \ + // expected-warning {{argument to 'sizeof' in 'memmove' call is the same expression as the destination}} + memcmp(ps, 0, sizeof(ps)); // \ + // expected-warning {{argument to 'sizeof' in 'memcmp' call is the same expression as the destination}} + /* Shouldn't warn */ memset((void*)&s, 0, sizeof(&s)); memset(&s, 0, sizeof(s)); @@ -99,3 +105,10 @@ void f(Mat m, const Foo& const_foo, char *buffer) { memcpy(&foo, &arr, sizeof(Foo)); memcpy(&arr, &foo, sizeof(Foo)); } + +namespace ns { +void memset(void* s, char c, int n); +void f(int* i) { + memset(i, 0, sizeof(i)); +} +}