diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index f1539f2733298d..b1bc98e93a2799 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -930,9 +930,23 @@ SVal CStringChecker::getCStringLength(CheckerContext &C, ProgramStateRef &state, const StringLiteral *strLit = cast(MR)->getStringLiteral(); return svalBuilder.makeIntVal(strLit->getLength(), sizeTy); } + case MemRegion::NonParamVarRegionKind: { + // If we have a global constant with a string literal initializer, + // compute the initializer's length. + const VarDecl *Decl = cast(MR)->getDecl(); + if (Decl->getType().isConstQualified() && Decl->hasGlobalStorage()) { + if (const Expr *Init = Decl->getInit()) { + if (auto *StrLit = dyn_cast(Init)) { + SValBuilder &SvalBuilder = C.getSValBuilder(); + QualType SizeTy = SvalBuilder.getContext().getSizeType(); + return SvalBuilder.makeIntVal(StrLit->getLength(), SizeTy); + } + } + } + [[fallthrough]]; + } case MemRegion::SymbolicRegionKind: case MemRegion::AllocaRegionKind: - case MemRegion::NonParamVarRegionKind: case MemRegion::ParamVarRegionKind: case MemRegion::FieldRegionKind: case MemRegion::ObjCIvarRegionKind: diff --git a/clang/test/Analysis/string.c b/clang/test/Analysis/string.c index d369ee9f7d854a..d47de9db8228e5 100644 --- a/clang/test/Analysis/string.c +++ b/clang/test/Analysis/string.c @@ -97,6 +97,29 @@ void strlen_constant2(char x) { clang_analyzer_eval(strlen(a) == 3); // expected-warning{{UNKNOWN}} } +const char *const global_str_ptr = "abcd"; +const char global_str_arr[] = "efgh"; +const char *global_non_const_ptr1 = "ijk"; +char *global_non_const_ptr2 = "lmn"; +char global_non_const_arr[] = "op"; + +void strlen_global_constant_ptr(void) { + clang_analyzer_eval(strlen(global_str_ptr) == 4); // expected-warning{{TRUE}} +} + +void strlen_global_constant_arr(void) { + clang_analyzer_eval(strlen(global_str_arr) == 4); // expected-warning{{TRUE}} +} + +void strlen_global_non_const_ptr(void) { + clang_analyzer_eval(strlen(global_non_const_ptr1) == 3); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(strlen(global_non_const_ptr2) == 3); // expected-warning{{UNKNOWN}} +} + +void strlen_global_non_const_arr(void) { + clang_analyzer_eval(strlen(global_non_const_arr) == 2); // expected-warning{{UNKNOWN}} +} + size_t strlen_null(void) { return strlen(0); // expected-warning{{Null pointer passed as 1st argument to string length function}} }