C++: Add some more test cases (moved from the private repo).

This commit is contained in:
Geoffrey White
2022-03-02 15:32:09 +00:00
parent 19718fa280
commit 67aa1449ce
5 changed files with 306 additions and 0 deletions

View File

@@ -12,6 +12,16 @@ edges
| tests2.cpp:109:6:109:8 | ptr [post update] | tests2.cpp:109:3:109:4 | c1 [post update] [ptr] |
| tests2.cpp:109:12:109:17 | call to getenv | tests2.cpp:109:6:109:8 | ptr [post update] |
| tests2.cpp:111:14:111:15 | c1 [read] [ptr] | tests2.cpp:111:14:111:19 | (const char *)... |
| tests_sockets.cpp:26:15:26:20 | call to getenv | tests_sockets.cpp:39:19:39:22 | (const void *)... |
| tests_sockets.cpp:26:15:26:20 | call to getenv | tests_sockets.cpp:39:19:39:22 | path |
| tests_sockets.cpp:26:15:26:20 | call to getenv | tests_sockets.cpp:43:20:43:23 | (const void *)... |
| tests_sockets.cpp:26:15:26:20 | call to getenv | tests_sockets.cpp:43:20:43:23 | path |
| tests_sockets.cpp:63:15:63:20 | call to getenv | tests_sockets.cpp:76:19:76:22 | (const void *)... |
| tests_sockets.cpp:63:15:63:20 | call to getenv | tests_sockets.cpp:76:19:76:22 | path |
| tests_sockets.cpp:63:15:63:20 | call to getenv | tests_sockets.cpp:80:20:80:23 | (const void *)... |
| tests_sockets.cpp:63:15:63:20 | call to getenv | tests_sockets.cpp:80:20:80:23 | path |
| tests_sysconf.cpp:36:21:36:27 | pathbuf | tests_sysconf.cpp:39:19:39:25 | (const void *)... |
| tests_sysconf.cpp:36:21:36:27 | pathbuf | tests_sysconf.cpp:39:19:39:25 | pathbuf |
nodes
| tests2.cpp:63:13:63:18 | call to getenv | semmle.label | call to getenv |
| tests2.cpp:63:13:63:18 | call to getenv | semmle.label | call to getenv |
@@ -38,6 +48,19 @@ nodes
| tests2.cpp:109:12:109:17 | call to getenv | semmle.label | call to getenv |
| tests2.cpp:111:14:111:15 | c1 [read] [ptr] | semmle.label | c1 [read] [ptr] |
| tests2.cpp:111:14:111:19 | (const char *)... | semmle.label | (const char *)... |
| tests_sockets.cpp:26:15:26:20 | call to getenv | semmle.label | call to getenv |
| tests_sockets.cpp:39:19:39:22 | (const void *)... | semmle.label | (const void *)... |
| tests_sockets.cpp:39:19:39:22 | path | semmle.label | path |
| tests_sockets.cpp:43:20:43:23 | (const void *)... | semmle.label | (const void *)... |
| tests_sockets.cpp:43:20:43:23 | path | semmle.label | path |
| tests_sockets.cpp:63:15:63:20 | call to getenv | semmle.label | call to getenv |
| tests_sockets.cpp:76:19:76:22 | (const void *)... | semmle.label | (const void *)... |
| tests_sockets.cpp:76:19:76:22 | path | semmle.label | path |
| tests_sockets.cpp:80:20:80:23 | (const void *)... | semmle.label | (const void *)... |
| tests_sockets.cpp:80:20:80:23 | path | semmle.label | path |
| tests_sysconf.cpp:36:21:36:27 | pathbuf | semmle.label | pathbuf |
| tests_sysconf.cpp:39:19:39:25 | (const void *)... | semmle.label | (const void *)... |
| tests_sysconf.cpp:39:19:39:25 | pathbuf | semmle.label | pathbuf |
subpaths
#select
| tests2.cpp:63:13:63:18 | call to getenv | tests2.cpp:63:13:63:18 | call to getenv | tests2.cpp:63:13:63:18 | call to getenv | This operation exposes system data from $@. | tests2.cpp:63:13:63:18 | call to getenv | call to getenv |
@@ -50,3 +73,8 @@ subpaths
| tests2.cpp:93:14:93:17 | str1 | tests2.cpp:91:42:91:45 | str1 | tests2.cpp:93:14:93:17 | str1 | This operation exposes system data from $@. | tests2.cpp:91:42:91:45 | str1 | str1 |
| tests2.cpp:102:14:102:15 | pw | tests2.cpp:101:8:101:15 | call to getpwuid | tests2.cpp:102:14:102:15 | pw | This operation exposes system data from $@. | tests2.cpp:101:8:101:15 | call to getpwuid | call to getpwuid |
| tests2.cpp:111:14:111:19 | (const char *)... | tests2.cpp:109:12:109:17 | call to getenv | tests2.cpp:111:14:111:19 | (const char *)... | This operation exposes system data from $@. | tests2.cpp:109:12:109:17 | call to getenv | call to getenv |
| tests_sockets.cpp:39:19:39:22 | path | tests_sockets.cpp:26:15:26:20 | call to getenv | tests_sockets.cpp:39:19:39:22 | path | This operation exposes system data from $@. | tests_sockets.cpp:26:15:26:20 | call to getenv | call to getenv |
| tests_sockets.cpp:43:20:43:23 | path | tests_sockets.cpp:26:15:26:20 | call to getenv | tests_sockets.cpp:43:20:43:23 | path | This operation exposes system data from $@. | tests_sockets.cpp:26:15:26:20 | call to getenv | call to getenv |
| tests_sockets.cpp:76:19:76:22 | path | tests_sockets.cpp:63:15:63:20 | call to getenv | tests_sockets.cpp:76:19:76:22 | path | This operation exposes system data from $@. | tests_sockets.cpp:63:15:63:20 | call to getenv | call to getenv |
| tests_sockets.cpp:80:20:80:23 | path | tests_sockets.cpp:63:15:63:20 | call to getenv | tests_sockets.cpp:80:20:80:23 | path | This operation exposes system data from $@. | tests_sockets.cpp:63:15:63:20 | call to getenv | call to getenv |
| tests_sysconf.cpp:39:19:39:25 | pathbuf | tests_sysconf.cpp:36:21:36:27 | pathbuf | tests_sysconf.cpp:39:19:39:25 | pathbuf | This operation exposes system data from $@. | tests_sysconf.cpp:36:21:36:27 | pathbuf | pathbuf |

View File

@@ -0,0 +1,132 @@
// test cases for rule CWE-497
// library functions etc
typedef unsigned long size_t;
typedef struct {} FILE;
FILE *stdout;
int puts(const char *s);
int printf(const char *format, ...);
int sprintf(char *s, const char *format, ...);
int snprintf(char *s, size_t n, const char *format, ...);
size_t strlen(const char *s);
char *getenv(const char *name);
namespace std
{
typedef size_t streamsize;
template<class charT> struct char_traits;
template <class charT, class traits = char_traits<charT> >
class basic_ostream /*: virtual public basic_ios<charT,traits> - not needed for this test */ {
public:
typedef charT char_type;
basic_ostream<charT,traits>& write(const char_type* s, streamsize n);
basic_ostream<charT, traits>& operator<<(int n);
};
template<class charT, class traits> basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&, const charT*);
typedef basic_ostream<char> ostream;
extern ostream cout;
extern ostream cerr;
extern ostream clog;
}
extern std::ostream someotherostream;
#define NULL (0)
// test cases
void test1()
{
std::ostream cout_copy = std::cout;
std::cout << getenv("USERPROFILE"); // BAD: outputs USERPROFILE environment variable [NOT DETECTED]
std::cerr << getenv("USERPROFILE"); // BAD: outputs USERPROFILE environment variable [NOT DETECTED]
std::clog << getenv("USERPROFILE"); // BAD: outputs USERPROFILE environment variable [NOT DETECTED]
someotherostream << getenv("USERPROFILE"); // GOOD: not output
cout_copy << getenv("USERPROFILE"); // BAD: outputs USERPROFILE environment variable [NOT DETECTED]
std::cout << getenv("PATH"); // BAD: outputs PATH environment variable [NOT DETECTED]
std::cout.write(getenv("PATH"), strlen(getenv("PATH"))); // BAD: outputs PATH environment variable [NOT DETECTED]
(std::cout << "PATH = ").write(getenv("PATH"), strlen(getenv("PATH"))); // BAD: outputs PATH environment variable [NOT DETECTED]
std::cout.write("PATH = ", 7) << getenv("PATH"); // BAD: outputs PATH environment variable [NOT DETECTED]
}
char *global_path = getenv("PATH");
char *global_other = "Hello, world!";
void test2(bool cond)
{
char *maybe;
maybe = cond ? global_path : global_other;
printf("path = '%s'\n", global_path); // BAD: outputs PATH environment variable [NOT DETECTED]
printf("other = '%s'\n", global_other);
printf("maybe = '%s'\n", maybe); // BAD: may output PATH environment variable [NOT DETECTED]
}
void test3()
{
char *path_string = getenv("PATH");
char buf[4096];
// ...
snprintf(buf, 4096, "invalid path '%s'\n", path_string);
puts(buf); // BAD: outputs PATH environment variable [NOT DETECTED]
}
void myOutputFn(const char *msg)
{
printf("%s", msg);
}
void myOtherFn(const char *msg)
{
}
void test4()
{
myOutputFn(getenv("PATH")); // BAD: outputs the PATH environment variable [NOT DETECTED]
myOtherFn(getenv("PATH")); // GOOD: does not output anything.
}
void myOutputFn2(const char *msg)
{
msg = "";
printf("%s", msg);
}
void myOutputFn3(const char *msg)
{
const char *tmp = msg;
printf("%s", tmp);
}
void myOutputFn4(const char *msg)
{
char buffer[4096];
sprintf(buffer, "log: %s\n", msg);
puts(buffer);
}
void myOutputFn5(const char *msg)
{
printf("%s", msg);
msg = "";
}
void test5()
{
myOutputFn2(getenv("PATH")); // GOOD: myOutputFn2 doesn't actually output the parameter
myOutputFn3(getenv("PATH")); // BAD: outputs the PATH environment variable [NOT DETECTED]
myOutputFn4(getenv("PATH")); // BAD: outputs the PATH environment variable [NOT DETECTED]
myOutputFn5(getenv("PATH")); // BAD: outputs the PATH environment variable [NOT DETECTED]
}

View File

@@ -0,0 +1,21 @@
int printf(const char *format, ...);
struct passwd {
char *pw_passwd;
char *pw_dir;
// ...
};
struct passwd *getpwnam(const char *name);
void test6(char *username)
{
passwd *pwd;
pwd = getpwnam(username);
printf("pw_passwd = %s\n", pwd->pw_passwd); // BAD [NOT DETECTED]
printf("pw_dir = %s\n", pwd->pw_dir); // BAD [NOT DETECTED]
printf("sizeof(passwd) = %i\n", sizeof(passwd)); // GOOD
}

View File

@@ -0,0 +1,84 @@
typedef unsigned long size_t;
size_t strlen(const char *s);
char *getenv(const char *name);
#define AF_INET (2)
#define SOCK_STREAM (1)
struct sockaddr {
int sa_family;
// ...
};
int socket(int domain, int type, int protocol);
int connect(int socket, const struct sockaddr *address, size_t address_len);
size_t send(int socket, const void *buffer, size_t length, int flags);
int write(int handle, const void *buffer, size_t length);
void test_sockets1()
{
int sockfd;
sockaddr addr_remote;
char *msg = "Hello, world!";
char *path = getenv("PATH");
// create socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) return;
// connect socket to a remote address
addr_remote.sa_family = AF_INET;
// ...
if (connect(sockfd, &addr_remote, sizeof(addr_remote)) != 0) return;
// send something using 'send'
if (send(sockfd, msg, strlen(msg) + 1, 0) < 0) return; // GOOD
if (send(sockfd, path, strlen(path) + 1, 0) < 0) return; // BAD
// send something using 'write'
if (write(sockfd, msg, strlen(msg) + 1) < 0) return; // GOOD
if (write(sockfd, path, strlen(path) + 1) < 0) return; // BAD
// clean up
// ...
}
int mksocket()
{
int fd;
fd = socket(AF_INET, SOCK_STREAM, 0);
return fd;
}
void test_sockets2()
{
int sockfd;
sockaddr addr_remote;
char *msg = "Hello, world!";
char *path = getenv("PATH");
// create socket
sockfd = mksocket();
if (sockfd < 0) return;
// connect socket to a remote address
addr_remote.sa_family = AF_INET;
// ...
if (connect(sockfd, &addr_remote, sizeof(addr_remote)) != 0) return;
// send something using 'send'
if (send(sockfd, msg, strlen(msg) + 1, 0) < 0) return; // GOOD
if (send(sockfd, path, strlen(path) + 1, 0) < 0) return; // BAD
// send something using 'write'
if (write(sockfd, msg, strlen(msg) + 1) < 0) return; // GOOD
if (write(sockfd, path, strlen(path) + 1) < 0) return; // BAD
// clean up
// ...
}

View File

@@ -0,0 +1,41 @@
typedef unsigned long size_t;
typedef signed long ssize_t;
void *malloc(size_t size);
#define NULL (0)
int printf(const char *format, ...);
size_t strlen(const char *s);
int get_fd();
int write(int handle, const void *buffer, size_t length);
long sysconf(int name);
#define _SC_CHILD_MAX (2)
size_t confstr(int name, char *buffer, size_t length);
#define _CS_PATH (1)
void test_sc_1()
{
int value = sysconf(_SC_CHILD_MAX);
printf("_SC_CHILD_MAX = %i\n", _SC_CHILD_MAX); // GOOD
printf("_SC_CHILD_MAX = %i\n", value); // BAD [NOT DETECTED]
}
void test_sc_2()
{
char *pathbuf;
size_t n;
n = confstr(_CS_PATH, NULL, (size_t)0);
pathbuf = (char *)malloc(n);
if (pathbuf != NULL)
{
confstr(_CS_PATH, pathbuf, n);
printf("path: %s", pathbuf); // BAD [NOT DETECTED]
write(get_fd(), pathbuf, strlen(pathbuf)); // BAD
}
}