Strlcpy strlcat checks with possible overlaps.
Details
- Reviewers
george.karpenkov NoQ rja - Commits
- rGc19843714c5a: [analyzer] Re-apply r331096 "CStringChecker: Add support for BSD strlcpy()...".
rG1aaf40253050: [analyzer] Revert r331096 "CStringChecker: Add support for BSD strlcpy()...".
rG03283ae9b7ad: [analyzer] CStringChecker: Add support for BSD strlcpy() and strlcat().
rL332303: [analyzer] Re-apply r331096 "CStringChecker: Add support for BSD strlcpy()...".
rC332303: [analyzer] Re-apply r331096 "CStringChecker: Add support for BSD strlcpy()...".
rL331401: [analyzer] Revert r331096 "CStringChecker: Add support for BSD strlcpy()...".
rC331401: [analyzer] Revert r331096 "CStringChecker: Add support for BSD strlcpy()...".
rL331096: [analyzer] CStringChecker: Add support for BSD strlcpy() and strlcat().
rC331096: [analyzer] CStringChecker: Add support for BSD strlcpy() and strlcat().
Diff Detail
- Repository
- rC Clang
Event Timeline
lib/StaticAnalyzer/Checkers/CStringChecker.cpp | ||
---|---|---|
106 | The fact that the regular strcpy/strcat isn't checked for overlaps looks like an omission to me. The difference between strcpy/strcat and strlcpy/strlcat is not in how it handles overlaps. |
Whoops - this isn't quite correct because there's one more difference between strlcpy/strlcat and the standard strcpy/strcat/strncpy/strncat: the return value. After this patch the new functions are modeled as if they return a pointer into the string, which is incorrect and in fact causes crashes.
One of the crashes is on the following code:
int foo(char *d) { char e[1]; return strlcpy(e, d, sizeof(e)) >= sizeof(e); }
...when analyzed as clang -cc1 -w -analyze -analyzer-checker=core,unix repro.c.
David, would you be willing to have a look at this problem?
Also I forgot to add the tests before committing. Sorry!
I reverted this for now. I'm sorry - i would have looked into this myself, but unfortunately there are other important fixes that distract me at the moment.
Yay that was fast, thanks!
Could we have tests for the return value? Like, concatenate a couple of concrete string literals and verify the return value via clang_analyzer_eval().
lib/StaticAnalyzer/Checkers/CStringChecker.cpp | ||
---|---|---|
1485 | This crashes on the old tests for the checker. I guess that's because the normal strcpy() doesn't have three arguments (it counts from 0). |
lib/StaticAnalyzer/Checkers/CStringChecker.cpp | ||
---|---|---|
1485 | True I forgot those cases. |
lib/StaticAnalyzer/Checkers/CStringChecker.cpp | ||
---|---|---|
1560–1566 | One more cornercase where the return value needs to be corrected. It'd be great to de-duplicate this code to avoid similar problems in the future. Test case: int foo(char *dst, const char *src) { return strlcpy(dst, src, 0); // no-crash } |
lib/StaticAnalyzer/Checkers/CStringChecker.cpp | ||
---|---|---|
1560–1566 | Thanks for the hint ! will do a separate "PR". |
This patch seems to cause an assertion failure:
assert.h assertion failed at clang/lib/StaticAnalyzer/Core/SValBuilder.cpp:427 in clang::ento::SVal clang::ento::SValBuilder::evalBinOp(clang::ento::ProgramStateRef, BinaryOperator::Opcode, clang::ento::SVal, clang::ento::SVal, clang::QualType): op == BO_Add
The stack trace is:
__assert_fail
clang::ento::SValBuilder::evalBinOp
clang::ento::SValBuilder::evalEQ
clang::ento::SValBuilder::evalEQ
::CStringChecker::assumeZero
::CStringChecker::checkNonNull
::CStringChecker::evalStrcpyCommon
::CStringChecker::evalStrcpy
::CStringChecker::evalCall
clang::ento::eval::Call::_evalCall
clang::ento::CheckerFn::operator()
clang::ento::CheckerManager::runCheckersForEvalCall
clang::ento::ExprEngine::evalCall
clang::ento::ExprEngine::VisitCallExpr
clang::ento::ExprEngine::Visit
clang::ento::ExprEngine::ProcessStmt
clang::ento::ExprEngine::processCFGElement
clang::ento::CoreEngine::HandlePostStmt
clang::ento::CoreEngine::dispatchWorkItem
clang::ento::CoreEngine::ExecuteWorkList
clang::ento::ExprEngine::ExecuteWorkList
::AnalysisConsumer::ActionExprEngine
::AnalysisConsumer::HandleCode
::AnalysisConsumer::HandleDeclsCallGraph
::AnalysisConsumer::runAnalysisOnTranslationUnit
::AnalysisConsumer::HandleTranslationUnit
I'm trying to reduce a test case.
I was unable to reproduce both FreeBSD and Linux. Plus my changes come after checkNonNull.
I'm not 100% sure this was caused by your patch, but the stack trace looks suspiciously similar to what was changed here. As for not being able to reproduce: do you build Clang with assertions enabled?
I admit I do not due to much longer compilation time, I ll recompile all with and will see tomorrow if I can reproduce.
I was able to reproduce but also with the revision before when it has been reverted (https://github.com/llvm-mirror/clang/commit/262d2570ebab81867b46caa763a79940768d7faa#diff-b75d57d7da174f60bb0c32783975665a)
The fact that the regular strcpy/strcat isn't checked for overlaps looks like an omission to me. The difference between strcpy/strcat and strlcpy/strlcat is not in how it handles overlaps.