mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-28 04:56:06 +00:00
[analyzer] Fix "sprintf" parameter modeling in CStringChecker
`CE->getCalleeDecl()` returns `VarDecl` if the callee is actually a function pointer variable. Consequently, calling `getAsFunction()` will return null. To workaround the case, we should use the `CallEvent::parameters()`, which will internally recover the function being called and do the right thing. Fixes #74269 Depends on "[analyzer][NFC] Prefer CallEvent over CallExpr in APIs"
This commit is contained in:
parent
d1856b2f18
commit
a49cf6c14a
@ -1115,6 +1115,9 @@ Crash and bug fixes
|
||||
`#59493 <https://github.com/llvm/llvm-project/issues/59493>`_,
|
||||
`#54533 <https://github.com/llvm/llvm-project/issues/54533>`_)
|
||||
|
||||
- Fixed an ``alpha.unix.cstring`` crash on variadic functions.
|
||||
(`#74269 <https://github.com/llvm/llvm-project/issues/74269>`_)
|
||||
|
||||
- Fix false positive in mutation check when using pointer to member function.
|
||||
(`#66204 <https://github.com/llvm/llvm-project/issues/66204>`_)
|
||||
|
||||
|
@ -2487,8 +2487,7 @@ void CStringChecker::evalSprintfCommon(CheckerContext &C, const CallEvent &Call,
|
||||
const auto *CE = cast<CallExpr>(Call.getOriginExpr());
|
||||
DestinationArgExpr Dest = {{Call.getArgExpr(0), 0}};
|
||||
|
||||
// FIXME: We should use `Call.parameters().size()` here.
|
||||
const auto NumParams = CE->getCalleeDecl()->getAsFunction()->getNumParams();
|
||||
const auto NumParams = Call.parameters().size();
|
||||
assert(CE->getNumArgs() >= NumParams);
|
||||
|
||||
const auto AllArguments =
|
||||
|
@ -1,6 +1,4 @@
|
||||
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix -verify %s
|
||||
|
||||
// expected-no-diagnostics
|
||||
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix,debug.ExprInspection -verify %s
|
||||
|
||||
// Test functions that are called "memcpy" but aren't the memcpy
|
||||
// we're looking for. Unfortunately, this test cannot be put into
|
||||
@ -9,6 +7,11 @@
|
||||
typedef __typeof(sizeof(int)) size_t;
|
||||
void *memcpy(void *, const void *, size_t);
|
||||
|
||||
int sprintf(char *str, const char *format, ...);
|
||||
int snprintf(char *str, size_t size, const char *format, ...);
|
||||
|
||||
void clang_analyzer_warnIfReached();
|
||||
|
||||
struct S {
|
||||
static S s1, s2;
|
||||
|
||||
@ -26,3 +29,19 @@ void *memcpy(void *, const S &, size_t);
|
||||
void test_out_of_class_weird_memcpy() {
|
||||
memcpy(&S::s1, S::s2, 1); // no-crash
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void log(const char* fmt, const Args&... args) {
|
||||
char buf[100] = {};
|
||||
auto f = snprintf;
|
||||
auto g = sprintf;
|
||||
int n = 0;
|
||||
n += f(buf, 99, fmt, args...); // no-crash: The CalleeDecl is a VarDecl, but it's okay.
|
||||
n += g(buf, fmt, args...); // no-crash: Same.
|
||||
(void)n;
|
||||
clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
|
||||
}
|
||||
|
||||
void test_gh_74269_no_crash() {
|
||||
log("%d", 1);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user