From 46ee833c43170e8f8cec7e6c66a2b6b94f65f732 Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Mon, 14 Oct 2024 10:57:22 +0530 Subject: [PATCH 1/2] null-library-function-c --- rules/c/security/null-library-function-c.yml | 187 ++++++++++++++++++ .../null-library-function-c-snapshot.yml | 20 ++ tests/c/null-library-function-c-test.yml | 30 +++ 3 files changed, 237 insertions(+) create mode 100644 rules/c/security/null-library-function-c.yml create mode 100644 tests/__snapshots__/null-library-function-c-snapshot.yml create mode 100644 tests/c/null-library-function-c-test.yml diff --git a/rules/c/security/null-library-function-c.yml b/rules/c/security/null-library-function-c.yml new file mode 100644 index 00000000..8467b3c0 --- /dev/null +++ b/rules/c/security/null-library-function-c.yml @@ -0,0 +1,187 @@ +id: null-library-function-c +language: C +severity: warning +message: >- + The `$SOURCE` function returns NULL on error and this line dereferences + the return value without checking for NULL. +note: >- + [CWE-476] NULL Pointer Dereference. + [REFERENCES] + - https://wiki.sei.cmu.edu/confluence/display/c/EXP34-C.+Do+not+dereference+null+pointers +utils: + MATCH_PATTERN_ONE: + kind: return_statement + has: + stopBy: neighbor + kind: field_expression + has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: "^fgets|::fgets|std::fgets|fopen|::fopen|std::fopen|getenv|::getenv|std::getenv|getgrent|::getgrent|std::getgrent|getgrgid|::getgrgid|std::getgrgid|getgrnam|::getgrnam|std::getgrnam|getlogin|::getlogin|std::getlogin|getpwent|::getpwent|std::getpwent|getpwnam|::getpwnam|std::getpwnam|getpwuid|::getpwuid|std::getpwuid|getpwuuid|::getpwuuid|std::getpwuuid|gets|::gets|std::gets|inet_ntop|::inet_ntop|std::inet_ntop|realpath|::realpath|std::realpath|tempnam|::tempnam|std::tempnam|tmpfile|::tmpfile|std::tmpfile|tmpnam|::tmpnam|std::tmpnam|memchr|::memchr|std::memchr|strcasestr_l|::strcasestr_l|std::strcasestr_l|strcasestr|::strcasestr|std::strcasestr|strchr|::strchr|std::strchr|strnstr|::strnstr|std::strnstr|strpbrk|::strpbrk|std::strpbrk|strrchr|::strrchr|std::strrchr|strstr|::strstr|std::strstr|strtok_r|::strtok_r|std::strtok_r|strtok|::strtok|std::strtok$" + + MATCH_PATTERN_THREE: + kind: call_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: "^atof|::atof|std::atof|atoi|::atoi|std::atoi|atol_l|::atol_l|std::atol_l|atol|::atol|std::atol|atoll_l|::atoll_l|std::atoll_l|atoll|::atoll|std::atoll|getc|::getc|std::getc|fprintf|::fprintf|std::fprintf|fgetpos|::fgetpos|std::fgetpos|fseek|::fseek|std::fseek|fseeko|::fseeko|std::fseeko|fsetpos|::fsetpos|std::fsetpos|ftell|::ftell|std::ftell|ftello|::ftello|std::ftello|rewind|::rewind|std::rewind|strlen|::strlen|std::strlen|strtoimax|::strtoimax|std::strtoimax|strtod|::strtod|std::strtod|strtol|::strtol|std::strtol|strtoul|::strtoul|std::strtoul|strtoll|::strtoll|std::strtoll|strtoq|::strtoq|std::strtoq$" + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: "^fgets|::fgets|std::fgets|fopen|::fopen|std::fopen|getenv|::getenv|std::getenv|getgrent|::getgrent|std::getgrent|getgrgid|::getgrgid|std::getgrgid|getgrnam|::getgrnam|std::getgrnam|getlogin|::getlogin|std::getlogin|getpwent|::getpwent|std::getpwent|getpwnam|::getpwnam|std::getpwnam|getpwuid|::getpwuid|std::getpwuid|getpwuuid|::getpwuuid|std::getpwuuid|gets|::gets|std::gets|inet_ntop|::inet_ntop|std::inet_ntop|realpath|::realpath|std::realpath|tempnam|::tempnam|std::tempnam|tmpfile|::tmpfile|std::tmpfile|tmpnam|::tmpnam|std::tmpnam|memchr|::memchr|std::memchr|strcasestr_l|::strcasestr_l|std::strcasestr_l|strcasestr|::strcasestr|std::strcasestr|strchr|::strchr|std::strchr|strnstr|::strnstr|std::strnstr|strpbrk|::strpbrk|std::strpbrk|strrchr|::strrchr|std::strrchr|strstr|::strstr|std::strstr|strtok_r|::strtok_r|std::strtok_r|strtok|::strtok|std::strtok$" + - has: + stopBy: end + kind: argument_list + + MATCH_PATTERN_FOUR: + kind: call_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: "^atof|::atof|std::atof|atoi|::atoi|std::atoi|atol_l|::atol_l|std::atol_l|atol|::atol|std::atol|atoll_l|::atoll_l|std::atoll_l|atoll|::atoll|std::atoll|getc|::getc|std::getc|fprintf|::fprintf|std::fprintf|fgetpos|::fgetpos|std::fgetpos|fseek|::fseek|std::fseek|fseeko|::fseeko|std::fseeko|fsetpos|::fsetpos|std::fsetpos|ftell|::ftell|std::ftell|ftello|::ftello|std::ftello|rewind|::rewind|std::rewind|strlen|::strlen|std::strlen|strtoimax|::strtoimax|std::strtoimax|strtod|::strtod|std::strtod|strtol|::strtol|std::strtol|strtoul|::strtoul|std::strtoul|strtoll|::strtoll|std::strtoll|strtoq|::strtoq|std::strtoq$" + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: neighbor + kind: assignment_expression + all: + - has: + stopBy: neighbor + kind: identifier + - has: + stopBy: neighbor + regex: "=" + - has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: "^fgets|::fgets|std::fgets|fopen|::fopen|std::fopen|getenv|::getenv|std::getenv|getgrent|::getgrent|std::getgrent|getgrgid|::getgrgid|std::getgrgid|getgrnam|::getgrnam|std::getgrnam|getlogin|::getlogin|std::getlogin|getpwent|::getpwent|std::getpwent|getpwnam|::getpwnam|std::getpwnam|getpwuid|::getpwuid|std::getpwuid|getpwuuid|::getpwuuid|std::getpwuuid|gets|::gets|std::gets|inet_ntop|::inet_ntop|std::inet_ntop|realpath|::realpath|std::realpath|tempnam|::tempnam|std::tempnam|tmpfile|::tmpfile|std::tmpfile|tmpnam|::tmpnam|std::tmpnam|memchr|::memchr|std::memchr|strcasestr_l|::strcasestr_l|std::strcasestr_l|strcasestr|::strcasestr|std::strcasestr|strchr|::strchr|std::strchr|strnstr|::strnstr|std::strnstr|strpbrk|::strpbrk|std::strpbrk|strrchr|::strrchr|std::strrchr|strstr|::strstr|std::strstr|strtok_r|::strtok_r|std::strtok_r|strtok|::strtok|std::strtok$" + - has: + stopBy: neighbor + kind: argument_list + + MATCH_PATTERN_FIVE: + kind: call_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: "^bcopy|::bcopy|std::bcopy|memccpy|::memccpy|std::memccpy|memcpy|::memcpy|std::memcpy|memmove|::memmove|std::memmove|stpncpy|::stpncpy|std::stpncpy|strcat|::strcat|std::strcat|strcpy|::strcpy|std::strcpy|strcpy|::strcpy|std::strcpy|strlcat|::strlcat|std::strlcat|strlcpy|::strlcpy|std::strlcpy|strncat|::strncat|std::strncat|strpcpy|::strpcpy|std::strpcpy|wcpcpy|::wcpcpy|std::wcpcpy|wcpncpy|::wcpncpy|std::wcpncpy$" + - has: + stopBy: neighbor + kind: argument_list + all: + - has: + stopBy: neighbor + pattern: $$$ + - has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: "^fgets|::fgets|std::fgets|fopen|::fopen|std::fopen|getenv|::getenv|std::getenv|getgrent|::getgrent|std::getgrent|getgrgid|::getgrgid|std::getgrgid|getgrnam|::getgrnam|std::getgrnam|getlogin|::getlogin|std::getlogin|getpwent|::getpwent|std::getpwent|getpwnam|::getpwnam|std::getpwnam|getpwuid|::getpwuid|std::getpwuid|getpwuuid|::getpwuuid|std::getpwuuid|gets|::gets|std::gets|inet_ntop|::inet_ntop|std::inet_ntop|realpath|::realpath|std::realpath|tempnam|::tempnam|std::tempnam|tmpfile|::tmpfile|std::tmpfile|tmpnam|::tmpnam|std::tmpnam|memchr|::memchr|std::memchr|strcasestr_l|::strcasestr_l|std::strcasestr_l|strcasestr|::strcasestr|std::strcasestr|strchr|::strchr|std::strchr|strnstr|::strnstr|std::strnstr|strpbrk|::strpbrk|std::strpbrk|strrchr|::strrchr|std::strrchr|strstr|::strstr|std::strstr|strtok_r|::strtok_r|std::strtok_r|strtok|::strtok|std::strtok$" + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: neighbor + pattern: $$$ + + MATCH_PATTERN_SIX: + kind: call_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: "^fwrite|::fwrite|std::fwrite$" + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: end + kind: call_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: "^fgets|::fgets|std::fgets|fopen|::fopen|std::fopen|getenv|::getenv|std::getenv|getgrent|::getgrent|std::getgrent|getgrgid|::getgrgid|std::getgrgid|getgrnam|::getgrnam|std::getgrnam|getlogin|::getlogin|std::getlogin|getpwent|::getpwent|std::getpwent|getpwnam|::getpwnam|std::getpwnam|getpwuid|::getpwuid|std::getpwuid|getpwuuid|::getpwuuid|std::getpwuuid|gets|::gets|std::gets|inet_ntop|::inet_ntop|std::inet_ntop|realpath|::realpath|std::realpath|tempnam|::tempnam|std::tempnam|tmpfile|::tmpfile|std::tmpfile|tmpnam|::tmpnam|std::tmpnam|memchr|::memchr|std::memchr|strcasestr_l|::strcasestr_l|std::strcasestr_l|strcasestr|::strcasestr|std::strcasestr|strchr|::strchr|std::strchr|strnstr|::strnstr|std::strnstr|strpbrk|::strpbrk|std::strpbrk|strrchr|::strrchr|std::strrchr|strstr|::strstr|std::strstr|strtok_r|::strtok_r|std::strtok_r|strtok|::strtok|std::strtok$" + - has: + stopBy: neighbor + kind: argument_list + + MATCH_PATTERN_TWO: + kind: subscript_expression + all: + - has: + stopBy: neighbor + kind: parenthesized_expression + has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: "^fgets|::fgets|std::fgets|fopen|::fopen|std::fopen|getenv|::getenv|std::getenv|getgrent|::getgrent|std::getgrent|getgrgid|::getgrgid|std::getgrgid|getgrnam|::getgrnam|std::getgrnam|getlogin|::getlogin|std::getlogin|getpwent|::getpwent|std::getpwent|getpwnam|::getpwnam|std::getpwnam|getpwuid|::getpwuid|std::getpwuid|getpwuuid|::getpwuuid|std::getpwuuid|gets|::gets|std::gets|inet_ntop|::inet_ntop|std::inet_ntop|realpath|::realpath|std::realpath|tempnam|::tempnam|std::tempnam|tmpfile|::tmpfile|std::tmpfile|tmpnam|::tmpnam|std::tmpnam|memchr|::memchr|std::memchr|strcasestr_l|::strcasestr_l|std::strcasestr_l|strcasestr|::strcasestr|std::strcasestr|strchr|::strchr|std::strchr|strnstr|::strnstr|std::strnstr|strpbrk|::strpbrk|std::strpbrk|strrchr|::strrchr|std::strrchr|strstr|::strstr|std::strstr|strtok_r|::strtok_r|std::strtok_r|strtok|::strtok|std::strtok$" + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: neighbor + pattern: $$$ + - has: + stopBy: neighbor + pattern: $$$ + + MATCH_PATTERN_SEVEN: + kind: subscript_expression + all: + - has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: "^fgets|::fgets|std::fgets|fopen|::fopen|std::fopen|getenv|::getenv|std::getenv|getgrent|::getgrent|std::getgrent|getgrgid|::getgrgid|std::getgrgid|getgrnam|::getgrnam|std::getgrnam|getlogin|::getlogin|std::getlogin|getpwent|::getpwent|std::getpwent|getpwnam|::getpwnam|std::getpwnam|getpwuid|::getpwuid|std::getpwuid|getpwuuid|::getpwuuid|std::getpwuuid|gets|::gets|std::gets|inet_ntop|::inet_ntop|std::inet_ntop|realpath|::realpath|std::realpath|tempnam|::tempnam|std::tempnam|tmpfile|::tmpfile|std::tmpfile|tmpnam|::tmpnam|std::tmpnam|memchr|::memchr|std::memchr|strcasestr_l|::strcasestr_l|std::strcasestr_l|strcasestr|::strcasestr|std::strcasestr|strchr|::strchr|std::strchr|strnstr|::strnstr|std::strnstr|strpbrk|::strpbrk|std::strpbrk|strrchr|::strrchr|std::strrchr|strstr|::strstr|std::strstr|strtok_r|::strtok_r|std::strtok_r|strtok|::strtok|std::strtok$" + - has: + stopBy: neighbor + kind: argument_list + - has: + stopBy: neighbor + pattern: $$$ + +rule: + any: + - kind: return_statement + any: + - matches: MATCH_PATTERN_ONE + - kind: call_expression + any: + - matches: MATCH_PATTERN_THREE + - matches: MATCH_PATTERN_FOUR + - matches: MATCH_PATTERN_FIVE + - matches: MATCH_PATTERN_SIX + - kind: subscript_expression + any: + - matches: MATCH_PATTERN_TWO + - matches: MATCH_PATTERN_SEVEN diff --git a/tests/__snapshots__/null-library-function-c-snapshot.yml b/tests/__snapshots__/null-library-function-c-snapshot.yml new file mode 100644 index 00000000..9a30d57f --- /dev/null +++ b/tests/__snapshots__/null-library-function-c-snapshot.yml @@ -0,0 +1,20 @@ +id: null-library-function-c +snapshots: + ? "gid_t f() {\nreturn getgrent()->gr_gid;\n}\nvoid f() {\nchar buf[128];\nstrcpy(buf, getenv(\"FOO\"));\n}\n{\nfwrite(\"foo\", 3, 1, fopen(\"foo.txt\", \"w\"));\n}\n{\nFILE *fptr;\nfwrite(\"foo\", 3, 1, fptr = fopen(\"foo.txt\", \"w\"));\n}\nvoid test_getc() {\nint c = getc(fopen(file_name, \"r\")); \nint c = getc(fptr = fopen(file_name, \"r\"));\n}\n" + : labels: + - source: return getgrent()->gr_gid; + style: primary + start: 12 + end: 38 + - source: getgrent + style: secondary + start: 19 + end: 27 + - source: getgrent() + style: secondary + start: 19 + end: 29 + - source: getgrent()->gr_gid + style: secondary + start: 19 + end: 37 diff --git a/tests/c/null-library-function-c-test.yml b/tests/c/null-library-function-c-test.yml new file mode 100644 index 00000000..96bdd2dc --- /dev/null +++ b/tests/c/null-library-function-c-test.yml @@ -0,0 +1,30 @@ +id: null-library-function-c +valid: + - | + errno = 0; + fwrite(data, len, 1, f); + if (errno) { + ERRS("unable to write output file"); + goto out_flush; + } + +invalid: + - | + gid_t f() { + return getgrent()->gr_gid; + } + void f() { + char buf[128]; + strcpy(buf, getenv("FOO")); + } + { + fwrite("foo", 3, 1, fopen("foo.txt", "w")); + } + { + FILE *fptr; + fwrite("foo", 3, 1, fptr = fopen("foo.txt", "w")); + } + void test_getc() { + int c = getc(fopen(file_name, "r")); + int c = getc(fptr = fopen(file_name, "r")); + } From da50d28f4eec2155890c926bc812fe6d8b123c9c Mon Sep 17 00:00:00 2001 From: ESS-ENN Date: Mon, 14 Oct 2024 10:58:27 +0530 Subject: [PATCH 2/2] null-library-function-cpp --- .../security/null-library-function-cpp.yml | 193 ++++++++++++++++++ .../null-library-function-cpp-snapshot.yml | 20 ++ tests/cpp/null-library-function-cpp-test.yml | 30 +++ 3 files changed, 243 insertions(+) create mode 100644 rules/cpp/security/null-library-function-cpp.yml create mode 100644 tests/__snapshots__/null-library-function-cpp-snapshot.yml create mode 100644 tests/cpp/null-library-function-cpp-test.yml diff --git a/rules/cpp/security/null-library-function-cpp.yml b/rules/cpp/security/null-library-function-cpp.yml new file mode 100644 index 00000000..91856c05 --- /dev/null +++ b/rules/cpp/security/null-library-function-cpp.yml @@ -0,0 +1,193 @@ +id: null-library-function-cpp +language: Cpp +severity: warning +message: >- + The `$SOURCE` function returns NULL on error and this line dereferences + the return value without checking for NULL. +note: >- + [CWE-476] NULL Pointer Dereference. + [REFERENCES] + - https://wiki.sei.cmu.edu/confluence/display/c/EXP34-C.+Do+not+dereference+null+pointers +utils: + MATCH_PATTERN_ONE: + kind: return_statement + has: + stopBy: neighbor + kind: field_expression + has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: "^fgets|::fgets|std::fgets|fopen|::fopen|std::fopen|getenv|::getenv|std::getenv|getgrent|::getgrent|std::getgrent|getgrgid|::getgrgid|std::getgrgid|getgrnam|::getgrnam|std::getgrnam|getlogin|::getlogin|std::getlogin|getpwent|::getpwent|std::getpwent|getpwnam|::getpwnam|std::getpwnam|getpwuid|::getpwuid|std::getpwuid|getpwuuid|::getpwuuid|std::getpwuuid|gets|::gets|std::gets|inet_ntop|::inet_ntop|std::inet_ntop|realpath|::realpath|std::realpath|tempnam|::tempnam|std::tempnam|tmpfile|::tmpfile|std::tmpfile|tmpnam|::tmpnam|std::tmpnam|memchr|::memchr|std::memchr|strcasestr_l|::strcasestr_l|std::strcasestr_l|strcasestr|::strcasestr|std::strcasestr|strchr|::strchr|std::strchr|strnstr|::strnstr|std::strnstr|strpbrk|::strpbrk|std::strpbrk|strrchr|::strrchr|std::strrchr|strstr|::strstr|std::strstr|strtok_r|::strtok_r|std::strtok_r|strtok|::strtok|std::strtok$" + + MATCH_PATTERN_TWO: + kind: subscript_expression + all: + - has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: "^fgets|::fgets|std::fgets|fopen|::fopen|std::fopen|getenv|::getenv|std::getenv|getgrent|::getgrent|std::getgrent|getgrgid|::getgrgid|std::getgrgid|getgrnam|::getgrnam|std::getgrnam|getlogin|::getlogin|std::getlogin|getpwent|::getpwent|std::getpwent|getpwnam|::getpwnam|std::getpwnam|getpwuid|::getpwuid|std::getpwuid|getpwuuid|::getpwuuid|std::getpwuuid|gets|::gets|std::gets|inet_ntop|::inet_ntop|std::inet_ntop|realpath|::realpath|std::realpath|tempnam|::tempnam|std::tempnam|tmpfile|::tmpfile|std::tmpfile|tmpnam|::tmpnam|std::tmpnam|memchr|::memchr|std::memchr|strcasestr_l|::strcasestr_l|std::strcasestr_l|strcasestr|::strcasestr|std::strcasestr|strchr|::strchr|std::strchr|strnstr|::strnstr|std::strnstr|strpbrk|::strpbrk|std::strpbrk|strrchr|::strrchr|std::strrchr|strstr|::strstr|std::strstr|strtok_r|::strtok_r|std::strtok_r|strtok|::strtok|std::strtok$" + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: neighbor + kind: string_literal + has: + stopBy: neighbor + kind: string_content + - has: + stopBy: neighbor + kind: subscript_argument_list + has: + stopBy: neighbor + pattern: $$$ + + MATCH_PATTERN_THREE: + kind: call_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: "^atof|::atof|std::atof|atoi|::atoi|std::atoi|atol_l|::atol_l|std::atol_l|atol|::atol|std::atol|atoll_l|::atoll_l|std::atoll_l|atoll|::atoll|std::atoll|getc|::getc|std::getc|fprintf|::fprintf|std::fprintf|fgetpos|::fgetpos|std::fgetpos|fseek|::fseek|std::fseek|fseeko|::fseeko|std::fseeko|fsetpos|::fsetpos|std::fsetpos|ftell|::ftell|std::ftell|ftello|::ftello|std::ftello|rewind|::rewind|std::rewind|strlen|::strlen|std::strlen|strtoimax|::strtoimax|std::strtoimax|strtod|::strtod|std::strtod|strtol|::strtol|std::strtol|strtoul|::strtoul|std::strtoul|strtoll|::strtoll|std::strtoll|strtoq|::strtoq|std::strtoq$" + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: "^fgets|::fgets|std::fgets|fopen|::fopen|std::fopen|getenv|::getenv|std::getenv|getgrent|::getgrent|std::getgrent|getgrgid|::getgrgid|std::getgrgid|getgrnam|::getgrnam|std::getgrnam|getlogin|::getlogin|std::getlogin|getpwent|::getpwent|std::getpwent|getpwnam|::getpwnam|std::getpwnam|getpwuid|::getpwuid|std::getpwuid|getpwuuid|::getpwuuid|std::getpwuuid|gets|::gets|std::gets|inet_ntop|::inet_ntop|std::inet_ntop|realpath|::realpath|std::realpath|tempnam|::tempnam|std::tempnam|tmpfile|::tmpfile|std::tmpfile|tmpnam|::tmpnam|std::tmpnam|memchr|::memchr|std::memchr|strcasestr_l|::strcasestr_l|std::strcasestr_l|strcasestr|::strcasestr|std::strcasestr|strchr|::strchr|std::strchr|strnstr|::strnstr|std::strnstr|strpbrk|::strpbrk|std::strpbrk|strrchr|::strrchr|std::strrchr|strstr|::strstr|std::strstr|strtok_r|::strtok_r|std::strtok_r|strtok|::strtok|std::strtok$" + - has: + stopBy: end + kind: argument_list + + MATCH_PATTERN_FOUR: + kind: call_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: "^atof|::atof|std::atof|atoi|::atoi|std::atoi|atol_l|::atol_l|std::atol_l|atol|::atol|std::atol|atoll_l|::atoll_l|std::atoll_l|atoll|::atoll|std::atoll|getc|::getc|std::getc|fprintf|::fprintf|std::fprintf|fgetpos|::fgetpos|std::fgetpos|fseek|::fseek|std::fseek|fseeko|::fseeko|std::fseeko|fsetpos|::fsetpos|std::fsetpos|ftell|::ftell|std::ftell|ftello|::ftello|std::ftello|rewind|::rewind|std::rewind|strlen|::strlen|std::strlen|strtoimax|::strtoimax|std::strtoimax|strtod|::strtod|std::strtod|strtol|::strtol|std::strtol|strtoul|::strtoul|std::strtoul|strtoll|::strtoll|std::strtoll|strtoq|::strtoq|std::strtoq$" + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: neighbor + kind: assignment_expression + all: + - has: + stopBy: neighbor + kind: identifier + - has: + stopBy: neighbor + regex: "=" + - has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: "^fgets|::fgets|std::fgets|fopen|::fopen|std::fopen|getenv|::getenv|std::getenv|getgrent|::getgrent|std::getgrent|getgrgid|::getgrgid|std::getgrgid|getgrnam|::getgrnam|std::getgrnam|getlogin|::getlogin|std::getlogin|getpwent|::getpwent|std::getpwent|getpwnam|::getpwnam|std::getpwnam|getpwuid|::getpwuid|std::getpwuid|getpwuuid|::getpwuuid|std::getpwuuid|gets|::gets|std::gets|inet_ntop|::inet_ntop|std::inet_ntop|realpath|::realpath|std::realpath|tempnam|::tempnam|std::tempnam|tmpfile|::tmpfile|std::tmpfile|tmpnam|::tmpnam|std::tmpnam|memchr|::memchr|std::memchr|strcasestr_l|::strcasestr_l|std::strcasestr_l|strcasestr|::strcasestr|std::strcasestr|strchr|::strchr|std::strchr|strnstr|::strnstr|std::strnstr|strpbrk|::strpbrk|std::strpbrk|strrchr|::strrchr|std::strrchr|strstr|::strstr|std::strstr|strtok_r|::strtok_r|std::strtok_r|strtok|::strtok|std::strtok$" + - has: + stopBy: neighbor + kind: argument_list + + MATCH_PATTERN_FIVE: + kind: call_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: "^bcopy|::bcopy|std::bcopy|memccpy|::memccpy|std::memccpy|memcpy|::memcpy|std::memcpy|memmove|::memmove|std::memmove|stpncpy|::stpncpy|std::stpncpy|strcat|::strcat|std::strcat|strcpy|::strcpy|std::strcpy|strcpy|::strcpy|std::strcpy|strlcat|::strlcat|std::strlcat|strlcpy|::strlcpy|std::strlcpy|strncat|::strncat|std::strncat|strpcpy|::strpcpy|std::strpcpy|wcpcpy|::wcpcpy|std::wcpcpy|wcpncpy|::wcpncpy|std::wcpncpy$" + - has: + stopBy: neighbor + kind: argument_list + all: + - has: + stopBy: neighbor + pattern: $$$ + - has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: "^fgets|::fgets|std::fgets|fopen|::fopen|std::fopen|getenv|::getenv|std::getenv|getgrent|::getgrent|std::getgrent|getgrgid|::getgrgid|std::getgrgid|getgrnam|::getgrnam|std::getgrnam|getlogin|::getlogin|std::getlogin|getpwent|::getpwent|std::getpwent|getpwnam|::getpwnam|std::getpwnam|getpwuid|::getpwuid|std::getpwuid|getpwuuid|::getpwuuid|std::getpwuuid|gets|::gets|std::gets|inet_ntop|::inet_ntop|std::inet_ntop|realpath|::realpath|std::realpath|tempnam|::tempnam|std::tempnam|tmpfile|::tmpfile|std::tmpfile|tmpnam|::tmpnam|std::tmpnam|memchr|::memchr|std::memchr|strcasestr_l|::strcasestr_l|std::strcasestr_l|strcasestr|::strcasestr|std::strcasestr|strchr|::strchr|std::strchr|strnstr|::strnstr|std::strnstr|strpbrk|::strpbrk|std::strpbrk|strrchr|::strrchr|std::strrchr|strstr|::strstr|std::strstr|strtok_r|::strtok_r|std::strtok_r|strtok|::strtok|std::strtok$" + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: neighbor + pattern: $$$ + + MATCH_PATTERN_SIX: + kind: call_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: "^fwrite|::fwrite|std::fwrite$" + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: end + kind: call_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: "^fgets|::fgets|std::fgets|fopen|::fopen|std::fopen|getenv|::getenv|std::getenv|getgrent|::getgrent|std::getgrent|getgrgid|::getgrgid|std::getgrgid|getgrnam|::getgrnam|std::getgrnam|getlogin|::getlogin|std::getlogin|getpwent|::getpwent|std::getpwent|getpwnam|::getpwnam|std::getpwnam|getpwuid|::getpwuid|std::getpwuid|getpwuuid|::getpwuuid|std::getpwuuid|gets|::gets|std::gets|inet_ntop|::inet_ntop|std::inet_ntop|realpath|::realpath|std::realpath|tempnam|::tempnam|std::tempnam|tmpfile|::tmpfile|std::tmpfile|tmpnam|::tmpnam|std::tmpnam|memchr|::memchr|std::memchr|strcasestr_l|::strcasestr_l|std::strcasestr_l|strcasestr|::strcasestr|std::strcasestr|strchr|::strchr|std::strchr|strnstr|::strnstr|std::strnstr|strpbrk|::strpbrk|std::strpbrk|strrchr|::strrchr|std::strrchr|strstr|::strstr|std::strstr|strtok_r|::strtok_r|std::strtok_r|strtok|::strtok|std::strtok$" + - has: + stopBy: neighbor + kind: argument_list + + MATCH_PATTERN_SEVEN: + kind: subscript_expression + all: + - has: + stopBy: neighbor + kind: parenthesized_expression + has: + stopBy: neighbor + kind: call_expression + all: + - has: + stopBy: neighbor + kind: identifier + regex: "^fgets|::fgets|std::fgets|fopen|::fopen|std::fopen|getenv|::getenv|std::getenv|getgrent|::getgrent|std::getgrent|getgrgid|::getgrgid|std::getgrgid|getgrnam|::getgrnam|std::getgrnam|getlogin|::getlogin|std::getlogin|getpwent|::getpwent|std::getpwent|getpwnam|::getpwnam|std::getpwnam|getpwuid|::getpwuid|std::getpwuid|getpwuuid|::getpwuuid|std::getpwuuid|gets|::gets|std::gets|inet_ntop|::inet_ntop|std::inet_ntop|realpath|::realpath|std::realpath|tempnam|::tempnam|std::tempnam|tmpfile|::tmpfile|std::tmpfile|tmpnam|::tmpnam|std::tmpnam|memchr|::memchr|std::memchr|strcasestr_l|::strcasestr_l|std::strcasestr_l|strcasestr|::strcasestr|std::strcasestr|strchr|::strchr|std::strchr|strnstr|::strnstr|std::strnstr|strpbrk|::strpbrk|std::strpbrk|strrchr|::strrchr|std::strrchr|strstr|::strstr|std::strstr|strtok_r|::strtok_r|std::strtok_r|strtok|::strtok|std::strtok$" + - has: + stopBy: neighbor + kind: subscript_argument_list + has: + stopBy: neighbor + pattern: $$$ + +rule: + any: + - kind: return_statement + any: + - matches: MATCH_PATTERN_ONE + - kind: subscript_expression + any: + - matches: MATCH_PATTERN_TWO + - matches: MATCH_PATTERN_SEVEN + - kind: call_expression + any: + - matches: MATCH_PATTERN_THREE + - matches: MATCH_PATTERN_FOUR + - matches: MATCH_PATTERN_FIVE + - matches: MATCH_PATTERN_SIX diff --git a/tests/__snapshots__/null-library-function-cpp-snapshot.yml b/tests/__snapshots__/null-library-function-cpp-snapshot.yml new file mode 100644 index 00000000..c95fb6f0 --- /dev/null +++ b/tests/__snapshots__/null-library-function-cpp-snapshot.yml @@ -0,0 +1,20 @@ +id: null-library-function-cpp +snapshots: + ? "gid_t f() {\nreturn getgrent()->gr_gid;\n}\nvoid f() {\nchar buf[128];\nstrcpy(buf, getenv(\"FOO\"));\n}\n{\nfwrite(\"foo\", 3, 1, fopen(\"foo.txt\", \"w\"));\n}\n{\nFILE *fptr;\nfwrite(\"foo\", 3, 1, fptr = fopen(\"foo.txt\", \"w\"));\n}\nvoid test_getc() {\nint c = getc(fopen(file_name, \"r\")); \nint c = getc(fptr = fopen(file_name, \"r\"));\n}\n" + : labels: + - source: return getgrent()->gr_gid; + style: primary + start: 12 + end: 38 + - source: getgrent + style: secondary + start: 19 + end: 27 + - source: getgrent() + style: secondary + start: 19 + end: 29 + - source: getgrent()->gr_gid + style: secondary + start: 19 + end: 37 diff --git a/tests/cpp/null-library-function-cpp-test.yml b/tests/cpp/null-library-function-cpp-test.yml new file mode 100644 index 00000000..070db324 --- /dev/null +++ b/tests/cpp/null-library-function-cpp-test.yml @@ -0,0 +1,30 @@ +id: null-library-function-cpp +valid: + - | + errno = 0; + fwrite(data, len, 1, f); + if (errno) { + ERRS("unable to write output file"); + goto out_flush; + } + +invalid: + - | + gid_t f() { + return getgrent()->gr_gid; + } + void f() { + char buf[128]; + strcpy(buf, getenv("FOO")); + } + { + fwrite("foo", 3, 1, fopen("foo.txt", "w")); + } + { + FILE *fptr; + fwrite("foo", 3, 1, fptr = fopen("foo.txt", "w")); + } + void test_getc() { + int c = getc(fopen(file_name, "r")); + int c = getc(fptr = fopen(file_name, "r")); + }