diff --git a/cpp/ql/test/library-tests/dataflow/security-taint/tainted.expected b/cpp/ql/test/library-tests/dataflow/security-taint/tainted.expected new file mode 100644 index 00000000000..7359b068d8e --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/security-taint/tainted.expected @@ -0,0 +1,54 @@ +| test.cpp:23:23:23:28 | call to getenv | test.cpp:8:24:8:25 | s1 | | +| test.cpp:23:23:23:28 | call to getenv | test.cpp:23:14:23:19 | envStr | | +| test.cpp:23:23:23:28 | call to getenv | test.cpp:23:23:23:28 | call to getenv | | +| test.cpp:23:23:23:28 | call to getenv | test.cpp:23:23:23:40 | (const char *)... | | +| test.cpp:23:23:23:28 | call to getenv | test.cpp:25:6:25:29 | ! ... | | +| test.cpp:23:23:23:28 | call to getenv | test.cpp:25:7:25:12 | call to strcmp | | +| test.cpp:23:23:23:28 | call to getenv | test.cpp:25:7:25:29 | (bool)... | | +| test.cpp:23:23:23:28 | call to getenv | test.cpp:25:14:25:19 | envStr | | +| test.cpp:23:23:23:28 | call to getenv | test.cpp:29:6:29:28 | ! ... | | +| test.cpp:23:23:23:28 | call to getenv | test.cpp:29:7:29:12 | call to strcmp | | +| test.cpp:23:23:23:28 | call to getenv | test.cpp:29:7:29:28 | (bool)... | | +| test.cpp:23:23:23:28 | call to getenv | test.cpp:29:14:29:19 | envStr | | +| test.cpp:38:23:38:28 | call to getenv | test.cpp:8:24:8:25 | s1 | | +| test.cpp:38:23:38:28 | call to getenv | test.cpp:38:14:38:19 | envStr | | +| test.cpp:38:23:38:28 | call to getenv | test.cpp:38:23:38:28 | call to getenv | | +| test.cpp:38:23:38:28 | call to getenv | test.cpp:38:23:38:40 | (const char *)... | | +| test.cpp:38:23:38:28 | call to getenv | test.cpp:40:14:40:19 | envStr | | +| test.cpp:49:23:49:28 | call to getenv | test.cpp:8:24:8:25 | s1 | envStrGlobal | +| test.cpp:49:23:49:28 | call to getenv | test.cpp:45:13:45:24 | envStrGlobal | | +| test.cpp:49:23:49:28 | call to getenv | test.cpp:45:13:45:24 | envStrGlobal | envStrGlobal | +| test.cpp:49:23:49:28 | call to getenv | test.cpp:49:14:49:19 | envStr | | +| test.cpp:49:23:49:28 | call to getenv | test.cpp:49:23:49:28 | call to getenv | | +| test.cpp:49:23:49:28 | call to getenv | test.cpp:49:23:49:40 | (const char *)... | | +| test.cpp:49:23:49:28 | call to getenv | test.cpp:50:15:50:24 | envStr_ptr | | +| test.cpp:49:23:49:28 | call to getenv | test.cpp:50:15:50:24 | envStr_ptr | envStrGlobal | +| test.cpp:49:23:49:28 | call to getenv | test.cpp:50:28:50:40 | & ... | envStrGlobal | +| test.cpp:49:23:49:28 | call to getenv | test.cpp:50:29:50:40 | envStrGlobal | envStrGlobal | +| test.cpp:49:23:49:28 | call to getenv | test.cpp:52:2:52:12 | * ... | | +| test.cpp:49:23:49:28 | call to getenv | test.cpp:52:3:52:12 | envStr_ptr | | +| test.cpp:49:23:49:28 | call to getenv | test.cpp:52:16:52:21 | envStr | | +| test.cpp:49:23:49:28 | call to getenv | test.cpp:54:6:54:35 | ! ... | envStrGlobal | +| test.cpp:49:23:49:28 | call to getenv | test.cpp:54:7:54:12 | call to strcmp | envStrGlobal | +| test.cpp:49:23:49:28 | call to getenv | test.cpp:54:7:54:35 | (bool)... | envStrGlobal | +| test.cpp:49:23:49:28 | call to getenv | test.cpp:54:14:54:25 | envStrGlobal | envStrGlobal | +| test.cpp:60:29:60:34 | call to getenv | test.cpp:10:27:10:27 | s | | +| test.cpp:60:29:60:34 | call to getenv | test.cpp:60:18:60:25 | userName | | +| test.cpp:60:29:60:34 | call to getenv | test.cpp:60:29:60:34 | call to getenv | | +| test.cpp:60:29:60:34 | call to getenv | test.cpp:60:29:60:47 | (const char *)... | | +| test.cpp:60:29:60:34 | call to getenv | test.cpp:64:25:64:32 | userName | | +| test.cpp:68:28:68:33 | call to getenv | test.cpp:11:20:11:21 | s1 | | +| test.cpp:68:28:68:33 | call to getenv | test.cpp:11:36:11:37 | s2 | | +| test.cpp:68:28:68:33 | call to getenv | test.cpp:67:7:67:13 | copying | | +| test.cpp:68:28:68:33 | call to getenv | test.cpp:68:17:68:24 | userName | | +| test.cpp:68:28:68:33 | call to getenv | test.cpp:68:28:68:33 | call to getenv | | +| test.cpp:68:28:68:33 | call to getenv | test.cpp:68:28:68:46 | (const char *)... | | +| test.cpp:68:28:68:33 | call to getenv | test.cpp:69:10:69:13 | copy | | +| test.cpp:68:28:68:33 | call to getenv | test.cpp:70:5:70:10 | call to strcpy | | +| test.cpp:68:28:68:33 | call to getenv | test.cpp:70:12:70:15 | copy | | +| test.cpp:68:28:68:33 | call to getenv | test.cpp:70:18:70:25 | userName | | +| test.cpp:68:28:68:33 | call to getenv | test.cpp:71:12:71:15 | copy | | +| test.cpp:75:20:75:25 | call to getenv | test.cpp:15:22:15:25 | nptr | | +| test.cpp:75:20:75:25 | call to getenv | test.cpp:75:15:75:18 | call to atoi | | +| test.cpp:75:20:75:25 | call to getenv | test.cpp:75:20:75:25 | call to getenv | | +| test.cpp:75:20:75:25 | call to getenv | test.cpp:75:20:75:45 | (const char *)... | | diff --git a/cpp/ql/test/library-tests/dataflow/security-taint/tainted.ql b/cpp/ql/test/library-tests/dataflow/security-taint/tainted.ql new file mode 100644 index 00000000000..64a724c4cab --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/security-taint/tainted.ql @@ -0,0 +1,7 @@ +import semmle.code.cpp.security.TaintTracking + +from Expr source, Element tainted, string globalVar +where + taintedIncludingGlobalVars(source, tainted, globalVar) and + not tainted.getLocation().getFile().getExtension() = "h" +select source, tainted, globalVar diff --git a/cpp/ql/test/library-tests/dataflow/security-taint/test.cpp b/cpp/ql/test/library-tests/dataflow/security-taint/test.cpp new file mode 100644 index 00000000000..5eb7ee79b46 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/security-taint/test.cpp @@ -0,0 +1,78 @@ +// Test for the general-purpose taint-tracking +// mechanism that is used by several of the security queries. + +///// Library functions ////// + +typedef unsigned long size_t; + +int strcmp(const char *s1, const char *s2); +char *getenv(const char *name); +size_t strlen(const char *s); +char *strcpy(char *s1, const char *s2); + +void *malloc(size_t size); + +int atoi(const char *nptr); + +//// Test code ///// + +bool isAdmin = false; + +void test1() +{ + const char *envStr = getenv("USERINFO"); + + if (!strcmp(envStr, "admin")) { + isAdmin = true; + } + + if (!strcmp(envStr, "none")) { + isAdmin = false; + } +} + +extern const char *specialUser; + +void test2() +{ + const char *envStr = getenv("USERINFO"); + + if (!strcmp(envStr, specialUser)) { + isAdmin = true; + } +} + +const char *envStrGlobal; + +void test3() +{ + const char *envStr = getenv("USERINFO"); + const char **envStr_ptr = &envStrGlobal; + + *envStr_ptr = envStr; + + if (!strcmp(envStrGlobal, "admin")) { + isAdmin = true; + } +} + +void bugWithBinop() { + const char *userName = getenv("USER_NAME"); + + // The following is tainted, but should not cause + // the whole program to be considered tainted. + int bytes = strlen(userName) + 1; +} + +char* copying() { + const char *userName = getenv("USER_NAME"); + char copy[1024]; + strcpy(copy, userName); + return copy; // copy should be tainted +} + +void guard() { + int len = atoi(getenv("FOOBAZ_BRANCHING")); + if (len > 1000) return; + char **node = (char **) malloc(len * sizeof(char *)); +}