[clang] [analyzer] Make recognition of hardened __FOO_chk functions explicit (PR #86536)

via cfe-commits cfe-commits at lists.llvm.org
Wed Mar 27 05:00:04 PDT 2024


================
@@ -124,34 +124,45 @@ class CStringChecker : public Checker< eval::Call,
                                      const CallEvent &)>;
 
   CallDescriptionMap<FnCheck> Callbacks = {
-      {{CDM::CLibrary, {"memcpy"}, 3},
+      {{CDM::CLibraryMaybeHardened, {"memcpy"}, 3},
        std::bind(&CStringChecker::evalMemcpy, _1, _2, _3, CK_Regular)},
-      {{CDM::CLibrary, {"wmemcpy"}, 3},
+      {{CDM::CLibraryMaybeHardened, {"wmemcpy"}, 3},
        std::bind(&CStringChecker::evalMemcpy, _1, _2, _3, CK_Wide)},
-      {{CDM::CLibrary, {"mempcpy"}, 3},
+      {{CDM::CLibraryMaybeHardened, {"mempcpy"}, 3},
        std::bind(&CStringChecker::evalMempcpy, _1, _2, _3, CK_Regular)},
-      {{CDM::Unspecified, {"wmempcpy"}, 3},
+      {{CDM::CLibraryMaybeHardened, {"wmempcpy"}, 3},
        std::bind(&CStringChecker::evalMempcpy, _1, _2, _3, CK_Wide)},
       {{CDM::CLibrary, {"memcmp"}, 3},
        std::bind(&CStringChecker::evalMemcmp, _1, _2, _3, CK_Regular)},
       {{CDM::CLibrary, {"wmemcmp"}, 3},
        std::bind(&CStringChecker::evalMemcmp, _1, _2, _3, CK_Wide)},
-      {{CDM::CLibrary, {"memmove"}, 3},
+      {{CDM::CLibraryMaybeHardened, {"memmove"}, 3},
        std::bind(&CStringChecker::evalMemmove, _1, _2, _3, CK_Regular)},
-      {{CDM::CLibrary, {"wmemmove"}, 3},
+      {{CDM::CLibraryMaybeHardened, {"wmemmove"}, 3},
        std::bind(&CStringChecker::evalMemmove, _1, _2, _3, CK_Wide)},
-      {{CDM::CLibrary, {"memset"}, 3}, &CStringChecker::evalMemset},
+      {{CDM::CLibraryMaybeHardened, {"memset"}, 3},
+       &CStringChecker::evalMemset},
       {{CDM::CLibrary, {"explicit_memset"}, 3}, &CStringChecker::evalMemset},
-      {{CDM::CLibrary, {"strcpy"}, 2}, &CStringChecker::evalStrcpy},
-      {{CDM::CLibrary, {"strncpy"}, 3}, &CStringChecker::evalStrncpy},
-      {{CDM::CLibrary, {"stpcpy"}, 2}, &CStringChecker::evalStpcpy},
-      {{CDM::CLibrary, {"strlcpy"}, 3}, &CStringChecker::evalStrlcpy},
-      {{CDM::CLibrary, {"strcat"}, 2}, &CStringChecker::evalStrcat},
-      {{CDM::CLibrary, {"strncat"}, 3}, &CStringChecker::evalStrncat},
-      {{CDM::CLibrary, {"strlcat"}, 3}, &CStringChecker::evalStrlcat},
-      {{CDM::CLibrary, {"strlen"}, 1}, &CStringChecker::evalstrLength},
+      /* FIXME: C23 introduces 'memset_explicit', maybe also model that */
+      {{CDM::CLibraryMaybeHardened, {"strcpy"}, 2},
+       &CStringChecker::evalStrcpy},
+      {{CDM::CLibraryMaybeHardened, {"strncpy"}, 3},
+       &CStringChecker::evalStrncpy},
+      {{CDM::CLibraryMaybeHardened, {"stpcpy"}, 2},
+       &CStringChecker::evalStpcpy},
----------------
NagyDonat wrote:

The mode `CDM::CLibraryMaybeHardened` understands that the hardened variants of the functions may have more arguments/parameters than the value that's encoded in the `CallDescription` (and it can also match the "usual" variants and for them it checks that the arg/param count exactly matches).

For example
```
{CDM::CLibraryMaybeHardened, {"strcpy"}, 2}
```
can match `strcpy(x, y)` (a normal strcpy call, two arguments), `__builtin_strcpy(x, y)` (a non-hardened builtin variant, two arguments), `__strcpy_chk(x, y, z)` (a hardened strcpy call, three arguments); but it doesn't match `strcpy(x, y, z)` (a non-hardened call with more than two arguments) or anything that has less than two arguments.


Note that the hardened variants usually have one additional argument (compared to the "normal" variant), but there are some (IIRC "sprintf" and "snprintf") that get two additional arguments, so I don't check their exact arg/param count and accept any call where the number of args/params is not less than the number of args/params for the original function. (Additional arguments don't disturb the checker, but an unexpectedly missing argument could lead to a checker crash.) This means that the current code would accept `__strcpy_chk(x, y)` and `__strcpy_chk(x, y, z, w)`, which are invalid calls (but I don't think that they would ever appear in real code and they don't cause checker crashes).


https://github.com/llvm/llvm-project/pull/86536


More information about the cfe-commits mailing list