| @@ -0,0 +1,98 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE122_Heap_Based_Buffer_Overflow__CWE131_loop_01.c | |||
| Label Definition File: CWE122_Heap_Based_Buffer_Overflow__CWE131.label.xml | |||
| Template File: sources-sink-01.tmpl.c | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 122 Heap Based Buffer Overflow | |||
| * BadSource: Allocate memory without using sizeof(int) | |||
| * GoodSource: Allocate memory using sizeof(int) | |||
| * Sink: loop | |||
| * BadSink : Copy array to data using a loop | |||
| * Flow Variant: 01 Baseline | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #ifndef OMITBAD | |||
| void CWE122_Heap_Based_Buffer_Overflow__CWE131_loop_01_bad() | |||
| { | |||
| int * data; | |||
| data = NULL; | |||
| /* FLAW: Allocate memory without using sizeof(int) */ | |||
| data = (int *)malloc(10); | |||
| if (data == NULL) {exit(-1);} | |||
| { | |||
| int source[10] = {0}; | |||
| size_t i; | |||
| /* POTENTIAL FLAW: Possible buffer overflow if data was not allocated correctly in the source */ | |||
| for (i = 0; i < 10; i++) | |||
| { | |||
| data[i] = source[i]; | |||
| } | |||
| printIntLine(data[0]); | |||
| free(data); | |||
| } | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* goodG2B uses the GoodSource with the BadSink */ | |||
| static void goodG2B() | |||
| { | |||
| int * data; | |||
| data = NULL; | |||
| /* FIX: Allocate memory using sizeof(int) */ | |||
| data = (int *)malloc(10*sizeof(int)); | |||
| if (data == NULL) {exit(-1);} | |||
| { | |||
| int source[10] = {0}; | |||
| size_t i; | |||
| /* POTENTIAL FLAW: Possible buffer overflow if data was not allocated correctly in the source */ | |||
| for (i = 0; i < 10; i++) | |||
| { | |||
| data[i] = source[i]; | |||
| } | |||
| printIntLine(data[0]); | |||
| free(data); | |||
| } | |||
| } | |||
| void CWE122_Heap_Based_Buffer_Overflow__CWE131_loop_01_good() | |||
| { | |||
| goodG2B(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| * its own for testing or for building a binary to use in testing binary | |||
| * analysis tools. It is not used when compiling all the testcases as one | |||
| * application, which is how source code analysis tools are tested. | |||
| */ | |||
| #ifdef INCLUDEMAIN | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| CWE122_Heap_Based_Buffer_Overflow__CWE131_loop_01_good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| CWE122_Heap_Based_Buffer_Overflow__CWE131_loop_01_bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,134 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE122_Heap_Based_Buffer_Overflow__CWE131_loop_02.c | |||
| Label Definition File: CWE122_Heap_Based_Buffer_Overflow__CWE131.label.xml | |||
| Template File: sources-sink-02.tmpl.c | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 122 Heap Based Buffer Overflow | |||
| * BadSource: Allocate memory without using sizeof(int) | |||
| * GoodSource: Allocate memory using sizeof(int) | |||
| * Sink: loop | |||
| * BadSink : Copy array to data using a loop | |||
| * Flow Variant: 02 Control flow: if(1) and if(0) | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #ifndef OMITBAD | |||
| void CWE122_Heap_Based_Buffer_Overflow__CWE131_loop_02_bad() | |||
| { | |||
| int * data; | |||
| data = NULL; | |||
| if(1) | |||
| { | |||
| /* FLAW: Allocate memory without using sizeof(int) */ | |||
| data = (int *)malloc(10); | |||
| if (data == NULL) {exit(-1);} | |||
| } | |||
| { | |||
| int source[10] = {0}; | |||
| size_t i; | |||
| /* POTENTIAL FLAW: Possible buffer overflow if data was not allocated correctly in the source */ | |||
| for (i = 0; i < 10; i++) | |||
| { | |||
| data[i] = source[i]; | |||
| } | |||
| printIntLine(data[0]); | |||
| free(data); | |||
| } | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* goodG2B1() - use goodsource and badsink by changing the 1 to 0 */ | |||
| static void goodG2B1() | |||
| { | |||
| int * data; | |||
| data = NULL; | |||
| if(0) | |||
| { | |||
| /* INCIDENTAL: CWE 561 Dead Code, the code below will never run */ | |||
| printLine("Benign, fixed string"); | |||
| } | |||
| else | |||
| { | |||
| /* FIX: Allocate memory using sizeof(int) */ | |||
| data = (int *)malloc(10*sizeof(int)); | |||
| if (data == NULL) {exit(-1);} | |||
| } | |||
| { | |||
| int source[10] = {0}; | |||
| size_t i; | |||
| /* POTENTIAL FLAW: Possible buffer overflow if data was not allocated correctly in the source */ | |||
| for (i = 0; i < 10; i++) | |||
| { | |||
| data[i] = source[i]; | |||
| } | |||
| printIntLine(data[0]); | |||
| free(data); | |||
| } | |||
| } | |||
| /* goodG2B2() - use goodsource and badsink by reversing the blocks in the if statement */ | |||
| static void goodG2B2() | |||
| { | |||
| int * data; | |||
| data = NULL; | |||
| if(1) | |||
| { | |||
| /* FIX: Allocate memory using sizeof(int) */ | |||
| data = (int *)malloc(10*sizeof(int)); | |||
| if (data == NULL) {exit(-1);} | |||
| } | |||
| { | |||
| int source[10] = {0}; | |||
| size_t i; | |||
| /* POTENTIAL FLAW: Possible buffer overflow if data was not allocated correctly in the source */ | |||
| for (i = 0; i < 10; i++) | |||
| { | |||
| data[i] = source[i]; | |||
| } | |||
| printIntLine(data[0]); | |||
| free(data); | |||
| } | |||
| } | |||
| void CWE122_Heap_Based_Buffer_Overflow__CWE131_loop_02_good() | |||
| { | |||
| goodG2B1(); | |||
| goodG2B2(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| * its own for testing or for building a binary to use in testing binary | |||
| * analysis tools. It is not used when compiling all the testcases as one | |||
| * application, which is how source code analysis tools are tested. | |||
| */ | |||
| #ifdef INCLUDEMAIN | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| CWE122_Heap_Based_Buffer_Overflow__CWE131_loop_02_good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| CWE122_Heap_Based_Buffer_Overflow__CWE131_loop_02_bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,134 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE122_Heap_Based_Buffer_Overflow__CWE131_loop_03.c | |||
| Label Definition File: CWE122_Heap_Based_Buffer_Overflow__CWE131.label.xml | |||
| Template File: sources-sink-03.tmpl.c | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 122 Heap Based Buffer Overflow | |||
| * BadSource: Allocate memory without using sizeof(int) | |||
| * GoodSource: Allocate memory using sizeof(int) | |||
| * Sink: loop | |||
| * BadSink : Copy array to data using a loop | |||
| * Flow Variant: 03 Control flow: if(5==5) and if(5!=5) | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #ifndef OMITBAD | |||
| void CWE122_Heap_Based_Buffer_Overflow__CWE131_loop_03_bad() | |||
| { | |||
| int * data; | |||
| data = NULL; | |||
| if(5==5) | |||
| { | |||
| /* FLAW: Allocate memory without using sizeof(int) */ | |||
| data = (int *)malloc(10); | |||
| if (data == NULL) {exit(-1);} | |||
| } | |||
| { | |||
| int source[10] = {0}; | |||
| size_t i; | |||
| /* POTENTIAL FLAW: Possible buffer overflow if data was not allocated correctly in the source */ | |||
| for (i = 0; i < 10; i++) | |||
| { | |||
| data[i] = source[i]; | |||
| } | |||
| printIntLine(data[0]); | |||
| free(data); | |||
| } | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* goodG2B1() - use goodsource and badsink by changing the 5==5 to 5!=5 */ | |||
| static void goodG2B1() | |||
| { | |||
| int * data; | |||
| data = NULL; | |||
| if(5!=5) | |||
| { | |||
| /* INCIDENTAL: CWE 561 Dead Code, the code below will never run */ | |||
| printLine("Benign, fixed string"); | |||
| } | |||
| else | |||
| { | |||
| /* FIX: Allocate memory using sizeof(int) */ | |||
| data = (int *)malloc(10*sizeof(int)); | |||
| if (data == NULL) {exit(-1);} | |||
| } | |||
| { | |||
| int source[10] = {0}; | |||
| size_t i; | |||
| /* POTENTIAL FLAW: Possible buffer overflow if data was not allocated correctly in the source */ | |||
| for (i = 0; i < 10; i++) | |||
| { | |||
| data[i] = source[i]; | |||
| } | |||
| printIntLine(data[0]); | |||
| free(data); | |||
| } | |||
| } | |||
| /* goodG2B2() - use goodsource and badsink by reversing the blocks in the if statement */ | |||
| static void goodG2B2() | |||
| { | |||
| int * data; | |||
| data = NULL; | |||
| if(5==5) | |||
| { | |||
| /* FIX: Allocate memory using sizeof(int) */ | |||
| data = (int *)malloc(10*sizeof(int)); | |||
| if (data == NULL) {exit(-1);} | |||
| } | |||
| { | |||
| int source[10] = {0}; | |||
| size_t i; | |||
| /* POTENTIAL FLAW: Possible buffer overflow if data was not allocated correctly in the source */ | |||
| for (i = 0; i < 10; i++) | |||
| { | |||
| data[i] = source[i]; | |||
| } | |||
| printIntLine(data[0]); | |||
| free(data); | |||
| } | |||
| } | |||
| void CWE122_Heap_Based_Buffer_Overflow__CWE131_loop_03_good() | |||
| { | |||
| goodG2B1(); | |||
| goodG2B2(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| * its own for testing or for building a binary to use in testing binary | |||
| * analysis tools. It is not used when compiling all the testcases as one | |||
| * application, which is how source code analysis tools are tested. | |||
| */ | |||
| #ifdef INCLUDEMAIN | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| CWE122_Heap_Based_Buffer_Overflow__CWE131_loop_03_good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| CWE122_Heap_Based_Buffer_Overflow__CWE131_loop_03_bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,274 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE124_Buffer_Underwrite__CWE839_connect_socket_01.c | |||
| Label Definition File: CWE124_Buffer_Underwrite__CWE839.label.xml | |||
| Template File: sources-sinks-01.tmpl.c | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 124 Buffer Underwrite | |||
| * BadSource: connect_socket Read data using a connect socket (client side) | |||
| * GoodSource: Non-negative but less than 10 | |||
| * Sinks: | |||
| * GoodSink: Ensure the array index is valid | |||
| * BadSink : Improperly check the array index by not checking the lower bound | |||
| * Flow Variant: 01 Baseline | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #ifdef _WIN32 | |||
| #include <winsock2.h> | |||
| #include <windows.h> | |||
| #include <direct.h> | |||
| #pragma comment(lib, "ws2_32") /* include ws2_32.lib when linking */ | |||
| #define CLOSE_SOCKET closesocket | |||
| #else /* NOT _WIN32 */ | |||
| #include <sys/types.h> | |||
| #include <sys/socket.h> | |||
| #include <netinet/in.h> | |||
| #include <arpa/inet.h> | |||
| #include <unistd.h> | |||
| #define INVALID_SOCKET -1 | |||
| #define SOCKET_ERROR -1 | |||
| #define CLOSE_SOCKET close | |||
| #define SOCKET int | |||
| #endif | |||
| #define TCP_PORT 27015 | |||
| #define IP_ADDRESS "127.0.0.1" | |||
| #define CHAR_ARRAY_SIZE (3 * sizeof(data) + 2) | |||
| #ifndef OMITBAD | |||
| void CWE124_Buffer_Underwrite__CWE839_connect_socket_01_bad() | |||
| { | |||
| int data; | |||
| /* Initialize data */ | |||
| data = -1; | |||
| { | |||
| #ifdef _WIN32 | |||
| WSADATA wsaData; | |||
| int wsaDataInit = 0; | |||
| #endif | |||
| int recvResult; | |||
| struct sockaddr_in service; | |||
| SOCKET connectSocket = INVALID_SOCKET; | |||
| char inputBuffer[CHAR_ARRAY_SIZE]; | |||
| do | |||
| { | |||
| #ifdef _WIN32 | |||
| if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| wsaDataInit = 1; | |||
| #endif | |||
| /* POTENTIAL FLAW: Read data using a connect socket */ | |||
| connectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |||
| if (connectSocket == INVALID_SOCKET) | |||
| { | |||
| break; | |||
| } | |||
| memset(&service, 0, sizeof(service)); | |||
| service.sin_family = AF_INET; | |||
| service.sin_addr.s_addr = inet_addr(IP_ADDRESS); | |||
| service.sin_port = htons(TCP_PORT); | |||
| if (connect(connectSocket, (struct sockaddr*)&service, sizeof(service)) == SOCKET_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| /* Abort on error or the connection was closed, make sure to recv one | |||
| * less char than is in the recv_buf in order to append a terminator */ | |||
| recvResult = recv(connectSocket, inputBuffer, CHAR_ARRAY_SIZE - 1, 0); | |||
| if (recvResult == SOCKET_ERROR || recvResult == 0) | |||
| { | |||
| break; | |||
| } | |||
| /* NUL-terminate the string */ | |||
| inputBuffer[recvResult] = '\0'; | |||
| /* Convert to int */ | |||
| data = atoi(inputBuffer); | |||
| } | |||
| while (0); | |||
| if (connectSocket != INVALID_SOCKET) | |||
| { | |||
| CLOSE_SOCKET(connectSocket); | |||
| } | |||
| #ifdef _WIN32 | |||
| if (wsaDataInit) | |||
| { | |||
| WSACleanup(); | |||
| } | |||
| #endif | |||
| } | |||
| { | |||
| int i; | |||
| int buffer[10] = { 0 }; | |||
| /* POTENTIAL FLAW: Attempt to access a negative index of the array | |||
| * This code does not check to see if the array index is negative */ | |||
| if (data < 10) | |||
| { | |||
| buffer[data] = 1; | |||
| /* Print the array values */ | |||
| for(i = 0; i < 10; i++) | |||
| { | |||
| printIntLine(buffer[i]); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| printLine("ERROR: Array index is negative."); | |||
| } | |||
| } | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* goodG2B uses the GoodSource with the BadSink */ | |||
| static void goodG2B() | |||
| { | |||
| int data; | |||
| /* Initialize data */ | |||
| data = -1; | |||
| /* FIX: Use a value greater than 0, but less than 10 to avoid attempting to | |||
| * access an index of the array in the sink that is out-of-bounds */ | |||
| data = 7; | |||
| { | |||
| int i; | |||
| int buffer[10] = { 0 }; | |||
| /* POTENTIAL FLAW: Attempt to access a negative index of the array | |||
| * This code does not check to see if the array index is negative */ | |||
| if (data < 10) | |||
| { | |||
| buffer[data] = 1; | |||
| /* Print the array values */ | |||
| for(i = 0; i < 10; i++) | |||
| { | |||
| printIntLine(buffer[i]); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| printLine("ERROR: Array index is negative."); | |||
| } | |||
| } | |||
| } | |||
| /* goodB2G uses the BadSource with the GoodSink */ | |||
| static void goodB2G() | |||
| { | |||
| int data; | |||
| /* Initialize data */ | |||
| data = -1; | |||
| { | |||
| #ifdef _WIN32 | |||
| WSADATA wsaData; | |||
| int wsaDataInit = 0; | |||
| #endif | |||
| int recvResult; | |||
| struct sockaddr_in service; | |||
| SOCKET connectSocket = INVALID_SOCKET; | |||
| char inputBuffer[CHAR_ARRAY_SIZE]; | |||
| do | |||
| { | |||
| #ifdef _WIN32 | |||
| if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| wsaDataInit = 1; | |||
| #endif | |||
| /* POTENTIAL FLAW: Read data using a connect socket */ | |||
| connectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |||
| if (connectSocket == INVALID_SOCKET) | |||
| { | |||
| break; | |||
| } | |||
| memset(&service, 0, sizeof(service)); | |||
| service.sin_family = AF_INET; | |||
| service.sin_addr.s_addr = inet_addr(IP_ADDRESS); | |||
| service.sin_port = htons(TCP_PORT); | |||
| if (connect(connectSocket, (struct sockaddr*)&service, sizeof(service)) == SOCKET_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| /* Abort on error or the connection was closed, make sure to recv one | |||
| * less char than is in the recv_buf in order to append a terminator */ | |||
| recvResult = recv(connectSocket, inputBuffer, CHAR_ARRAY_SIZE - 1, 0); | |||
| if (recvResult == SOCKET_ERROR || recvResult == 0) | |||
| { | |||
| break; | |||
| } | |||
| /* NUL-terminate the string */ | |||
| inputBuffer[recvResult] = '\0'; | |||
| /* Convert to int */ | |||
| data = atoi(inputBuffer); | |||
| } | |||
| while (0); | |||
| if (connectSocket != INVALID_SOCKET) | |||
| { | |||
| CLOSE_SOCKET(connectSocket); | |||
| } | |||
| #ifdef _WIN32 | |||
| if (wsaDataInit) | |||
| { | |||
| WSACleanup(); | |||
| } | |||
| #endif | |||
| } | |||
| { | |||
| int i; | |||
| int buffer[10] = { 0 }; | |||
| /* FIX: Properly validate the array index and prevent a buffer underwrite */ | |||
| if (data >= 0 && data < (10)) | |||
| { | |||
| buffer[data] = 1; | |||
| /* Print the array values */ | |||
| for(i = 0; i < 10; i++) | |||
| { | |||
| printIntLine(buffer[i]); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| printLine("ERROR: Array index is out-of-bounds"); | |||
| } | |||
| } | |||
| } | |||
| void CWE124_Buffer_Underwrite__CWE839_connect_socket_01_good() | |||
| { | |||
| goodG2B(); | |||
| goodB2G(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| its own for testing or for building a binary to use in testing binary | |||
| analysis tools. It is not used when compiling all the testcases as one | |||
| application, which is how source code analysis tools are tested. */ | |||
| #ifdef INCLUDEMAIN | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| CWE124_Buffer_Underwrite__CWE839_connect_socket_01_good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| CWE124_Buffer_Underwrite__CWE839_connect_socket_01_bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,428 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE124_Buffer_Underwrite__CWE839_connect_socket_02.c | |||
| Label Definition File: CWE124_Buffer_Underwrite__CWE839.label.xml | |||
| Template File: sources-sinks-02.tmpl.c | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 124 Buffer Underwrite | |||
| * BadSource: connect_socket Read data using a connect socket (client side) | |||
| * GoodSource: Non-negative but less than 10 | |||
| * Sinks: | |||
| * GoodSink: Ensure the array index is valid | |||
| * BadSink : Improperly check the array index by not checking the lower bound | |||
| * Flow Variant: 02 Control flow: if(1) and if(0) | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #ifdef _WIN32 | |||
| #include <winsock2.h> | |||
| #include <windows.h> | |||
| #include <direct.h> | |||
| #pragma comment(lib, "ws2_32") /* include ws2_32.lib when linking */ | |||
| #define CLOSE_SOCKET closesocket | |||
| #else /* NOT _WIN32 */ | |||
| #include <sys/types.h> | |||
| #include <sys/socket.h> | |||
| #include <netinet/in.h> | |||
| #include <arpa/inet.h> | |||
| #include <unistd.h> | |||
| #define INVALID_SOCKET -1 | |||
| #define SOCKET_ERROR -1 | |||
| #define CLOSE_SOCKET close | |||
| #define SOCKET int | |||
| #endif | |||
| #define TCP_PORT 27015 | |||
| #define IP_ADDRESS "127.0.0.1" | |||
| #define CHAR_ARRAY_SIZE (3 * sizeof(data) + 2) | |||
| #ifndef OMITBAD | |||
| void CWE124_Buffer_Underwrite__CWE839_connect_socket_02_bad() | |||
| { | |||
| int data; | |||
| /* Initialize data */ | |||
| data = -1; | |||
| if(1) | |||
| { | |||
| { | |||
| #ifdef _WIN32 | |||
| WSADATA wsaData; | |||
| int wsaDataInit = 0; | |||
| #endif | |||
| int recvResult; | |||
| struct sockaddr_in service; | |||
| SOCKET connectSocket = INVALID_SOCKET; | |||
| char inputBuffer[CHAR_ARRAY_SIZE]; | |||
| do | |||
| { | |||
| #ifdef _WIN32 | |||
| if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| wsaDataInit = 1; | |||
| #endif | |||
| /* POTENTIAL FLAW: Read data using a connect socket */ | |||
| connectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |||
| if (connectSocket == INVALID_SOCKET) | |||
| { | |||
| break; | |||
| } | |||
| memset(&service, 0, sizeof(service)); | |||
| service.sin_family = AF_INET; | |||
| service.sin_addr.s_addr = inet_addr(IP_ADDRESS); | |||
| service.sin_port = htons(TCP_PORT); | |||
| if (connect(connectSocket, (struct sockaddr*)&service, sizeof(service)) == SOCKET_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| /* Abort on error or the connection was closed, make sure to recv one | |||
| * less char than is in the recv_buf in order to append a terminator */ | |||
| recvResult = recv(connectSocket, inputBuffer, CHAR_ARRAY_SIZE - 1, 0); | |||
| if (recvResult == SOCKET_ERROR || recvResult == 0) | |||
| { | |||
| break; | |||
| } | |||
| /* NUL-terminate the string */ | |||
| inputBuffer[recvResult] = '\0'; | |||
| /* Convert to int */ | |||
| data = atoi(inputBuffer); | |||
| } | |||
| while (0); | |||
| if (connectSocket != INVALID_SOCKET) | |||
| { | |||
| CLOSE_SOCKET(connectSocket); | |||
| } | |||
| #ifdef _WIN32 | |||
| if (wsaDataInit) | |||
| { | |||
| WSACleanup(); | |||
| } | |||
| #endif | |||
| } | |||
| } | |||
| if(1) | |||
| { | |||
| { | |||
| int i; | |||
| int buffer[10] = { 0 }; | |||
| /* POTENTIAL FLAW: Attempt to access a negative index of the array | |||
| * This code does not check to see if the array index is negative */ | |||
| if (data < 10) | |||
| { | |||
| buffer[data] = 1; | |||
| /* Print the array values */ | |||
| for(i = 0; i < 10; i++) | |||
| { | |||
| printIntLine(buffer[i]); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| printLine("ERROR: Array index is negative."); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* goodB2G1() - use badsource and goodsink by changing the second 1 to 0 */ | |||
| static void goodB2G1() | |||
| { | |||
| int data; | |||
| /* Initialize data */ | |||
| data = -1; | |||
| if(1) | |||
| { | |||
| { | |||
| #ifdef _WIN32 | |||
| WSADATA wsaData; | |||
| int wsaDataInit = 0; | |||
| #endif | |||
| int recvResult; | |||
| struct sockaddr_in service; | |||
| SOCKET connectSocket = INVALID_SOCKET; | |||
| char inputBuffer[CHAR_ARRAY_SIZE]; | |||
| do | |||
| { | |||
| #ifdef _WIN32 | |||
| if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| wsaDataInit = 1; | |||
| #endif | |||
| /* POTENTIAL FLAW: Read data using a connect socket */ | |||
| connectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |||
| if (connectSocket == INVALID_SOCKET) | |||
| { | |||
| break; | |||
| } | |||
| memset(&service, 0, sizeof(service)); | |||
| service.sin_family = AF_INET; | |||
| service.sin_addr.s_addr = inet_addr(IP_ADDRESS); | |||
| service.sin_port = htons(TCP_PORT); | |||
| if (connect(connectSocket, (struct sockaddr*)&service, sizeof(service)) == SOCKET_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| /* Abort on error or the connection was closed, make sure to recv one | |||
| * less char than is in the recv_buf in order to append a terminator */ | |||
| recvResult = recv(connectSocket, inputBuffer, CHAR_ARRAY_SIZE - 1, 0); | |||
| if (recvResult == SOCKET_ERROR || recvResult == 0) | |||
| { | |||
| break; | |||
| } | |||
| /* NUL-terminate the string */ | |||
| inputBuffer[recvResult] = '\0'; | |||
| /* Convert to int */ | |||
| data = atoi(inputBuffer); | |||
| } | |||
| while (0); | |||
| if (connectSocket != INVALID_SOCKET) | |||
| { | |||
| CLOSE_SOCKET(connectSocket); | |||
| } | |||
| #ifdef _WIN32 | |||
| if (wsaDataInit) | |||
| { | |||
| WSACleanup(); | |||
| } | |||
| #endif | |||
| } | |||
| } | |||
| if(0) | |||
| { | |||
| /* INCIDENTAL: CWE 561 Dead Code, the code below will never run */ | |||
| printLine("Benign, fixed string"); | |||
| } | |||
| else | |||
| { | |||
| { | |||
| int i; | |||
| int buffer[10] = { 0 }; | |||
| /* FIX: Properly validate the array index and prevent a buffer underwrite */ | |||
| if (data >= 0 && data < (10)) | |||
| { | |||
| buffer[data] = 1; | |||
| /* Print the array values */ | |||
| for(i = 0; i < 10; i++) | |||
| { | |||
| printIntLine(buffer[i]); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| printLine("ERROR: Array index is out-of-bounds"); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /* goodB2G2() - use badsource and goodsink by reversing the blocks in the second if */ | |||
| static void goodB2G2() | |||
| { | |||
| int data; | |||
| /* Initialize data */ | |||
| data = -1; | |||
| if(1) | |||
| { | |||
| { | |||
| #ifdef _WIN32 | |||
| WSADATA wsaData; | |||
| int wsaDataInit = 0; | |||
| #endif | |||
| int recvResult; | |||
| struct sockaddr_in service; | |||
| SOCKET connectSocket = INVALID_SOCKET; | |||
| char inputBuffer[CHAR_ARRAY_SIZE]; | |||
| do | |||
| { | |||
| #ifdef _WIN32 | |||
| if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| wsaDataInit = 1; | |||
| #endif | |||
| /* POTENTIAL FLAW: Read data using a connect socket */ | |||
| connectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |||
| if (connectSocket == INVALID_SOCKET) | |||
| { | |||
| break; | |||
| } | |||
| memset(&service, 0, sizeof(service)); | |||
| service.sin_family = AF_INET; | |||
| service.sin_addr.s_addr = inet_addr(IP_ADDRESS); | |||
| service.sin_port = htons(TCP_PORT); | |||
| if (connect(connectSocket, (struct sockaddr*)&service, sizeof(service)) == SOCKET_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| /* Abort on error or the connection was closed, make sure to recv one | |||
| * less char than is in the recv_buf in order to append a terminator */ | |||
| recvResult = recv(connectSocket, inputBuffer, CHAR_ARRAY_SIZE - 1, 0); | |||
| if (recvResult == SOCKET_ERROR || recvResult == 0) | |||
| { | |||
| break; | |||
| } | |||
| /* NUL-terminate the string */ | |||
| inputBuffer[recvResult] = '\0'; | |||
| /* Convert to int */ | |||
| data = atoi(inputBuffer); | |||
| } | |||
| while (0); | |||
| if (connectSocket != INVALID_SOCKET) | |||
| { | |||
| CLOSE_SOCKET(connectSocket); | |||
| } | |||
| #ifdef _WIN32 | |||
| if (wsaDataInit) | |||
| { | |||
| WSACleanup(); | |||
| } | |||
| #endif | |||
| } | |||
| } | |||
| if(1) | |||
| { | |||
| { | |||
| int i; | |||
| int buffer[10] = { 0 }; | |||
| /* FIX: Properly validate the array index and prevent a buffer underwrite */ | |||
| if (data >= 0 && data < (10)) | |||
| { | |||
| buffer[data] = 1; | |||
| /* Print the array values */ | |||
| for(i = 0; i < 10; i++) | |||
| { | |||
| printIntLine(buffer[i]); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| printLine("ERROR: Array index is out-of-bounds"); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /* goodG2B1() - use goodsource and badsink by changing the first 1 to 0 */ | |||
| static void goodG2B1() | |||
| { | |||
| int data; | |||
| /* Initialize data */ | |||
| data = -1; | |||
| if(0) | |||
| { | |||
| /* INCIDENTAL: CWE 561 Dead Code, the code below will never run */ | |||
| printLine("Benign, fixed string"); | |||
| } | |||
| else | |||
| { | |||
| /* FIX: Use a value greater than 0, but less than 10 to avoid attempting to | |||
| * access an index of the array in the sink that is out-of-bounds */ | |||
| data = 7; | |||
| } | |||
| if(1) | |||
| { | |||
| { | |||
| int i; | |||
| int buffer[10] = { 0 }; | |||
| /* POTENTIAL FLAW: Attempt to access a negative index of the array | |||
| * This code does not check to see if the array index is negative */ | |||
| if (data < 10) | |||
| { | |||
| buffer[data] = 1; | |||
| /* Print the array values */ | |||
| for(i = 0; i < 10; i++) | |||
| { | |||
| printIntLine(buffer[i]); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| printLine("ERROR: Array index is negative."); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /* goodG2B2() - use goodsource and badsink by reversing the blocks in the first if */ | |||
| static void goodG2B2() | |||
| { | |||
| int data; | |||
| /* Initialize data */ | |||
| data = -1; | |||
| if(1) | |||
| { | |||
| /* FIX: Use a value greater than 0, but less than 10 to avoid attempting to | |||
| * access an index of the array in the sink that is out-of-bounds */ | |||
| data = 7; | |||
| } | |||
| if(1) | |||
| { | |||
| { | |||
| int i; | |||
| int buffer[10] = { 0 }; | |||
| /* POTENTIAL FLAW: Attempt to access a negative index of the array | |||
| * This code does not check to see if the array index is negative */ | |||
| if (data < 10) | |||
| { | |||
| buffer[data] = 1; | |||
| /* Print the array values */ | |||
| for(i = 0; i < 10; i++) | |||
| { | |||
| printIntLine(buffer[i]); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| printLine("ERROR: Array index is negative."); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| void CWE124_Buffer_Underwrite__CWE839_connect_socket_02_good() | |||
| { | |||
| goodB2G1(); | |||
| goodB2G2(); | |||
| goodG2B1(); | |||
| goodG2B2(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| its own for testing or for building a binary to use in testing binary | |||
| analysis tools. It is not used when compiling all the testcases as one | |||
| application, which is how source code analysis tools are tested. */ | |||
| #ifdef INCLUDEMAIN | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| CWE124_Buffer_Underwrite__CWE839_connect_socket_02_good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| CWE124_Buffer_Underwrite__CWE839_connect_socket_02_bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,256 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE126_Buffer_Overread__CWE129_connect_socket_01.c | |||
| Label Definition File: CWE126_Buffer_Overread__CWE129.label.xml | |||
| Template File: sources-sinks-01.tmpl.c | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 126 Buffer Overread | |||
| * BadSource: connect_socket Read data using a connect socket (client side) | |||
| * GoodSource: Larger than zero but less than 10 | |||
| * Sinks: | |||
| * GoodSink: Ensure the array index is valid | |||
| * BadSink : Improperly check the array index by not checking the upper bound | |||
| * Flow Variant: 01 Baseline | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #ifdef _WIN32 | |||
| #include <winsock2.h> | |||
| #include <windows.h> | |||
| #include <direct.h> | |||
| #pragma comment(lib, "ws2_32") /* include ws2_32.lib when linking */ | |||
| #define CLOSE_SOCKET closesocket | |||
| #else /* NOT _WIN32 */ | |||
| #include <sys/types.h> | |||
| #include <sys/socket.h> | |||
| #include <netinet/in.h> | |||
| #include <arpa/inet.h> | |||
| #include <unistd.h> | |||
| #define INVALID_SOCKET -1 | |||
| #define SOCKET_ERROR -1 | |||
| #define CLOSE_SOCKET close | |||
| #define SOCKET int | |||
| #endif | |||
| #define TCP_PORT 27015 | |||
| #define IP_ADDRESS "127.0.0.1" | |||
| #define CHAR_ARRAY_SIZE (3 * sizeof(data) + 2) | |||
| #ifndef OMITBAD | |||
| void CWE126_Buffer_Overread__CWE129_connect_socket_01_bad() | |||
| { | |||
| int data; | |||
| /* Initialize data */ | |||
| data = -1; | |||
| { | |||
| #ifdef _WIN32 | |||
| WSADATA wsaData; | |||
| int wsaDataInit = 0; | |||
| #endif | |||
| int recvResult; | |||
| struct sockaddr_in service; | |||
| SOCKET connectSocket = INVALID_SOCKET; | |||
| char inputBuffer[CHAR_ARRAY_SIZE]; | |||
| do | |||
| { | |||
| #ifdef _WIN32 | |||
| if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| wsaDataInit = 1; | |||
| #endif | |||
| /* POTENTIAL FLAW: Read data using a connect socket */ | |||
| connectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |||
| if (connectSocket == INVALID_SOCKET) | |||
| { | |||
| break; | |||
| } | |||
| memset(&service, 0, sizeof(service)); | |||
| service.sin_family = AF_INET; | |||
| service.sin_addr.s_addr = inet_addr(IP_ADDRESS); | |||
| service.sin_port = htons(TCP_PORT); | |||
| if (connect(connectSocket, (struct sockaddr*)&service, sizeof(service)) == SOCKET_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| /* Abort on error or the connection was closed, make sure to recv one | |||
| * less char than is in the recv_buf in order to append a terminator */ | |||
| recvResult = recv(connectSocket, inputBuffer, CHAR_ARRAY_SIZE - 1, 0); | |||
| if (recvResult == SOCKET_ERROR || recvResult == 0) | |||
| { | |||
| break; | |||
| } | |||
| /* NUL-terminate the string */ | |||
| inputBuffer[recvResult] = '\0'; | |||
| /* Convert to int */ | |||
| data = atoi(inputBuffer); | |||
| } | |||
| while (0); | |||
| if (connectSocket != INVALID_SOCKET) | |||
| { | |||
| CLOSE_SOCKET(connectSocket); | |||
| } | |||
| #ifdef _WIN32 | |||
| if (wsaDataInit) | |||
| { | |||
| WSACleanup(); | |||
| } | |||
| #endif | |||
| } | |||
| { | |||
| int buffer[10] = { 0 }; | |||
| /* POTENTIAL FLAW: Attempt to access an index of the array that is above the upper bound | |||
| * This check does not check the upper bounds of the array index */ | |||
| if (data >= 0) | |||
| { | |||
| printIntLine(buffer[data]); | |||
| } | |||
| else | |||
| { | |||
| printLine("ERROR: Array index is negative"); | |||
| } | |||
| } | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* goodG2B uses the GoodSource with the BadSink */ | |||
| static void goodG2B() | |||
| { | |||
| int data; | |||
| /* Initialize data */ | |||
| data = -1; | |||
| /* FIX: Use a value greater than 0, but less than 10 to avoid attempting to | |||
| * access an index of the array in the sink that is out-of-bounds */ | |||
| data = 7; | |||
| { | |||
| int buffer[10] = { 0 }; | |||
| /* POTENTIAL FLAW: Attempt to access an index of the array that is above the upper bound | |||
| * This check does not check the upper bounds of the array index */ | |||
| if (data >= 0) | |||
| { | |||
| printIntLine(buffer[data]); | |||
| } | |||
| else | |||
| { | |||
| printLine("ERROR: Array index is negative"); | |||
| } | |||
| } | |||
| } | |||
| /* goodB2G uses the BadSource with the GoodSink */ | |||
| static void goodB2G() | |||
| { | |||
| int data; | |||
| /* Initialize data */ | |||
| data = -1; | |||
| { | |||
| #ifdef _WIN32 | |||
| WSADATA wsaData; | |||
| int wsaDataInit = 0; | |||
| #endif | |||
| int recvResult; | |||
| struct sockaddr_in service; | |||
| SOCKET connectSocket = INVALID_SOCKET; | |||
| char inputBuffer[CHAR_ARRAY_SIZE]; | |||
| do | |||
| { | |||
| #ifdef _WIN32 | |||
| if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| wsaDataInit = 1; | |||
| #endif | |||
| /* POTENTIAL FLAW: Read data using a connect socket */ | |||
| connectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |||
| if (connectSocket == INVALID_SOCKET) | |||
| { | |||
| break; | |||
| } | |||
| memset(&service, 0, sizeof(service)); | |||
| service.sin_family = AF_INET; | |||
| service.sin_addr.s_addr = inet_addr(IP_ADDRESS); | |||
| service.sin_port = htons(TCP_PORT); | |||
| if (connect(connectSocket, (struct sockaddr*)&service, sizeof(service)) == SOCKET_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| /* Abort on error or the connection was closed, make sure to recv one | |||
| * less char than is in the recv_buf in order to append a terminator */ | |||
| recvResult = recv(connectSocket, inputBuffer, CHAR_ARRAY_SIZE - 1, 0); | |||
| if (recvResult == SOCKET_ERROR || recvResult == 0) | |||
| { | |||
| break; | |||
| } | |||
| /* NUL-terminate the string */ | |||
| inputBuffer[recvResult] = '\0'; | |||
| /* Convert to int */ | |||
| data = atoi(inputBuffer); | |||
| } | |||
| while (0); | |||
| if (connectSocket != INVALID_SOCKET) | |||
| { | |||
| CLOSE_SOCKET(connectSocket); | |||
| } | |||
| #ifdef _WIN32 | |||
| if (wsaDataInit) | |||
| { | |||
| WSACleanup(); | |||
| } | |||
| #endif | |||
| } | |||
| { | |||
| int buffer[10] = { 0 }; | |||
| /* FIX: Properly validate the array index and prevent a buffer overread */ | |||
| if (data >= 0 && data < (10)) | |||
| { | |||
| printIntLine(buffer[data]); | |||
| } | |||
| else | |||
| { | |||
| printLine("ERROR: Array index is out-of-bounds"); | |||
| } | |||
| } | |||
| } | |||
| void CWE126_Buffer_Overread__CWE129_connect_socket_01_good() | |||
| { | |||
| goodG2B(); | |||
| goodB2G(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| its own for testing or for building a binary to use in testing binary | |||
| analysis tools. It is not used when compiling all the testcases as one | |||
| application, which is how source code analysis tools are tested. */ | |||
| #ifdef INCLUDEMAIN | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| CWE126_Buffer_Overread__CWE129_connect_socket_01_good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| CWE126_Buffer_Overread__CWE129_connect_socket_01_bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,398 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE126_Buffer_Overread__CWE129_connect_socket_02.c | |||
| Label Definition File: CWE126_Buffer_Overread__CWE129.label.xml | |||
| Template File: sources-sinks-02.tmpl.c | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 126 Buffer Overread | |||
| * BadSource: connect_socket Read data using a connect socket (client side) | |||
| * GoodSource: Larger than zero but less than 10 | |||
| * Sinks: | |||
| * GoodSink: Ensure the array index is valid | |||
| * BadSink : Improperly check the array index by not checking the upper bound | |||
| * Flow Variant: 02 Control flow: if(1) and if(0) | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #ifdef _WIN32 | |||
| #include <winsock2.h> | |||
| #include <windows.h> | |||
| #include <direct.h> | |||
| #pragma comment(lib, "ws2_32") /* include ws2_32.lib when linking */ | |||
| #define CLOSE_SOCKET closesocket | |||
| #else /* NOT _WIN32 */ | |||
| #include <sys/types.h> | |||
| #include <sys/socket.h> | |||
| #include <netinet/in.h> | |||
| #include <arpa/inet.h> | |||
| #include <unistd.h> | |||
| #define INVALID_SOCKET -1 | |||
| #define SOCKET_ERROR -1 | |||
| #define CLOSE_SOCKET close | |||
| #define SOCKET int | |||
| #endif | |||
| #define TCP_PORT 27015 | |||
| #define IP_ADDRESS "127.0.0.1" | |||
| #define CHAR_ARRAY_SIZE (3 * sizeof(data) + 2) | |||
| #ifndef OMITBAD | |||
| void CWE126_Buffer_Overread__CWE129_connect_socket_02_bad() | |||
| { | |||
| int data; | |||
| /* Initialize data */ | |||
| data = -1; | |||
| if(1) | |||
| { | |||
| { | |||
| #ifdef _WIN32 | |||
| WSADATA wsaData; | |||
| int wsaDataInit = 0; | |||
| #endif | |||
| int recvResult; | |||
| struct sockaddr_in service; | |||
| SOCKET connectSocket = INVALID_SOCKET; | |||
| char inputBuffer[CHAR_ARRAY_SIZE]; | |||
| do | |||
| { | |||
| #ifdef _WIN32 | |||
| if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| wsaDataInit = 1; | |||
| #endif | |||
| /* POTENTIAL FLAW: Read data using a connect socket */ | |||
| connectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |||
| if (connectSocket == INVALID_SOCKET) | |||
| { | |||
| break; | |||
| } | |||
| memset(&service, 0, sizeof(service)); | |||
| service.sin_family = AF_INET; | |||
| service.sin_addr.s_addr = inet_addr(IP_ADDRESS); | |||
| service.sin_port = htons(TCP_PORT); | |||
| if (connect(connectSocket, (struct sockaddr*)&service, sizeof(service)) == SOCKET_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| /* Abort on error or the connection was closed, make sure to recv one | |||
| * less char than is in the recv_buf in order to append a terminator */ | |||
| recvResult = recv(connectSocket, inputBuffer, CHAR_ARRAY_SIZE - 1, 0); | |||
| if (recvResult == SOCKET_ERROR || recvResult == 0) | |||
| { | |||
| break; | |||
| } | |||
| /* NUL-terminate the string */ | |||
| inputBuffer[recvResult] = '\0'; | |||
| /* Convert to int */ | |||
| data = atoi(inputBuffer); | |||
| } | |||
| while (0); | |||
| if (connectSocket != INVALID_SOCKET) | |||
| { | |||
| CLOSE_SOCKET(connectSocket); | |||
| } | |||
| #ifdef _WIN32 | |||
| if (wsaDataInit) | |||
| { | |||
| WSACleanup(); | |||
| } | |||
| #endif | |||
| } | |||
| } | |||
| if(1) | |||
| { | |||
| { | |||
| int buffer[10] = { 0 }; | |||
| /* POTENTIAL FLAW: Attempt to access an index of the array that is above the upper bound | |||
| * This check does not check the upper bounds of the array index */ | |||
| if (data >= 0) | |||
| { | |||
| printIntLine(buffer[data]); | |||
| } | |||
| else | |||
| { | |||
| printLine("ERROR: Array index is negative"); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* goodB2G1() - use badsource and goodsink by changing the second 1 to 0 */ | |||
| static void goodB2G1() | |||
| { | |||
| int data; | |||
| /* Initialize data */ | |||
| data = -1; | |||
| if(1) | |||
| { | |||
| { | |||
| #ifdef _WIN32 | |||
| WSADATA wsaData; | |||
| int wsaDataInit = 0; | |||
| #endif | |||
| int recvResult; | |||
| struct sockaddr_in service; | |||
| SOCKET connectSocket = INVALID_SOCKET; | |||
| char inputBuffer[CHAR_ARRAY_SIZE]; | |||
| do | |||
| { | |||
| #ifdef _WIN32 | |||
| if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| wsaDataInit = 1; | |||
| #endif | |||
| /* POTENTIAL FLAW: Read data using a connect socket */ | |||
| connectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |||
| if (connectSocket == INVALID_SOCKET) | |||
| { | |||
| break; | |||
| } | |||
| memset(&service, 0, sizeof(service)); | |||
| service.sin_family = AF_INET; | |||
| service.sin_addr.s_addr = inet_addr(IP_ADDRESS); | |||
| service.sin_port = htons(TCP_PORT); | |||
| if (connect(connectSocket, (struct sockaddr*)&service, sizeof(service)) == SOCKET_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| /* Abort on error or the connection was closed, make sure to recv one | |||
| * less char than is in the recv_buf in order to append a terminator */ | |||
| recvResult = recv(connectSocket, inputBuffer, CHAR_ARRAY_SIZE - 1, 0); | |||
| if (recvResult == SOCKET_ERROR || recvResult == 0) | |||
| { | |||
| break; | |||
| } | |||
| /* NUL-terminate the string */ | |||
| inputBuffer[recvResult] = '\0'; | |||
| /* Convert to int */ | |||
| data = atoi(inputBuffer); | |||
| } | |||
| while (0); | |||
| if (connectSocket != INVALID_SOCKET) | |||
| { | |||
| CLOSE_SOCKET(connectSocket); | |||
| } | |||
| #ifdef _WIN32 | |||
| if (wsaDataInit) | |||
| { | |||
| WSACleanup(); | |||
| } | |||
| #endif | |||
| } | |||
| } | |||
| if(0) | |||
| { | |||
| /* INCIDENTAL: CWE 561 Dead Code, the code below will never run */ | |||
| printLine("Benign, fixed string"); | |||
| } | |||
| else | |||
| { | |||
| { | |||
| int buffer[10] = { 0 }; | |||
| /* FIX: Properly validate the array index and prevent a buffer overread */ | |||
| if (data >= 0 && data < (10)) | |||
| { | |||
| printIntLine(buffer[data]); | |||
| } | |||
| else | |||
| { | |||
| printLine("ERROR: Array index is out-of-bounds"); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /* goodB2G2() - use badsource and goodsink by reversing the blocks in the second if */ | |||
| static void goodB2G2() | |||
| { | |||
| int data; | |||
| /* Initialize data */ | |||
| data = -1; | |||
| if(1) | |||
| { | |||
| { | |||
| #ifdef _WIN32 | |||
| WSADATA wsaData; | |||
| int wsaDataInit = 0; | |||
| #endif | |||
| int recvResult; | |||
| struct sockaddr_in service; | |||
| SOCKET connectSocket = INVALID_SOCKET; | |||
| char inputBuffer[CHAR_ARRAY_SIZE]; | |||
| do | |||
| { | |||
| #ifdef _WIN32 | |||
| if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| wsaDataInit = 1; | |||
| #endif | |||
| /* POTENTIAL FLAW: Read data using a connect socket */ | |||
| connectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |||
| if (connectSocket == INVALID_SOCKET) | |||
| { | |||
| break; | |||
| } | |||
| memset(&service, 0, sizeof(service)); | |||
| service.sin_family = AF_INET; | |||
| service.sin_addr.s_addr = inet_addr(IP_ADDRESS); | |||
| service.sin_port = htons(TCP_PORT); | |||
| if (connect(connectSocket, (struct sockaddr*)&service, sizeof(service)) == SOCKET_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| /* Abort on error or the connection was closed, make sure to recv one | |||
| * less char than is in the recv_buf in order to append a terminator */ | |||
| recvResult = recv(connectSocket, inputBuffer, CHAR_ARRAY_SIZE - 1, 0); | |||
| if (recvResult == SOCKET_ERROR || recvResult == 0) | |||
| { | |||
| break; | |||
| } | |||
| /* NUL-terminate the string */ | |||
| inputBuffer[recvResult] = '\0'; | |||
| /* Convert to int */ | |||
| data = atoi(inputBuffer); | |||
| } | |||
| while (0); | |||
| if (connectSocket != INVALID_SOCKET) | |||
| { | |||
| CLOSE_SOCKET(connectSocket); | |||
| } | |||
| #ifdef _WIN32 | |||
| if (wsaDataInit) | |||
| { | |||
| WSACleanup(); | |||
| } | |||
| #endif | |||
| } | |||
| } | |||
| if(1) | |||
| { | |||
| { | |||
| int buffer[10] = { 0 }; | |||
| /* FIX: Properly validate the array index and prevent a buffer overread */ | |||
| if (data >= 0 && data < (10)) | |||
| { | |||
| printIntLine(buffer[data]); | |||
| } | |||
| else | |||
| { | |||
| printLine("ERROR: Array index is out-of-bounds"); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /* goodG2B1() - use goodsource and badsink by changing the first 1 to 0 */ | |||
| static void goodG2B1() | |||
| { | |||
| int data; | |||
| /* Initialize data */ | |||
| data = -1; | |||
| if(0) | |||
| { | |||
| /* INCIDENTAL: CWE 561 Dead Code, the code below will never run */ | |||
| printLine("Benign, fixed string"); | |||
| } | |||
| else | |||
| { | |||
| /* FIX: Use a value greater than 0, but less than 10 to avoid attempting to | |||
| * access an index of the array in the sink that is out-of-bounds */ | |||
| data = 7; | |||
| } | |||
| if(1) | |||
| { | |||
| { | |||
| int buffer[10] = { 0 }; | |||
| /* POTENTIAL FLAW: Attempt to access an index of the array that is above the upper bound | |||
| * This check does not check the upper bounds of the array index */ | |||
| if (data >= 0) | |||
| { | |||
| printIntLine(buffer[data]); | |||
| } | |||
| else | |||
| { | |||
| printLine("ERROR: Array index is negative"); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /* goodG2B2() - use goodsource and badsink by reversing the blocks in the first if */ | |||
| static void goodG2B2() | |||
| { | |||
| int data; | |||
| /* Initialize data */ | |||
| data = -1; | |||
| if(1) | |||
| { | |||
| /* FIX: Use a value greater than 0, but less than 10 to avoid attempting to | |||
| * access an index of the array in the sink that is out-of-bounds */ | |||
| data = 7; | |||
| } | |||
| if(1) | |||
| { | |||
| { | |||
| int buffer[10] = { 0 }; | |||
| /* POTENTIAL FLAW: Attempt to access an index of the array that is above the upper bound | |||
| * This check does not check the upper bounds of the array index */ | |||
| if (data >= 0) | |||
| { | |||
| printIntLine(buffer[data]); | |||
| } | |||
| else | |||
| { | |||
| printLine("ERROR: Array index is negative"); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| void CWE126_Buffer_Overread__CWE129_connect_socket_02_good() | |||
| { | |||
| goodB2G1(); | |||
| goodB2G2(); | |||
| goodG2B1(); | |||
| goodG2B2(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| its own for testing or for building a binary to use in testing binary | |||
| analysis tools. It is not used when compiling all the testcases as one | |||
| application, which is how source code analysis tools are tested. */ | |||
| #ifdef INCLUDEMAIN | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| CWE126_Buffer_Overread__CWE129_connect_socket_02_good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| CWE126_Buffer_Overread__CWE129_connect_socket_02_bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,398 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE126_Buffer_Overread__CWE129_connect_socket_03.c | |||
| Label Definition File: CWE126_Buffer_Overread__CWE129.label.xml | |||
| Template File: sources-sinks-03.tmpl.c | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 126 Buffer Overread | |||
| * BadSource: connect_socket Read data using a connect socket (client side) | |||
| * GoodSource: Larger than zero but less than 10 | |||
| * Sinks: | |||
| * GoodSink: Ensure the array index is valid | |||
| * BadSink : Improperly check the array index by not checking the upper bound | |||
| * Flow Variant: 03 Control flow: if(5==5) and if(5!=5) | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #ifdef _WIN32 | |||
| #include <winsock2.h> | |||
| #include <windows.h> | |||
| #include <direct.h> | |||
| #pragma comment(lib, "ws2_32") /* include ws2_32.lib when linking */ | |||
| #define CLOSE_SOCKET closesocket | |||
| #else /* NOT _WIN32 */ | |||
| #include <sys/types.h> | |||
| #include <sys/socket.h> | |||
| #include <netinet/in.h> | |||
| #include <arpa/inet.h> | |||
| #include <unistd.h> | |||
| #define INVALID_SOCKET -1 | |||
| #define SOCKET_ERROR -1 | |||
| #define CLOSE_SOCKET close | |||
| #define SOCKET int | |||
| #endif | |||
| #define TCP_PORT 27015 | |||
| #define IP_ADDRESS "127.0.0.1" | |||
| #define CHAR_ARRAY_SIZE (3 * sizeof(data) + 2) | |||
| #ifndef OMITBAD | |||
| void CWE126_Buffer_Overread__CWE129_connect_socket_03_bad() | |||
| { | |||
| int data; | |||
| /* Initialize data */ | |||
| data = -1; | |||
| if(5==5) | |||
| { | |||
| { | |||
| #ifdef _WIN32 | |||
| WSADATA wsaData; | |||
| int wsaDataInit = 0; | |||
| #endif | |||
| int recvResult; | |||
| struct sockaddr_in service; | |||
| SOCKET connectSocket = INVALID_SOCKET; | |||
| char inputBuffer[CHAR_ARRAY_SIZE]; | |||
| do | |||
| { | |||
| #ifdef _WIN32 | |||
| if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| wsaDataInit = 1; | |||
| #endif | |||
| /* POTENTIAL FLAW: Read data using a connect socket */ | |||
| connectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |||
| if (connectSocket == INVALID_SOCKET) | |||
| { | |||
| break; | |||
| } | |||
| memset(&service, 0, sizeof(service)); | |||
| service.sin_family = AF_INET; | |||
| service.sin_addr.s_addr = inet_addr(IP_ADDRESS); | |||
| service.sin_port = htons(TCP_PORT); | |||
| if (connect(connectSocket, (struct sockaddr*)&service, sizeof(service)) == SOCKET_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| /* Abort on error or the connection was closed, make sure to recv one | |||
| * less char than is in the recv_buf in order to append a terminator */ | |||
| recvResult = recv(connectSocket, inputBuffer, CHAR_ARRAY_SIZE - 1, 0); | |||
| if (recvResult == SOCKET_ERROR || recvResult == 0) | |||
| { | |||
| break; | |||
| } | |||
| /* NUL-terminate the string */ | |||
| inputBuffer[recvResult] = '\0'; | |||
| /* Convert to int */ | |||
| data = atoi(inputBuffer); | |||
| } | |||
| while (0); | |||
| if (connectSocket != INVALID_SOCKET) | |||
| { | |||
| CLOSE_SOCKET(connectSocket); | |||
| } | |||
| #ifdef _WIN32 | |||
| if (wsaDataInit) | |||
| { | |||
| WSACleanup(); | |||
| } | |||
| #endif | |||
| } | |||
| } | |||
| if(5==5) | |||
| { | |||
| { | |||
| int buffer[10] = { 0 }; | |||
| /* POTENTIAL FLAW: Attempt to access an index of the array that is above the upper bound | |||
| * This check does not check the upper bounds of the array index */ | |||
| if (data >= 0) | |||
| { | |||
| printIntLine(buffer[data]); | |||
| } | |||
| else | |||
| { | |||
| printLine("ERROR: Array index is negative"); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* goodB2G1() - use badsource and goodsink by changing the second 5==5 to 5!=5 */ | |||
| static void goodB2G1() | |||
| { | |||
| int data; | |||
| /* Initialize data */ | |||
| data = -1; | |||
| if(5==5) | |||
| { | |||
| { | |||
| #ifdef _WIN32 | |||
| WSADATA wsaData; | |||
| int wsaDataInit = 0; | |||
| #endif | |||
| int recvResult; | |||
| struct sockaddr_in service; | |||
| SOCKET connectSocket = INVALID_SOCKET; | |||
| char inputBuffer[CHAR_ARRAY_SIZE]; | |||
| do | |||
| { | |||
| #ifdef _WIN32 | |||
| if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| wsaDataInit = 1; | |||
| #endif | |||
| /* POTENTIAL FLAW: Read data using a connect socket */ | |||
| connectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |||
| if (connectSocket == INVALID_SOCKET) | |||
| { | |||
| break; | |||
| } | |||
| memset(&service, 0, sizeof(service)); | |||
| service.sin_family = AF_INET; | |||
| service.sin_addr.s_addr = inet_addr(IP_ADDRESS); | |||
| service.sin_port = htons(TCP_PORT); | |||
| if (connect(connectSocket, (struct sockaddr*)&service, sizeof(service)) == SOCKET_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| /* Abort on error or the connection was closed, make sure to recv one | |||
| * less char than is in the recv_buf in order to append a terminator */ | |||
| recvResult = recv(connectSocket, inputBuffer, CHAR_ARRAY_SIZE - 1, 0); | |||
| if (recvResult == SOCKET_ERROR || recvResult == 0) | |||
| { | |||
| break; | |||
| } | |||
| /* NUL-terminate the string */ | |||
| inputBuffer[recvResult] = '\0'; | |||
| /* Convert to int */ | |||
| data = atoi(inputBuffer); | |||
| } | |||
| while (0); | |||
| if (connectSocket != INVALID_SOCKET) | |||
| { | |||
| CLOSE_SOCKET(connectSocket); | |||
| } | |||
| #ifdef _WIN32 | |||
| if (wsaDataInit) | |||
| { | |||
| WSACleanup(); | |||
| } | |||
| #endif | |||
| } | |||
| } | |||
| if(5!=5) | |||
| { | |||
| /* INCIDENTAL: CWE 561 Dead Code, the code below will never run */ | |||
| printLine("Benign, fixed string"); | |||
| } | |||
| else | |||
| { | |||
| { | |||
| int buffer[10] = { 0 }; | |||
| /* FIX: Properly validate the array index and prevent a buffer overread */ | |||
| if (data >= 0 && data < (10)) | |||
| { | |||
| printIntLine(buffer[data]); | |||
| } | |||
| else | |||
| { | |||
| printLine("ERROR: Array index is out-of-bounds"); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /* goodB2G2() - use badsource and goodsink by reversing the blocks in the second if */ | |||
| static void goodB2G2() | |||
| { | |||
| int data; | |||
| /* Initialize data */ | |||
| data = -1; | |||
| if(5==5) | |||
| { | |||
| { | |||
| #ifdef _WIN32 | |||
| WSADATA wsaData; | |||
| int wsaDataInit = 0; | |||
| #endif | |||
| int recvResult; | |||
| struct sockaddr_in service; | |||
| SOCKET connectSocket = INVALID_SOCKET; | |||
| char inputBuffer[CHAR_ARRAY_SIZE]; | |||
| do | |||
| { | |||
| #ifdef _WIN32 | |||
| if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| wsaDataInit = 1; | |||
| #endif | |||
| /* POTENTIAL FLAW: Read data using a connect socket */ | |||
| connectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |||
| if (connectSocket == INVALID_SOCKET) | |||
| { | |||
| break; | |||
| } | |||
| memset(&service, 0, sizeof(service)); | |||
| service.sin_family = AF_INET; | |||
| service.sin_addr.s_addr = inet_addr(IP_ADDRESS); | |||
| service.sin_port = htons(TCP_PORT); | |||
| if (connect(connectSocket, (struct sockaddr*)&service, sizeof(service)) == SOCKET_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| /* Abort on error or the connection was closed, make sure to recv one | |||
| * less char than is in the recv_buf in order to append a terminator */ | |||
| recvResult = recv(connectSocket, inputBuffer, CHAR_ARRAY_SIZE - 1, 0); | |||
| if (recvResult == SOCKET_ERROR || recvResult == 0) | |||
| { | |||
| break; | |||
| } | |||
| /* NUL-terminate the string */ | |||
| inputBuffer[recvResult] = '\0'; | |||
| /* Convert to int */ | |||
| data = atoi(inputBuffer); | |||
| } | |||
| while (0); | |||
| if (connectSocket != INVALID_SOCKET) | |||
| { | |||
| CLOSE_SOCKET(connectSocket); | |||
| } | |||
| #ifdef _WIN32 | |||
| if (wsaDataInit) | |||
| { | |||
| WSACleanup(); | |||
| } | |||
| #endif | |||
| } | |||
| } | |||
| if(5==5) | |||
| { | |||
| { | |||
| int buffer[10] = { 0 }; | |||
| /* FIX: Properly validate the array index and prevent a buffer overread */ | |||
| if (data >= 0 && data < (10)) | |||
| { | |||
| printIntLine(buffer[data]); | |||
| } | |||
| else | |||
| { | |||
| printLine("ERROR: Array index is out-of-bounds"); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /* goodG2B1() - use goodsource and badsink by changing the first 5==5 to 5!=5 */ | |||
| static void goodG2B1() | |||
| { | |||
| int data; | |||
| /* Initialize data */ | |||
| data = -1; | |||
| if(5!=5) | |||
| { | |||
| /* INCIDENTAL: CWE 561 Dead Code, the code below will never run */ | |||
| printLine("Benign, fixed string"); | |||
| } | |||
| else | |||
| { | |||
| /* FIX: Use a value greater than 0, but less than 10 to avoid attempting to | |||
| * access an index of the array in the sink that is out-of-bounds */ | |||
| data = 7; | |||
| } | |||
| if(5==5) | |||
| { | |||
| { | |||
| int buffer[10] = { 0 }; | |||
| /* POTENTIAL FLAW: Attempt to access an index of the array that is above the upper bound | |||
| * This check does not check the upper bounds of the array index */ | |||
| if (data >= 0) | |||
| { | |||
| printIntLine(buffer[data]); | |||
| } | |||
| else | |||
| { | |||
| printLine("ERROR: Array index is negative"); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /* goodG2B2() - use goodsource and badsink by reversing the blocks in the first if */ | |||
| static void goodG2B2() | |||
| { | |||
| int data; | |||
| /* Initialize data */ | |||
| data = -1; | |||
| if(5==5) | |||
| { | |||
| /* FIX: Use a value greater than 0, but less than 10 to avoid attempting to | |||
| * access an index of the array in the sink that is out-of-bounds */ | |||
| data = 7; | |||
| } | |||
| if(5==5) | |||
| { | |||
| { | |||
| int buffer[10] = { 0 }; | |||
| /* POTENTIAL FLAW: Attempt to access an index of the array that is above the upper bound | |||
| * This check does not check the upper bounds of the array index */ | |||
| if (data >= 0) | |||
| { | |||
| printIntLine(buffer[data]); | |||
| } | |||
| else | |||
| { | |||
| printLine("ERROR: Array index is negative"); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| void CWE126_Buffer_Overread__CWE129_connect_socket_03_good() | |||
| { | |||
| goodB2G1(); | |||
| goodB2G2(); | |||
| goodG2B1(); | |||
| goodG2B2(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| its own for testing or for building a binary to use in testing binary | |||
| analysis tools. It is not used when compiling all the testcases as one | |||
| application, which is how source code analysis tools are tested. */ | |||
| #ifdef INCLUDEMAIN | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| CWE126_Buffer_Overread__CWE129_connect_socket_03_good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| CWE126_Buffer_Overread__CWE129_connect_socket_03_bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,256 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE127_Buffer_Underread__CWE839_connect_socket_01.c | |||
| Label Definition File: CWE127_Buffer_Underread__CWE839.label.xml | |||
| Template File: sources-sinks-01.tmpl.c | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 127 Buffer Underread | |||
| * BadSource: connect_socket Read data using a connect socket (client side) | |||
| * GoodSource: Non-negative but less than 10 | |||
| * Sinks: | |||
| * GoodSink: Ensure the array index is valid | |||
| * BadSink : Improperly check the array index by not checking to see if the value is negative | |||
| * Flow Variant: 01 Baseline | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #ifdef _WIN32 | |||
| #include <winsock2.h> | |||
| #include <windows.h> | |||
| #include <direct.h> | |||
| #pragma comment(lib, "ws2_32") /* include ws2_32.lib when linking */ | |||
| #define CLOSE_SOCKET closesocket | |||
| #else /* NOT _WIN32 */ | |||
| #include <sys/types.h> | |||
| #include <sys/socket.h> | |||
| #include <netinet/in.h> | |||
| #include <arpa/inet.h> | |||
| #include <unistd.h> | |||
| #define INVALID_SOCKET -1 | |||
| #define SOCKET_ERROR -1 | |||
| #define CLOSE_SOCKET close | |||
| #define SOCKET int | |||
| #endif | |||
| #define TCP_PORT 27015 | |||
| #define IP_ADDRESS "127.0.0.1" | |||
| #define CHAR_ARRAY_SIZE (3 * sizeof(data) + 2) | |||
| #ifndef OMITBAD | |||
| void CWE127_Buffer_Underread__CWE839_connect_socket_01_bad() | |||
| { | |||
| int data; | |||
| /* Initialize data */ | |||
| data = -1; | |||
| { | |||
| #ifdef _WIN32 | |||
| WSADATA wsaData; | |||
| int wsaDataInit = 0; | |||
| #endif | |||
| int recvResult; | |||
| struct sockaddr_in service; | |||
| SOCKET connectSocket = INVALID_SOCKET; | |||
| char inputBuffer[CHAR_ARRAY_SIZE]; | |||
| do | |||
| { | |||
| #ifdef _WIN32 | |||
| if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| wsaDataInit = 1; | |||
| #endif | |||
| /* POTENTIAL FLAW: Read data using a connect socket */ | |||
| connectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |||
| if (connectSocket == INVALID_SOCKET) | |||
| { | |||
| break; | |||
| } | |||
| memset(&service, 0, sizeof(service)); | |||
| service.sin_family = AF_INET; | |||
| service.sin_addr.s_addr = inet_addr(IP_ADDRESS); | |||
| service.sin_port = htons(TCP_PORT); | |||
| if (connect(connectSocket, (struct sockaddr*)&service, sizeof(service)) == SOCKET_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| /* Abort on error or the connection was closed, make sure to recv one | |||
| * less char than is in the recv_buf in order to append a terminator */ | |||
| recvResult = recv(connectSocket, inputBuffer, CHAR_ARRAY_SIZE - 1, 0); | |||
| if (recvResult == SOCKET_ERROR || recvResult == 0) | |||
| { | |||
| break; | |||
| } | |||
| /* NUL-terminate the string */ | |||
| inputBuffer[recvResult] = '\0'; | |||
| /* Convert to int */ | |||
| data = atoi(inputBuffer); | |||
| } | |||
| while (0); | |||
| if (connectSocket != INVALID_SOCKET) | |||
| { | |||
| CLOSE_SOCKET(connectSocket); | |||
| } | |||
| #ifdef _WIN32 | |||
| if (wsaDataInit) | |||
| { | |||
| WSACleanup(); | |||
| } | |||
| #endif | |||
| } | |||
| { | |||
| int buffer[10] = { 0 }; | |||
| /* POTENTIAL FLAW: Attempt to access a negative index of the array | |||
| * This check does not check to see if the array index is negative */ | |||
| if (data < 10) | |||
| { | |||
| printIntLine(buffer[data]); | |||
| } | |||
| else | |||
| { | |||
| printLine("ERROR: Array index is too big."); | |||
| } | |||
| } | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* goodG2B uses the GoodSource with the BadSink */ | |||
| static void goodG2B() | |||
| { | |||
| int data; | |||
| /* Initialize data */ | |||
| data = -1; | |||
| /* FIX: Use a value greater than 0, but less than 10 to avoid attempting to | |||
| * access an index of the array in the sink that is out-of-bounds */ | |||
| data = 7; | |||
| { | |||
| int buffer[10] = { 0 }; | |||
| /* POTENTIAL FLAW: Attempt to access a negative index of the array | |||
| * This check does not check to see if the array index is negative */ | |||
| if (data < 10) | |||
| { | |||
| printIntLine(buffer[data]); | |||
| } | |||
| else | |||
| { | |||
| printLine("ERROR: Array index is too big."); | |||
| } | |||
| } | |||
| } | |||
| /* goodB2G uses the BadSource with the GoodSink */ | |||
| static void goodB2G() | |||
| { | |||
| int data; | |||
| /* Initialize data */ | |||
| data = -1; | |||
| { | |||
| #ifdef _WIN32 | |||
| WSADATA wsaData; | |||
| int wsaDataInit = 0; | |||
| #endif | |||
| int recvResult; | |||
| struct sockaddr_in service; | |||
| SOCKET connectSocket = INVALID_SOCKET; | |||
| char inputBuffer[CHAR_ARRAY_SIZE]; | |||
| do | |||
| { | |||
| #ifdef _WIN32 | |||
| if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| wsaDataInit = 1; | |||
| #endif | |||
| /* POTENTIAL FLAW: Read data using a connect socket */ | |||
| connectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |||
| if (connectSocket == INVALID_SOCKET) | |||
| { | |||
| break; | |||
| } | |||
| memset(&service, 0, sizeof(service)); | |||
| service.sin_family = AF_INET; | |||
| service.sin_addr.s_addr = inet_addr(IP_ADDRESS); | |||
| service.sin_port = htons(TCP_PORT); | |||
| if (connect(connectSocket, (struct sockaddr*)&service, sizeof(service)) == SOCKET_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| /* Abort on error or the connection was closed, make sure to recv one | |||
| * less char than is in the recv_buf in order to append a terminator */ | |||
| recvResult = recv(connectSocket, inputBuffer, CHAR_ARRAY_SIZE - 1, 0); | |||
| if (recvResult == SOCKET_ERROR || recvResult == 0) | |||
| { | |||
| break; | |||
| } | |||
| /* NUL-terminate the string */ | |||
| inputBuffer[recvResult] = '\0'; | |||
| /* Convert to int */ | |||
| data = atoi(inputBuffer); | |||
| } | |||
| while (0); | |||
| if (connectSocket != INVALID_SOCKET) | |||
| { | |||
| CLOSE_SOCKET(connectSocket); | |||
| } | |||
| #ifdef _WIN32 | |||
| if (wsaDataInit) | |||
| { | |||
| WSACleanup(); | |||
| } | |||
| #endif | |||
| } | |||
| { | |||
| int buffer[10] = { 0 }; | |||
| /* FIX: Properly validate the array index and prevent a buffer underread */ | |||
| if (data >= 0 && data < (10)) | |||
| { | |||
| printIntLine(buffer[data]); | |||
| } | |||
| else | |||
| { | |||
| printLine("ERROR: Array index is out-of-bounds"); | |||
| } | |||
| } | |||
| } | |||
| void CWE127_Buffer_Underread__CWE839_connect_socket_01_good() | |||
| { | |||
| goodG2B(); | |||
| goodB2G(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| its own for testing or for building a binary to use in testing binary | |||
| analysis tools. It is not used when compiling all the testcases as one | |||
| application, which is how source code analysis tools are tested. */ | |||
| #ifdef INCLUDEMAIN | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| CWE127_Buffer_Underread__CWE839_connect_socket_01_good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| CWE127_Buffer_Underread__CWE839_connect_socket_01_bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,398 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE127_Buffer_Underread__CWE839_connect_socket_02.c | |||
| Label Definition File: CWE127_Buffer_Underread__CWE839.label.xml | |||
| Template File: sources-sinks-02.tmpl.c | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 127 Buffer Underread | |||
| * BadSource: connect_socket Read data using a connect socket (client side) | |||
| * GoodSource: Non-negative but less than 10 | |||
| * Sinks: | |||
| * GoodSink: Ensure the array index is valid | |||
| * BadSink : Improperly check the array index by not checking to see if the value is negative | |||
| * Flow Variant: 02 Control flow: if(1) and if(0) | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #ifdef _WIN32 | |||
| #include <winsock2.h> | |||
| #include <windows.h> | |||
| #include <direct.h> | |||
| #pragma comment(lib, "ws2_32") /* include ws2_32.lib when linking */ | |||
| #define CLOSE_SOCKET closesocket | |||
| #else /* NOT _WIN32 */ | |||
| #include <sys/types.h> | |||
| #include <sys/socket.h> | |||
| #include <netinet/in.h> | |||
| #include <arpa/inet.h> | |||
| #include <unistd.h> | |||
| #define INVALID_SOCKET -1 | |||
| #define SOCKET_ERROR -1 | |||
| #define CLOSE_SOCKET close | |||
| #define SOCKET int | |||
| #endif | |||
| #define TCP_PORT 27015 | |||
| #define IP_ADDRESS "127.0.0.1" | |||
| #define CHAR_ARRAY_SIZE (3 * sizeof(data) + 2) | |||
| #ifndef OMITBAD | |||
| void CWE127_Buffer_Underread__CWE839_connect_socket_02_bad() | |||
| { | |||
| int data; | |||
| /* Initialize data */ | |||
| data = -1; | |||
| if(1) | |||
| { | |||
| { | |||
| #ifdef _WIN32 | |||
| WSADATA wsaData; | |||
| int wsaDataInit = 0; | |||
| #endif | |||
| int recvResult; | |||
| struct sockaddr_in service; | |||
| SOCKET connectSocket = INVALID_SOCKET; | |||
| char inputBuffer[CHAR_ARRAY_SIZE]; | |||
| do | |||
| { | |||
| #ifdef _WIN32 | |||
| if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| wsaDataInit = 1; | |||
| #endif | |||
| /* POTENTIAL FLAW: Read data using a connect socket */ | |||
| connectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |||
| if (connectSocket == INVALID_SOCKET) | |||
| { | |||
| break; | |||
| } | |||
| memset(&service, 0, sizeof(service)); | |||
| service.sin_family = AF_INET; | |||
| service.sin_addr.s_addr = inet_addr(IP_ADDRESS); | |||
| service.sin_port = htons(TCP_PORT); | |||
| if (connect(connectSocket, (struct sockaddr*)&service, sizeof(service)) == SOCKET_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| /* Abort on error or the connection was closed, make sure to recv one | |||
| * less char than is in the recv_buf in order to append a terminator */ | |||
| recvResult = recv(connectSocket, inputBuffer, CHAR_ARRAY_SIZE - 1, 0); | |||
| if (recvResult == SOCKET_ERROR || recvResult == 0) | |||
| { | |||
| break; | |||
| } | |||
| /* NUL-terminate the string */ | |||
| inputBuffer[recvResult] = '\0'; | |||
| /* Convert to int */ | |||
| data = atoi(inputBuffer); | |||
| } | |||
| while (0); | |||
| if (connectSocket != INVALID_SOCKET) | |||
| { | |||
| CLOSE_SOCKET(connectSocket); | |||
| } | |||
| #ifdef _WIN32 | |||
| if (wsaDataInit) | |||
| { | |||
| WSACleanup(); | |||
| } | |||
| #endif | |||
| } | |||
| } | |||
| if(1) | |||
| { | |||
| { | |||
| int buffer[10] = { 0 }; | |||
| /* POTENTIAL FLAW: Attempt to access a negative index of the array | |||
| * This check does not check to see if the array index is negative */ | |||
| if (data < 10) | |||
| { | |||
| printIntLine(buffer[data]); | |||
| } | |||
| else | |||
| { | |||
| printLine("ERROR: Array index is too big."); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* goodB2G1() - use badsource and goodsink by changing the second 1 to 0 */ | |||
| static void goodB2G1() | |||
| { | |||
| int data; | |||
| /* Initialize data */ | |||
| data = -1; | |||
| if(1) | |||
| { | |||
| { | |||
| #ifdef _WIN32 | |||
| WSADATA wsaData; | |||
| int wsaDataInit = 0; | |||
| #endif | |||
| int recvResult; | |||
| struct sockaddr_in service; | |||
| SOCKET connectSocket = INVALID_SOCKET; | |||
| char inputBuffer[CHAR_ARRAY_SIZE]; | |||
| do | |||
| { | |||
| #ifdef _WIN32 | |||
| if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| wsaDataInit = 1; | |||
| #endif | |||
| /* POTENTIAL FLAW: Read data using a connect socket */ | |||
| connectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |||
| if (connectSocket == INVALID_SOCKET) | |||
| { | |||
| break; | |||
| } | |||
| memset(&service, 0, sizeof(service)); | |||
| service.sin_family = AF_INET; | |||
| service.sin_addr.s_addr = inet_addr(IP_ADDRESS); | |||
| service.sin_port = htons(TCP_PORT); | |||
| if (connect(connectSocket, (struct sockaddr*)&service, sizeof(service)) == SOCKET_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| /* Abort on error or the connection was closed, make sure to recv one | |||
| * less char than is in the recv_buf in order to append a terminator */ | |||
| recvResult = recv(connectSocket, inputBuffer, CHAR_ARRAY_SIZE - 1, 0); | |||
| if (recvResult == SOCKET_ERROR || recvResult == 0) | |||
| { | |||
| break; | |||
| } | |||
| /* NUL-terminate the string */ | |||
| inputBuffer[recvResult] = '\0'; | |||
| /* Convert to int */ | |||
| data = atoi(inputBuffer); | |||
| } | |||
| while (0); | |||
| if (connectSocket != INVALID_SOCKET) | |||
| { | |||
| CLOSE_SOCKET(connectSocket); | |||
| } | |||
| #ifdef _WIN32 | |||
| if (wsaDataInit) | |||
| { | |||
| WSACleanup(); | |||
| } | |||
| #endif | |||
| } | |||
| } | |||
| if(0) | |||
| { | |||
| /* INCIDENTAL: CWE 561 Dead Code, the code below will never run */ | |||
| printLine("Benign, fixed string"); | |||
| } | |||
| else | |||
| { | |||
| { | |||
| int buffer[10] = { 0 }; | |||
| /* FIX: Properly validate the array index and prevent a buffer underread */ | |||
| if (data >= 0 && data < (10)) | |||
| { | |||
| printIntLine(buffer[data]); | |||
| } | |||
| else | |||
| { | |||
| printLine("ERROR: Array index is out-of-bounds"); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /* goodB2G2() - use badsource and goodsink by reversing the blocks in the second if */ | |||
| static void goodB2G2() | |||
| { | |||
| int data; | |||
| /* Initialize data */ | |||
| data = -1; | |||
| if(1) | |||
| { | |||
| { | |||
| #ifdef _WIN32 | |||
| WSADATA wsaData; | |||
| int wsaDataInit = 0; | |||
| #endif | |||
| int recvResult; | |||
| struct sockaddr_in service; | |||
| SOCKET connectSocket = INVALID_SOCKET; | |||
| char inputBuffer[CHAR_ARRAY_SIZE]; | |||
| do | |||
| { | |||
| #ifdef _WIN32 | |||
| if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| wsaDataInit = 1; | |||
| #endif | |||
| /* POTENTIAL FLAW: Read data using a connect socket */ | |||
| connectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |||
| if (connectSocket == INVALID_SOCKET) | |||
| { | |||
| break; | |||
| } | |||
| memset(&service, 0, sizeof(service)); | |||
| service.sin_family = AF_INET; | |||
| service.sin_addr.s_addr = inet_addr(IP_ADDRESS); | |||
| service.sin_port = htons(TCP_PORT); | |||
| if (connect(connectSocket, (struct sockaddr*)&service, sizeof(service)) == SOCKET_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| /* Abort on error or the connection was closed, make sure to recv one | |||
| * less char than is in the recv_buf in order to append a terminator */ | |||
| recvResult = recv(connectSocket, inputBuffer, CHAR_ARRAY_SIZE - 1, 0); | |||
| if (recvResult == SOCKET_ERROR || recvResult == 0) | |||
| { | |||
| break; | |||
| } | |||
| /* NUL-terminate the string */ | |||
| inputBuffer[recvResult] = '\0'; | |||
| /* Convert to int */ | |||
| data = atoi(inputBuffer); | |||
| } | |||
| while (0); | |||
| if (connectSocket != INVALID_SOCKET) | |||
| { | |||
| CLOSE_SOCKET(connectSocket); | |||
| } | |||
| #ifdef _WIN32 | |||
| if (wsaDataInit) | |||
| { | |||
| WSACleanup(); | |||
| } | |||
| #endif | |||
| } | |||
| } | |||
| if(1) | |||
| { | |||
| { | |||
| int buffer[10] = { 0 }; | |||
| /* FIX: Properly validate the array index and prevent a buffer underread */ | |||
| if (data >= 0 && data < (10)) | |||
| { | |||
| printIntLine(buffer[data]); | |||
| } | |||
| else | |||
| { | |||
| printLine("ERROR: Array index is out-of-bounds"); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /* goodG2B1() - use goodsource and badsink by changing the first 1 to 0 */ | |||
| static void goodG2B1() | |||
| { | |||
| int data; | |||
| /* Initialize data */ | |||
| data = -1; | |||
| if(0) | |||
| { | |||
| /* INCIDENTAL: CWE 561 Dead Code, the code below will never run */ | |||
| printLine("Benign, fixed string"); | |||
| } | |||
| else | |||
| { | |||
| /* FIX: Use a value greater than 0, but less than 10 to avoid attempting to | |||
| * access an index of the array in the sink that is out-of-bounds */ | |||
| data = 7; | |||
| } | |||
| if(1) | |||
| { | |||
| { | |||
| int buffer[10] = { 0 }; | |||
| /* POTENTIAL FLAW: Attempt to access a negative index of the array | |||
| * This check does not check to see if the array index is negative */ | |||
| if (data < 10) | |||
| { | |||
| printIntLine(buffer[data]); | |||
| } | |||
| else | |||
| { | |||
| printLine("ERROR: Array index is too big."); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /* goodG2B2() - use goodsource and badsink by reversing the blocks in the first if */ | |||
| static void goodG2B2() | |||
| { | |||
| int data; | |||
| /* Initialize data */ | |||
| data = -1; | |||
| if(1) | |||
| { | |||
| /* FIX: Use a value greater than 0, but less than 10 to avoid attempting to | |||
| * access an index of the array in the sink that is out-of-bounds */ | |||
| data = 7; | |||
| } | |||
| if(1) | |||
| { | |||
| { | |||
| int buffer[10] = { 0 }; | |||
| /* POTENTIAL FLAW: Attempt to access a negative index of the array | |||
| * This check does not check to see if the array index is negative */ | |||
| if (data < 10) | |||
| { | |||
| printIntLine(buffer[data]); | |||
| } | |||
| else | |||
| { | |||
| printLine("ERROR: Array index is too big."); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| void CWE127_Buffer_Underread__CWE839_connect_socket_02_good() | |||
| { | |||
| goodB2G1(); | |||
| goodB2G2(); | |||
| goodG2B1(); | |||
| goodG2B2(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| its own for testing or for building a binary to use in testing binary | |||
| analysis tools. It is not used when compiling all the testcases as one | |||
| application, which is how source code analysis tools are tested. */ | |||
| #ifdef INCLUDEMAIN | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| CWE127_Buffer_Underread__CWE839_connect_socket_02_good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| CWE127_Buffer_Underread__CWE839_connect_socket_02_bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,379 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE134_Uncontrolled_Format_String__char_connect_socket_fprintf_02.c | |||
| Label Definition File: CWE134_Uncontrolled_Format_String.label.xml | |||
| Template File: sources-sinks-02.tmpl.c | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 134 Uncontrolled Format String | |||
| * BadSource: connect_socket Read data using a connect socket (client side) | |||
| * GoodSource: Copy a fixed string into data | |||
| * Sinks: fprintf | |||
| * GoodSink: fprintf with "%s" as the second argument and data as the third | |||
| * BadSink : fprintf with data as the second argument | |||
| * Flow Variant: 02 Control flow: if(1) and if(0) | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #ifndef _WIN32 | |||
| #include <wchar.h> | |||
| #endif | |||
| #ifdef _WIN32 | |||
| #include <winsock2.h> | |||
| #include <windows.h> | |||
| #include <direct.h> | |||
| #pragma comment(lib, "ws2_32") /* include ws2_32.lib when linking */ | |||
| #define CLOSE_SOCKET closesocket | |||
| #else /* NOT _WIN32 */ | |||
| #include <sys/types.h> | |||
| #include <sys/socket.h> | |||
| #include <netinet/in.h> | |||
| #include <arpa/inet.h> | |||
| #include <unistd.h> | |||
| #define INVALID_SOCKET -1 | |||
| #define SOCKET_ERROR -1 | |||
| #define CLOSE_SOCKET close | |||
| #define SOCKET int | |||
| #endif | |||
| #define TCP_PORT 27015 | |||
| #define IP_ADDRESS "127.0.0.1" | |||
| #ifndef OMITBAD | |||
| void CWE134_Uncontrolled_Format_String__char_connect_socket_fprintf_02_bad() | |||
| { | |||
| char * data; | |||
| char dataBuffer[100] = ""; | |||
| data = dataBuffer; | |||
| if(1) | |||
| { | |||
| { | |||
| #ifdef _WIN32 | |||
| WSADATA wsaData; | |||
| int wsaDataInit = 0; | |||
| #endif | |||
| int recvResult; | |||
| struct sockaddr_in service; | |||
| char *replace; | |||
| SOCKET connectSocket = INVALID_SOCKET; | |||
| size_t dataLen = strlen(data); | |||
| do | |||
| { | |||
| #ifdef _WIN32 | |||
| if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| wsaDataInit = 1; | |||
| #endif | |||
| /* POTENTIAL FLAW: Read data using a connect socket */ | |||
| connectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |||
| if (connectSocket == INVALID_SOCKET) | |||
| { | |||
| break; | |||
| } | |||
| memset(&service, 0, sizeof(service)); | |||
| service.sin_family = AF_INET; | |||
| service.sin_addr.s_addr = inet_addr(IP_ADDRESS); | |||
| service.sin_port = htons(TCP_PORT); | |||
| if (connect(connectSocket, (struct sockaddr*)&service, sizeof(service)) == SOCKET_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| /* Abort on error or the connection was closed, make sure to recv one | |||
| * less char than is in the recv_buf in order to append a terminator */ | |||
| /* Abort on error or the connection was closed */ | |||
| recvResult = recv(connectSocket, (char *)(data + dataLen), sizeof(char) * (100 - dataLen - 1), 0); | |||
| if (recvResult == SOCKET_ERROR || recvResult == 0) | |||
| { | |||
| break; | |||
| } | |||
| /* Append null terminator */ | |||
| data[dataLen + recvResult / sizeof(char)] = '\0'; | |||
| /* Eliminate CRLF */ | |||
| replace = strchr(data, '\r'); | |||
| if (replace) | |||
| { | |||
| *replace = '\0'; | |||
| } | |||
| replace = strchr(data, '\n'); | |||
| if (replace) | |||
| { | |||
| *replace = '\0'; | |||
| } | |||
| } | |||
| while (0); | |||
| if (connectSocket != INVALID_SOCKET) | |||
| { | |||
| CLOSE_SOCKET(connectSocket); | |||
| } | |||
| #ifdef _WIN32 | |||
| if (wsaDataInit) | |||
| { | |||
| WSACleanup(); | |||
| } | |||
| #endif | |||
| } | |||
| } | |||
| if(1) | |||
| { | |||
| /* POTENTIAL FLAW: Do not specify the format allowing a possible format string vulnerability */ | |||
| fprintf(stdout, data); | |||
| } | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* goodB2G1() - use badsource and goodsink by changing the second 1 to 0 */ | |||
| static void goodB2G1() | |||
| { | |||
| char * data; | |||
| char dataBuffer[100] = ""; | |||
| data = dataBuffer; | |||
| if(1) | |||
| { | |||
| { | |||
| #ifdef _WIN32 | |||
| WSADATA wsaData; | |||
| int wsaDataInit = 0; | |||
| #endif | |||
| int recvResult; | |||
| struct sockaddr_in service; | |||
| char *replace; | |||
| SOCKET connectSocket = INVALID_SOCKET; | |||
| size_t dataLen = strlen(data); | |||
| do | |||
| { | |||
| #ifdef _WIN32 | |||
| if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| wsaDataInit = 1; | |||
| #endif | |||
| /* POTENTIAL FLAW: Read data using a connect socket */ | |||
| connectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |||
| if (connectSocket == INVALID_SOCKET) | |||
| { | |||
| break; | |||
| } | |||
| memset(&service, 0, sizeof(service)); | |||
| service.sin_family = AF_INET; | |||
| service.sin_addr.s_addr = inet_addr(IP_ADDRESS); | |||
| service.sin_port = htons(TCP_PORT); | |||
| if (connect(connectSocket, (struct sockaddr*)&service, sizeof(service)) == SOCKET_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| /* Abort on error or the connection was closed, make sure to recv one | |||
| * less char than is in the recv_buf in order to append a terminator */ | |||
| /* Abort on error or the connection was closed */ | |||
| recvResult = recv(connectSocket, (char *)(data + dataLen), sizeof(char) * (100 - dataLen - 1), 0); | |||
| if (recvResult == SOCKET_ERROR || recvResult == 0) | |||
| { | |||
| break; | |||
| } | |||
| /* Append null terminator */ | |||
| data[dataLen + recvResult / sizeof(char)] = '\0'; | |||
| /* Eliminate CRLF */ | |||
| replace = strchr(data, '\r'); | |||
| if (replace) | |||
| { | |||
| *replace = '\0'; | |||
| } | |||
| replace = strchr(data, '\n'); | |||
| if (replace) | |||
| { | |||
| *replace = '\0'; | |||
| } | |||
| } | |||
| while (0); | |||
| if (connectSocket != INVALID_SOCKET) | |||
| { | |||
| CLOSE_SOCKET(connectSocket); | |||
| } | |||
| #ifdef _WIN32 | |||
| if (wsaDataInit) | |||
| { | |||
| WSACleanup(); | |||
| } | |||
| #endif | |||
| } | |||
| } | |||
| if(0) | |||
| { | |||
| /* INCIDENTAL: CWE 561 Dead Code, the code below will never run */ | |||
| printLine("Benign, fixed string"); | |||
| } | |||
| else | |||
| { | |||
| /* FIX: Specify the format disallowing a format string vulnerability */ | |||
| fprintf(stdout, "%s\n", data); | |||
| } | |||
| } | |||
| /* goodB2G2() - use badsource and goodsink by reversing the blocks in the second if */ | |||
| static void goodB2G2() | |||
| { | |||
| char * data; | |||
| char dataBuffer[100] = ""; | |||
| data = dataBuffer; | |||
| if(1) | |||
| { | |||
| { | |||
| #ifdef _WIN32 | |||
| WSADATA wsaData; | |||
| int wsaDataInit = 0; | |||
| #endif | |||
| int recvResult; | |||
| struct sockaddr_in service; | |||
| char *replace; | |||
| SOCKET connectSocket = INVALID_SOCKET; | |||
| size_t dataLen = strlen(data); | |||
| do | |||
| { | |||
| #ifdef _WIN32 | |||
| if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| wsaDataInit = 1; | |||
| #endif | |||
| /* POTENTIAL FLAW: Read data using a connect socket */ | |||
| connectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |||
| if (connectSocket == INVALID_SOCKET) | |||
| { | |||
| break; | |||
| } | |||
| memset(&service, 0, sizeof(service)); | |||
| service.sin_family = AF_INET; | |||
| service.sin_addr.s_addr = inet_addr(IP_ADDRESS); | |||
| service.sin_port = htons(TCP_PORT); | |||
| if (connect(connectSocket, (struct sockaddr*)&service, sizeof(service)) == SOCKET_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| /* Abort on error or the connection was closed, make sure to recv one | |||
| * less char than is in the recv_buf in order to append a terminator */ | |||
| /* Abort on error or the connection was closed */ | |||
| recvResult = recv(connectSocket, (char *)(data + dataLen), sizeof(char) * (100 - dataLen - 1), 0); | |||
| if (recvResult == SOCKET_ERROR || recvResult == 0) | |||
| { | |||
| break; | |||
| } | |||
| /* Append null terminator */ | |||
| data[dataLen + recvResult / sizeof(char)] = '\0'; | |||
| /* Eliminate CRLF */ | |||
| replace = strchr(data, '\r'); | |||
| if (replace) | |||
| { | |||
| *replace = '\0'; | |||
| } | |||
| replace = strchr(data, '\n'); | |||
| if (replace) | |||
| { | |||
| *replace = '\0'; | |||
| } | |||
| } | |||
| while (0); | |||
| if (connectSocket != INVALID_SOCKET) | |||
| { | |||
| CLOSE_SOCKET(connectSocket); | |||
| } | |||
| #ifdef _WIN32 | |||
| if (wsaDataInit) | |||
| { | |||
| WSACleanup(); | |||
| } | |||
| #endif | |||
| } | |||
| } | |||
| if(1) | |||
| { | |||
| /* FIX: Specify the format disallowing a format string vulnerability */ | |||
| fprintf(stdout, "%s\n", data); | |||
| } | |||
| } | |||
| /* goodG2B1() - use goodsource and badsink by changing the first 1 to 0 */ | |||
| static void goodG2B1() | |||
| { | |||
| char * data; | |||
| char dataBuffer[100] = ""; | |||
| data = dataBuffer; | |||
| if(0) | |||
| { | |||
| /* INCIDENTAL: CWE 561 Dead Code, the code below will never run */ | |||
| printLine("Benign, fixed string"); | |||
| } | |||
| else | |||
| { | |||
| /* FIX: Use a fixed string that does not contain a format specifier */ | |||
| strcpy(data, "fixedstringtest"); | |||
| } | |||
| if(1) | |||
| { | |||
| /* POTENTIAL FLAW: Do not specify the format allowing a possible format string vulnerability */ | |||
| fprintf(stdout, data); | |||
| } | |||
| } | |||
| /* goodG2B2() - use goodsource and badsink by reversing the blocks in the first if */ | |||
| static void goodG2B2() | |||
| { | |||
| char * data; | |||
| char dataBuffer[100] = ""; | |||
| data = dataBuffer; | |||
| if(1) | |||
| { | |||
| /* FIX: Use a fixed string that does not contain a format specifier */ | |||
| strcpy(data, "fixedstringtest"); | |||
| } | |||
| if(1) | |||
| { | |||
| /* POTENTIAL FLAW: Do not specify the format allowing a possible format string vulnerability */ | |||
| fprintf(stdout, data); | |||
| } | |||
| } | |||
| void CWE134_Uncontrolled_Format_String__char_connect_socket_fprintf_02_good() | |||
| { | |||
| goodB2G1(); | |||
| goodB2G2(); | |||
| goodG2B1(); | |||
| goodG2B2(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| its own for testing or for building a binary to use in testing binary | |||
| analysis tools. It is not used when compiling all the testcases as one | |||
| application, which is how source code analysis tools are tested. */ | |||
| #ifdef INCLUDEMAIN | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| CWE134_Uncontrolled_Format_String__char_connect_socket_fprintf_02_good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| CWE134_Uncontrolled_Format_String__char_connect_socket_fprintf_02_bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,121 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE23_Relative_Path_Traversal__char_environment_ofstream_01.cpp | |||
| Label Definition File: CWE23_Relative_Path_Traversal.label.xml | |||
| Template File: sources-sink-01.tmpl.cpp | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 23 Relative Path Traversal | |||
| * BadSource: environment Read input from an environment variable | |||
| * GoodSource: Use a fixed file name | |||
| * Sink: ofstream | |||
| * BadSink : Open the file named in data using ofstream::open() | |||
| * Flow Variant: 01 Baseline | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #ifdef _WIN32 | |||
| #define BASEPATH "c:\\temp\\" | |||
| #else | |||
| #include <wchar.h> | |||
| #define BASEPATH "/tmp/" | |||
| #endif | |||
| #define ENV_VARIABLE "ADD" | |||
| #ifdef _WIN32 | |||
| #define GETENV getenv | |||
| #else | |||
| #define GETENV getenv | |||
| #endif | |||
| #include <fstream> | |||
| using namespace std; | |||
| namespace CWE23_Relative_Path_Traversal__char_environment_ofstream_01 | |||
| { | |||
| #ifndef OMITBAD | |||
| void bad() | |||
| { | |||
| char * data; | |||
| char dataBuffer[FILENAME_MAX] = BASEPATH; | |||
| data = dataBuffer; | |||
| { | |||
| /* Append input from an environment variable to data */ | |||
| size_t dataLen = strlen(data); | |||
| char * environment = GETENV(ENV_VARIABLE); | |||
| /* If there is data in the environment variable */ | |||
| if (environment != NULL) | |||
| { | |||
| /* POTENTIAL FLAW: Read data from an environment variable */ | |||
| strncat(data+dataLen, environment, FILENAME_MAX-dataLen-1); | |||
| } | |||
| } | |||
| { | |||
| ofstream outputFile; | |||
| /* POTENTIAL FLAW: Possibly opening a file without validating the file name or path */ | |||
| outputFile.open((char *)data); | |||
| outputFile.close(); | |||
| } | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* goodG2B uses the GoodSource with the BadSink */ | |||
| static void goodG2B() | |||
| { | |||
| char * data; | |||
| char dataBuffer[FILENAME_MAX] = BASEPATH; | |||
| data = dataBuffer; | |||
| /* FIX: Use a fixed file name */ | |||
| strcat(data, "file.txt"); | |||
| { | |||
| ofstream outputFile; | |||
| /* POTENTIAL FLAW: Possibly opening a file without validating the file name or path */ | |||
| outputFile.open((char *)data); | |||
| outputFile.close(); | |||
| } | |||
| } | |||
| void good() | |||
| { | |||
| goodG2B(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| } /* close namespace */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| its own for testing or for building a binary to use in testing binary | |||
| analysis tools. It is not used when compiling all the testcases as one | |||
| application, which is how source code analysis tools are tested. */ | |||
| #ifdef INCLUDEMAIN | |||
| using namespace CWE23_Relative_Path_Traversal__char_environment_ofstream_01; /* so that we can use good and bad easily */ | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,191 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE36_Absolute_Path_Traversal__char_connect_socket_fopen_51a.cpp | |||
| Label Definition File: CWE36_Absolute_Path_Traversal.label.xml | |||
| Template File: sources-sink-51a.tmpl.cpp | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 36 Absolute Path Traversal | |||
| * BadSource: connect_socket Read data using a connect socket (client side) | |||
| * GoodSource: Full path and file name | |||
| * Sink: fopen | |||
| * BadSink : Open the file named in data using fopen() | |||
| * Flow Variant: 51 Data flow: data passed as an argument from one function to another in different source files | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #ifndef _WIN32 | |||
| #include <wchar.h> | |||
| #endif | |||
| #ifdef _WIN32 | |||
| #include <winsock2.h> | |||
| #include <windows.h> | |||
| #include <direct.h> | |||
| #pragma comment(lib, "ws2_32") /* include ws2_32.lib when linking */ | |||
| #define CLOSE_SOCKET closesocket | |||
| #else /* NOT _WIN32 */ | |||
| #include <sys/types.h> | |||
| #include <sys/socket.h> | |||
| #include <netinet/in.h> | |||
| #include <arpa/inet.h> | |||
| #include <unistd.h> | |||
| #define INVALID_SOCKET -1 | |||
| #define SOCKET_ERROR -1 | |||
| #define CLOSE_SOCKET close | |||
| #define SOCKET int | |||
| #endif | |||
| #define TCP_PORT 27015 | |||
| #define IP_ADDRESS "127.0.0.1" | |||
| #ifdef _WIN32 | |||
| #define FOPEN fopen | |||
| #else | |||
| #define FOPEN fopen | |||
| #endif | |||
| namespace CWE36_Absolute_Path_Traversal__char_connect_socket_fopen_51 | |||
| { | |||
| #ifndef OMITBAD | |||
| /* bad function declaration */ | |||
| void badSink(char * data); | |||
| void bad() | |||
| { | |||
| char * data; | |||
| char dataBuffer[FILENAME_MAX] = ""; | |||
| data = dataBuffer; | |||
| { | |||
| #ifdef _WIN32 | |||
| WSADATA wsaData; | |||
| int wsaDataInit = 0; | |||
| #endif | |||
| int recvResult; | |||
| struct sockaddr_in service; | |||
| char *replace; | |||
| SOCKET connectSocket = INVALID_SOCKET; | |||
| size_t dataLen = strlen(data); | |||
| do | |||
| { | |||
| #ifdef _WIN32 | |||
| if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| wsaDataInit = 1; | |||
| #endif | |||
| /* POTENTIAL FLAW: Read data using a connect socket */ | |||
| connectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |||
| if (connectSocket == INVALID_SOCKET) | |||
| { | |||
| break; | |||
| } | |||
| memset(&service, 0, sizeof(service)); | |||
| service.sin_family = AF_INET; | |||
| service.sin_addr.s_addr = inet_addr(IP_ADDRESS); | |||
| service.sin_port = htons(TCP_PORT); | |||
| if (connect(connectSocket, (struct sockaddr*)&service, sizeof(service)) == SOCKET_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| /* Abort on error or the connection was closed, make sure to recv one | |||
| * less char than is in the recv_buf in order to append a terminator */ | |||
| /* Abort on error or the connection was closed */ | |||
| recvResult = recv(connectSocket, (char *)(data + dataLen), sizeof(char) * (FILENAME_MAX - dataLen - 1), 0); | |||
| if (recvResult == SOCKET_ERROR || recvResult == 0) | |||
| { | |||
| break; | |||
| } | |||
| /* Append null terminator */ | |||
| data[dataLen + recvResult / sizeof(char)] = '\0'; | |||
| /* Eliminate CRLF */ | |||
| replace = strchr(data, '\r'); | |||
| if (replace) | |||
| { | |||
| *replace = '\0'; | |||
| } | |||
| replace = strchr(data, '\n'); | |||
| if (replace) | |||
| { | |||
| *replace = '\0'; | |||
| } | |||
| } | |||
| while (0); | |||
| if (connectSocket != INVALID_SOCKET) | |||
| { | |||
| CLOSE_SOCKET(connectSocket); | |||
| } | |||
| #ifdef _WIN32 | |||
| if (wsaDataInit) | |||
| { | |||
| WSACleanup(); | |||
| } | |||
| #endif | |||
| } | |||
| badSink(data); | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* good function declarations */ | |||
| void goodG2BSink(char * data); | |||
| /* goodG2B uses the GoodSource with the BadSink */ | |||
| static void goodG2B() | |||
| { | |||
| char * data; | |||
| char dataBuffer[FILENAME_MAX] = ""; | |||
| data = dataBuffer; | |||
| #ifdef _WIN32 | |||
| /* FIX: Use a fixed, full path and file name */ | |||
| strcat(data, "c:\\temp\\file.txt"); | |||
| #else | |||
| /* FIX: Use a fixed, full path and file name */ | |||
| strcat(data, "/tmp/file.txt"); | |||
| #endif | |||
| goodG2BSink(data); | |||
| } | |||
| void good() | |||
| { | |||
| goodG2B(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| } /* close namespace */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| its own for testing or for building a binary to use in testing binary | |||
| analysis tools. It is not used when compiling all the testcases as one | |||
| application, which is how source code analysis tools are tested. */ | |||
| #ifdef INCLUDEMAIN | |||
| using namespace CWE36_Absolute_Path_Traversal__char_connect_socket_fopen_51; /* so that we can use good and bad easily */ | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,103 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE401_Memory_Leak__char_calloc_01.c | |||
| Label Definition File: CWE401_Memory_Leak.c.label.xml | |||
| Template File: sources-sinks-01.tmpl.c | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 401 Memory Leak | |||
| * BadSource: calloc Allocate data using calloc() | |||
| * GoodSource: Allocate data on the stack | |||
| * Sinks: | |||
| * GoodSink: call free() on data | |||
| * BadSink : no deallocation of data | |||
| * Flow Variant: 01 Baseline | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #include <wchar.h> | |||
| #ifndef OMITBAD | |||
| void CWE401_Memory_Leak__char_calloc_01_bad() | |||
| { | |||
| char * data; | |||
| data = NULL; | |||
| /* POTENTIAL FLAW: Allocate memory on the heap */ | |||
| data = (char *)calloc(100, sizeof(char)); | |||
| if (data == NULL) {exit(-1);} | |||
| /* Initialize and make use of data */ | |||
| strcpy(data, "A String"); | |||
| printLine(data); | |||
| /* POTENTIAL FLAW: No deallocation */ | |||
| ; /* empty statement needed for some flow variants */ | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* goodG2B uses the GoodSource with the BadSink */ | |||
| static void goodG2B() | |||
| { | |||
| char * data; | |||
| data = NULL; | |||
| /* FIX: Use memory allocated on the stack with ALLOCA */ | |||
| data = (char *)ALLOCA(100*sizeof(char)); | |||
| /* Initialize and make use of data */ | |||
| strcpy(data, "A String"); | |||
| printLine(data); | |||
| /* POTENTIAL FLAW: No deallocation */ | |||
| ; /* empty statement needed for some flow variants */ | |||
| } | |||
| /* goodB2G uses the BadSource with the GoodSink */ | |||
| static void goodB2G() | |||
| { | |||
| char * data; | |||
| data = NULL; | |||
| /* POTENTIAL FLAW: Allocate memory on the heap */ | |||
| data = (char *)calloc(100, sizeof(char)); | |||
| if (data == NULL) {exit(-1);} | |||
| /* Initialize and make use of data */ | |||
| strcpy(data, "A String"); | |||
| printLine(data); | |||
| /* FIX: Deallocate memory */ | |||
| free(data); | |||
| } | |||
| void CWE401_Memory_Leak__char_calloc_01_good() | |||
| { | |||
| goodG2B(); | |||
| goodB2G(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| its own for testing or for building a binary to use in testing binary | |||
| analysis tools. It is not used when compiling all the testcases as one | |||
| application, which is how source code analysis tools are tested. */ | |||
| #ifdef INCLUDEMAIN | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| CWE401_Memory_Leak__char_calloc_01_good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| CWE401_Memory_Leak__char_calloc_01_bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,174 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE401_Memory_Leak__char_calloc_02.c | |||
| Label Definition File: CWE401_Memory_Leak.c.label.xml | |||
| Template File: sources-sinks-02.tmpl.c | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 401 Memory Leak | |||
| * BadSource: calloc Allocate data using calloc() | |||
| * GoodSource: Allocate data on the stack | |||
| * Sinks: | |||
| * GoodSink: call free() on data | |||
| * BadSink : no deallocation of data | |||
| * Flow Variant: 02 Control flow: if(1) and if(0) | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #include <wchar.h> | |||
| #ifndef OMITBAD | |||
| void CWE401_Memory_Leak__char_calloc_02_bad() | |||
| { | |||
| char * data; | |||
| data = NULL; | |||
| if(1) | |||
| { | |||
| /* POTENTIAL FLAW: Allocate memory on the heap */ | |||
| data = (char *)calloc(100, sizeof(char)); | |||
| if (data == NULL) {exit(-1);} | |||
| /* Initialize and make use of data */ | |||
| strcpy(data, "A String"); | |||
| printLine(data); | |||
| } | |||
| if(1) | |||
| { | |||
| /* POTENTIAL FLAW: No deallocation */ | |||
| ; /* empty statement needed for some flow variants */ | |||
| } | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* goodB2G1() - use badsource and goodsink by changing the second 1 to 0 */ | |||
| static void goodB2G1() | |||
| { | |||
| char * data; | |||
| data = NULL; | |||
| if(1) | |||
| { | |||
| /* POTENTIAL FLAW: Allocate memory on the heap */ | |||
| data = (char *)calloc(100, sizeof(char)); | |||
| if (data == NULL) {exit(-1);} | |||
| /* Initialize and make use of data */ | |||
| strcpy(data, "A String"); | |||
| printLine(data); | |||
| } | |||
| if(0) | |||
| { | |||
| /* INCIDENTAL: CWE 561 Dead Code, the code below will never run */ | |||
| printLine("Benign, fixed string"); | |||
| } | |||
| else | |||
| { | |||
| /* FIX: Deallocate memory */ | |||
| free(data); | |||
| } | |||
| } | |||
| /* goodB2G2() - use badsource and goodsink by reversing the blocks in the second if */ | |||
| static void goodB2G2() | |||
| { | |||
| char * data; | |||
| data = NULL; | |||
| if(1) | |||
| { | |||
| /* POTENTIAL FLAW: Allocate memory on the heap */ | |||
| data = (char *)calloc(100, sizeof(char)); | |||
| if (data == NULL) {exit(-1);} | |||
| /* Initialize and make use of data */ | |||
| strcpy(data, "A String"); | |||
| printLine(data); | |||
| } | |||
| if(1) | |||
| { | |||
| /* FIX: Deallocate memory */ | |||
| free(data); | |||
| } | |||
| } | |||
| /* goodG2B1() - use goodsource and badsink by changing the first 1 to 0 */ | |||
| static void goodG2B1() | |||
| { | |||
| char * data; | |||
| data = NULL; | |||
| if(0) | |||
| { | |||
| /* INCIDENTAL: CWE 561 Dead Code, the code below will never run */ | |||
| printLine("Benign, fixed string"); | |||
| } | |||
| else | |||
| { | |||
| /* FIX: Use memory allocated on the stack with ALLOCA */ | |||
| data = (char *)ALLOCA(100*sizeof(char)); | |||
| /* Initialize and make use of data */ | |||
| strcpy(data, "A String"); | |||
| printLine(data); | |||
| } | |||
| if(1) | |||
| { | |||
| /* POTENTIAL FLAW: No deallocation */ | |||
| ; /* empty statement needed for some flow variants */ | |||
| } | |||
| } | |||
| /* goodG2B2() - use goodsource and badsink by reversing the blocks in the first if */ | |||
| static void goodG2B2() | |||
| { | |||
| char * data; | |||
| data = NULL; | |||
| if(1) | |||
| { | |||
| /* FIX: Use memory allocated on the stack with ALLOCA */ | |||
| data = (char *)ALLOCA(100*sizeof(char)); | |||
| /* Initialize and make use of data */ | |||
| strcpy(data, "A String"); | |||
| printLine(data); | |||
| } | |||
| if(1) | |||
| { | |||
| /* POTENTIAL FLAW: No deallocation */ | |||
| ; /* empty statement needed for some flow variants */ | |||
| } | |||
| } | |||
| void CWE401_Memory_Leak__char_calloc_02_good() | |||
| { | |||
| goodB2G1(); | |||
| goodB2G2(); | |||
| goodG2B1(); | |||
| goodG2B2(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| its own for testing or for building a binary to use in testing binary | |||
| analysis tools. It is not used when compiling all the testcases as one | |||
| application, which is how source code analysis tools are tested. */ | |||
| #ifdef INCLUDEMAIN | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| CWE401_Memory_Leak__char_calloc_02_good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| CWE401_Memory_Leak__char_calloc_02_bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,101 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE415_Double_Free__malloc_free_char_01.c | |||
| Label Definition File: CWE415_Double_Free__malloc_free.label.xml | |||
| Template File: sources-sinks-01.tmpl.c | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 415 Double Free | |||
| * BadSource: Allocate data using malloc() and Deallocate data using free() | |||
| * GoodSource: Allocate data using malloc() | |||
| * Sinks: | |||
| * GoodSink: do nothing | |||
| * BadSink : Deallocate data using free() | |||
| * Flow Variant: 01 Baseline | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #include <wchar.h> | |||
| #ifndef OMITBAD | |||
| void CWE415_Double_Free__malloc_free_char_01_bad() | |||
| { | |||
| char * data; | |||
| /* Initialize data */ | |||
| data = NULL; | |||
| data = (char *)malloc(100*sizeof(char)); | |||
| if (data == NULL) {exit(-1);} | |||
| /* POTENTIAL FLAW: Free data in the source - the bad sink frees data as well */ | |||
| free(data); | |||
| /* POTENTIAL FLAW: Possibly freeing memory twice */ | |||
| free(data); | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* goodG2B uses the GoodSource with the BadSink */ | |||
| static void goodG2B() | |||
| { | |||
| char * data; | |||
| /* Initialize data */ | |||
| data = NULL; | |||
| data = (char *)malloc(100*sizeof(char)); | |||
| if (data == NULL) {exit(-1);} | |||
| /* FIX: Do NOT free data in the source - the bad sink frees data */ | |||
| /* POTENTIAL FLAW: Possibly freeing memory twice */ | |||
| free(data); | |||
| } | |||
| /* goodB2G uses the BadSource with the GoodSink */ | |||
| static void goodB2G() | |||
| { | |||
| char * data; | |||
| /* Initialize data */ | |||
| data = NULL; | |||
| data = (char *)malloc(100*sizeof(char)); | |||
| if (data == NULL) {exit(-1);} | |||
| /* POTENTIAL FLAW: Free data in the source - the bad sink frees data as well */ | |||
| free(data); | |||
| /* do nothing */ | |||
| /* FIX: Don't attempt to free the memory */ | |||
| ; /* empty statement needed for some flow variants */ | |||
| } | |||
| void CWE415_Double_Free__malloc_free_char_01_good() | |||
| { | |||
| goodG2B(); | |||
| goodB2G(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| its own for testing or for building a binary to use in testing binary | |||
| analysis tools. It is not used when compiling all the testcases as one | |||
| application, which is how source code analysis tools are tested. */ | |||
| #ifdef INCLUDEMAIN | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| CWE415_Double_Free__malloc_free_char_01_good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| CWE415_Double_Free__malloc_free_char_01_bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,171 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE415_Double_Free__malloc_free_char_02.c | |||
| Label Definition File: CWE415_Double_Free__malloc_free.label.xml | |||
| Template File: sources-sinks-02.tmpl.c | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 415 Double Free | |||
| * BadSource: Allocate data using malloc() and Deallocate data using free() | |||
| * GoodSource: Allocate data using malloc() | |||
| * Sinks: | |||
| * GoodSink: do nothing | |||
| * BadSink : Deallocate data using free() | |||
| * Flow Variant: 02 Control flow: if(1) and if(0) | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #include <wchar.h> | |||
| #ifndef OMITBAD | |||
| void CWE415_Double_Free__malloc_free_char_02_bad() | |||
| { | |||
| char * data; | |||
| /* Initialize data */ | |||
| data = NULL; | |||
| if(1) | |||
| { | |||
| data = (char *)malloc(100*sizeof(char)); | |||
| if (data == NULL) {exit(-1);} | |||
| /* POTENTIAL FLAW: Free data in the source - the bad sink frees data as well */ | |||
| free(data); | |||
| } | |||
| if(1) | |||
| { | |||
| /* POTENTIAL FLAW: Possibly freeing memory twice */ | |||
| free(data); | |||
| } | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* goodB2G1() - use badsource and goodsink by changing the second 1 to 0 */ | |||
| static void goodB2G1() | |||
| { | |||
| char * data; | |||
| /* Initialize data */ | |||
| data = NULL; | |||
| if(1) | |||
| { | |||
| data = (char *)malloc(100*sizeof(char)); | |||
| if (data == NULL) {exit(-1);} | |||
| /* POTENTIAL FLAW: Free data in the source - the bad sink frees data as well */ | |||
| free(data); | |||
| } | |||
| if(0) | |||
| { | |||
| /* INCIDENTAL: CWE 561 Dead Code, the code below will never run */ | |||
| printLine("Benign, fixed string"); | |||
| } | |||
| else | |||
| { | |||
| /* do nothing */ | |||
| /* FIX: Don't attempt to free the memory */ | |||
| ; /* empty statement needed for some flow variants */ | |||
| } | |||
| } | |||
| /* goodB2G2() - use badsource and goodsink by reversing the blocks in the second if */ | |||
| static void goodB2G2() | |||
| { | |||
| char * data; | |||
| /* Initialize data */ | |||
| data = NULL; | |||
| if(1) | |||
| { | |||
| data = (char *)malloc(100*sizeof(char)); | |||
| if (data == NULL) {exit(-1);} | |||
| /* POTENTIAL FLAW: Free data in the source - the bad sink frees data as well */ | |||
| free(data); | |||
| } | |||
| if(1) | |||
| { | |||
| /* do nothing */ | |||
| /* FIX: Don't attempt to free the memory */ | |||
| ; /* empty statement needed for some flow variants */ | |||
| } | |||
| } | |||
| /* goodG2B1() - use goodsource and badsink by changing the first 1 to 0 */ | |||
| static void goodG2B1() | |||
| { | |||
| char * data; | |||
| /* Initialize data */ | |||
| data = NULL; | |||
| if(0) | |||
| { | |||
| /* INCIDENTAL: CWE 561 Dead Code, the code below will never run */ | |||
| printLine("Benign, fixed string"); | |||
| } | |||
| else | |||
| { | |||
| data = (char *)malloc(100*sizeof(char)); | |||
| if (data == NULL) {exit(-1);} | |||
| /* FIX: Do NOT free data in the source - the bad sink frees data */ | |||
| } | |||
| if(1) | |||
| { | |||
| /* POTENTIAL FLAW: Possibly freeing memory twice */ | |||
| free(data); | |||
| } | |||
| } | |||
| /* goodG2B2() - use goodsource and badsink by reversing the blocks in the first if */ | |||
| static void goodG2B2() | |||
| { | |||
| char * data; | |||
| /* Initialize data */ | |||
| data = NULL; | |||
| if(1) | |||
| { | |||
| data = (char *)malloc(100*sizeof(char)); | |||
| if (data == NULL) {exit(-1);} | |||
| /* FIX: Do NOT free data in the source - the bad sink frees data */ | |||
| } | |||
| if(1) | |||
| { | |||
| /* POTENTIAL FLAW: Possibly freeing memory twice */ | |||
| free(data); | |||
| } | |||
| } | |||
| void CWE415_Double_Free__malloc_free_char_02_good() | |||
| { | |||
| goodB2G1(); | |||
| goodB2G2(); | |||
| goodG2B1(); | |||
| goodG2B2(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| its own for testing or for building a binary to use in testing binary | |||
| analysis tools. It is not used when compiling all the testcases as one | |||
| application, which is how source code analysis tools are tested. */ | |||
| #ifdef INCLUDEMAIN | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| CWE415_Double_Free__malloc_free_char_02_good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| CWE415_Double_Free__malloc_free_char_02_bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,110 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE416_Use_After_Free__malloc_free_char_01.c | |||
| Label Definition File: CWE416_Use_After_Free__malloc_free.label.xml | |||
| Template File: sources-sinks-01.tmpl.c | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 416 Use After Free | |||
| * BadSource: Allocate data using malloc(), initialize memory block, and Deallocate data using free() | |||
| * GoodSource: Allocate data using malloc() and initialize memory block | |||
| * Sinks: | |||
| * GoodSink: Do nothing | |||
| * BadSink : Use data | |||
| * Flow Variant: 01 Baseline | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #include <wchar.h> | |||
| #ifndef OMITBAD | |||
| void CWE416_Use_After_Free__malloc_free_char_01_bad() | |||
| { | |||
| char * data; | |||
| /* Initialize data */ | |||
| data = NULL; | |||
| data = (char *)malloc(100*sizeof(char)); | |||
| if (data == NULL) {exit(-1);} | |||
| memset(data, 'A', 100-1); | |||
| data[100-1] = '\0'; | |||
| /* POTENTIAL FLAW: Free data in the source - the bad sink attempts to use data */ | |||
| free(data); | |||
| /* POTENTIAL FLAW: Use of data that may have been freed */ | |||
| printLine(data); | |||
| /* POTENTIAL INCIDENTAL - Possible memory leak here if data was not freed */ | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* goodG2B uses the GoodSource with the BadSink */ | |||
| static void goodG2B() | |||
| { | |||
| char * data; | |||
| /* Initialize data */ | |||
| data = NULL; | |||
| data = (char *)malloc(100*sizeof(char)); | |||
| if (data == NULL) {exit(-1);} | |||
| memset(data, 'A', 100-1); | |||
| data[100-1] = '\0'; | |||
| /* FIX: Do not free data in the source */ | |||
| /* POTENTIAL FLAW: Use of data that may have been freed */ | |||
| printLine(data); | |||
| /* POTENTIAL INCIDENTAL - Possible memory leak here if data was not freed */ | |||
| } | |||
| /* goodB2G uses the BadSource with the GoodSink */ | |||
| static void goodB2G() | |||
| { | |||
| char * data; | |||
| /* Initialize data */ | |||
| data = NULL; | |||
| data = (char *)malloc(100*sizeof(char)); | |||
| if (data == NULL) {exit(-1);} | |||
| memset(data, 'A', 100-1); | |||
| data[100-1] = '\0'; | |||
| /* POTENTIAL FLAW: Free data in the source - the bad sink attempts to use data */ | |||
| free(data); | |||
| /* FIX: Don't use data that may have been freed already */ | |||
| /* POTENTIAL INCIDENTAL - Possible memory leak here if data was not freed */ | |||
| /* do nothing */ | |||
| ; /* empty statement needed for some flow variants */ | |||
| } | |||
| void CWE416_Use_After_Free__malloc_free_char_01_good() | |||
| { | |||
| goodG2B(); | |||
| goodB2G(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| its own for testing or for building a binary to use in testing binary | |||
| analysis tools. It is not used when compiling all the testcases as one | |||
| application, which is how source code analysis tools are tested. */ | |||
| #ifdef INCLUDEMAIN | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| CWE416_Use_After_Free__malloc_free_char_01_good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| CWE416_Use_After_Free__malloc_free_char_01_bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,186 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE416_Use_After_Free__malloc_free_char_02.c | |||
| Label Definition File: CWE416_Use_After_Free__malloc_free.label.xml | |||
| Template File: sources-sinks-02.tmpl.c | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 416 Use After Free | |||
| * BadSource: Allocate data using malloc(), initialize memory block, and Deallocate data using free() | |||
| * GoodSource: Allocate data using malloc() and initialize memory block | |||
| * Sinks: | |||
| * GoodSink: Do nothing | |||
| * BadSink : Use data | |||
| * Flow Variant: 02 Control flow: if(1) and if(0) | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #include <wchar.h> | |||
| #ifndef OMITBAD | |||
| void CWE416_Use_After_Free__malloc_free_char_02_bad() | |||
| { | |||
| char * data; | |||
| /* Initialize data */ | |||
| data = NULL; | |||
| if(1) | |||
| { | |||
| data = (char *)malloc(100*sizeof(char)); | |||
| if (data == NULL) {exit(-1);} | |||
| memset(data, 'A', 100-1); | |||
| data[100-1] = '\0'; | |||
| /* POTENTIAL FLAW: Free data in the source - the bad sink attempts to use data */ | |||
| free(data); | |||
| } | |||
| if(1) | |||
| { | |||
| /* POTENTIAL FLAW: Use of data that may have been freed */ | |||
| printLine(data); | |||
| /* POTENTIAL INCIDENTAL - Possible memory leak here if data was not freed */ | |||
| } | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* goodB2G1() - use badsource and goodsink by changing the second 1 to 0 */ | |||
| static void goodB2G1() | |||
| { | |||
| char * data; | |||
| /* Initialize data */ | |||
| data = NULL; | |||
| if(1) | |||
| { | |||
| data = (char *)malloc(100*sizeof(char)); | |||
| if (data == NULL) {exit(-1);} | |||
| memset(data, 'A', 100-1); | |||
| data[100-1] = '\0'; | |||
| /* POTENTIAL FLAW: Free data in the source - the bad sink attempts to use data */ | |||
| free(data); | |||
| } | |||
| if(0) | |||
| { | |||
| /* INCIDENTAL: CWE 561 Dead Code, the code below will never run */ | |||
| printLine("Benign, fixed string"); | |||
| } | |||
| else | |||
| { | |||
| /* FIX: Don't use data that may have been freed already */ | |||
| /* POTENTIAL INCIDENTAL - Possible memory leak here if data was not freed */ | |||
| /* do nothing */ | |||
| ; /* empty statement needed for some flow variants */ | |||
| } | |||
| } | |||
| /* goodB2G2() - use badsource and goodsink by reversing the blocks in the second if */ | |||
| static void goodB2G2() | |||
| { | |||
| char * data; | |||
| /* Initialize data */ | |||
| data = NULL; | |||
| if(1) | |||
| { | |||
| data = (char *)malloc(100*sizeof(char)); | |||
| if (data == NULL) {exit(-1);} | |||
| memset(data, 'A', 100-1); | |||
| data[100-1] = '\0'; | |||
| /* POTENTIAL FLAW: Free data in the source - the bad sink attempts to use data */ | |||
| free(data); | |||
| } | |||
| if(1) | |||
| { | |||
| /* FIX: Don't use data that may have been freed already */ | |||
| /* POTENTIAL INCIDENTAL - Possible memory leak here if data was not freed */ | |||
| /* do nothing */ | |||
| ; /* empty statement needed for some flow variants */ | |||
| } | |||
| } | |||
| /* goodG2B1() - use goodsource and badsink by changing the first 1 to 0 */ | |||
| static void goodG2B1() | |||
| { | |||
| char * data; | |||
| /* Initialize data */ | |||
| data = NULL; | |||
| if(0) | |||
| { | |||
| /* INCIDENTAL: CWE 561 Dead Code, the code below will never run */ | |||
| printLine("Benign, fixed string"); | |||
| } | |||
| else | |||
| { | |||
| data = (char *)malloc(100*sizeof(char)); | |||
| if (data == NULL) {exit(-1);} | |||
| memset(data, 'A', 100-1); | |||
| data[100-1] = '\0'; | |||
| /* FIX: Do not free data in the source */ | |||
| } | |||
| if(1) | |||
| { | |||
| /* POTENTIAL FLAW: Use of data that may have been freed */ | |||
| printLine(data); | |||
| /* POTENTIAL INCIDENTAL - Possible memory leak here if data was not freed */ | |||
| } | |||
| } | |||
| /* goodG2B2() - use goodsource and badsink by reversing the blocks in the first if */ | |||
| static void goodG2B2() | |||
| { | |||
| char * data; | |||
| /* Initialize data */ | |||
| data = NULL; | |||
| if(1) | |||
| { | |||
| data = (char *)malloc(100*sizeof(char)); | |||
| if (data == NULL) {exit(-1);} | |||
| memset(data, 'A', 100-1); | |||
| data[100-1] = '\0'; | |||
| /* FIX: Do not free data in the source */ | |||
| } | |||
| if(1) | |||
| { | |||
| /* POTENTIAL FLAW: Use of data that may have been freed */ | |||
| printLine(data); | |||
| /* POTENTIAL INCIDENTAL - Possible memory leak here if data was not freed */ | |||
| } | |||
| } | |||
| void CWE416_Use_After_Free__malloc_free_char_02_good() | |||
| { | |||
| goodB2G1(); | |||
| goodB2G2(); | |||
| goodG2B1(); | |||
| goodG2B2(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| its own for testing or for building a binary to use in testing binary | |||
| analysis tools. It is not used when compiling all the testcases as one | |||
| application, which is how source code analysis tools are tested. */ | |||
| #ifdef INCLUDEMAIN | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| CWE416_Use_After_Free__malloc_free_char_02_good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| CWE416_Use_After_Free__malloc_free_char_02_bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,186 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE416_Use_After_Free__malloc_free_char_03.c | |||
| Label Definition File: CWE416_Use_After_Free__malloc_free.label.xml | |||
| Template File: sources-sinks-03.tmpl.c | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 416 Use After Free | |||
| * BadSource: Allocate data using malloc(), initialize memory block, and Deallocate data using free() | |||
| * GoodSource: Allocate data using malloc() and initialize memory block | |||
| * Sinks: | |||
| * GoodSink: Do nothing | |||
| * BadSink : Use data | |||
| * Flow Variant: 03 Control flow: if(5==5) and if(5!=5) | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #include <wchar.h> | |||
| #ifndef OMITBAD | |||
| void CWE416_Use_After_Free__malloc_free_char_03_bad() | |||
| { | |||
| char * data; | |||
| /* Initialize data */ | |||
| data = NULL; | |||
| if(5==5) | |||
| { | |||
| data = (char *)malloc(100*sizeof(char)); | |||
| if (data == NULL) {exit(-1);} | |||
| memset(data, 'A', 100-1); | |||
| data[100-1] = '\0'; | |||
| /* POTENTIAL FLAW: Free data in the source - the bad sink attempts to use data */ | |||
| free(data); | |||
| } | |||
| if(5==5) | |||
| { | |||
| /* POTENTIAL FLAW: Use of data that may have been freed */ | |||
| printLine(data); | |||
| /* POTENTIAL INCIDENTAL - Possible memory leak here if data was not freed */ | |||
| } | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* goodB2G1() - use badsource and goodsink by changing the second 5==5 to 5!=5 */ | |||
| static void goodB2G1() | |||
| { | |||
| char * data; | |||
| /* Initialize data */ | |||
| data = NULL; | |||
| if(5==5) | |||
| { | |||
| data = (char *)malloc(100*sizeof(char)); | |||
| if (data == NULL) {exit(-1);} | |||
| memset(data, 'A', 100-1); | |||
| data[100-1] = '\0'; | |||
| /* POTENTIAL FLAW: Free data in the source - the bad sink attempts to use data */ | |||
| free(data); | |||
| } | |||
| if(5!=5) | |||
| { | |||
| /* INCIDENTAL: CWE 561 Dead Code, the code below will never run */ | |||
| printLine("Benign, fixed string"); | |||
| } | |||
| else | |||
| { | |||
| /* FIX: Don't use data that may have been freed already */ | |||
| /* POTENTIAL INCIDENTAL - Possible memory leak here if data was not freed */ | |||
| /* do nothing */ | |||
| ; /* empty statement needed for some flow variants */ | |||
| } | |||
| } | |||
| /* goodB2G2() - use badsource and goodsink by reversing the blocks in the second if */ | |||
| static void goodB2G2() | |||
| { | |||
| char * data; | |||
| /* Initialize data */ | |||
| data = NULL; | |||
| if(5==5) | |||
| { | |||
| data = (char *)malloc(100*sizeof(char)); | |||
| if (data == NULL) {exit(-1);} | |||
| memset(data, 'A', 100-1); | |||
| data[100-1] = '\0'; | |||
| /* POTENTIAL FLAW: Free data in the source - the bad sink attempts to use data */ | |||
| free(data); | |||
| } | |||
| if(5==5) | |||
| { | |||
| /* FIX: Don't use data that may have been freed already */ | |||
| /* POTENTIAL INCIDENTAL - Possible memory leak here if data was not freed */ | |||
| /* do nothing */ | |||
| ; /* empty statement needed for some flow variants */ | |||
| } | |||
| } | |||
| /* goodG2B1() - use goodsource and badsink by changing the first 5==5 to 5!=5 */ | |||
| static void goodG2B1() | |||
| { | |||
| char * data; | |||
| /* Initialize data */ | |||
| data = NULL; | |||
| if(5!=5) | |||
| { | |||
| /* INCIDENTAL: CWE 561 Dead Code, the code below will never run */ | |||
| printLine("Benign, fixed string"); | |||
| } | |||
| else | |||
| { | |||
| data = (char *)malloc(100*sizeof(char)); | |||
| if (data == NULL) {exit(-1);} | |||
| memset(data, 'A', 100-1); | |||
| data[100-1] = '\0'; | |||
| /* FIX: Do not free data in the source */ | |||
| } | |||
| if(5==5) | |||
| { | |||
| /* POTENTIAL FLAW: Use of data that may have been freed */ | |||
| printLine(data); | |||
| /* POTENTIAL INCIDENTAL - Possible memory leak here if data was not freed */ | |||
| } | |||
| } | |||
| /* goodG2B2() - use goodsource and badsink by reversing the blocks in the first if */ | |||
| static void goodG2B2() | |||
| { | |||
| char * data; | |||
| /* Initialize data */ | |||
| data = NULL; | |||
| if(5==5) | |||
| { | |||
| data = (char *)malloc(100*sizeof(char)); | |||
| if (data == NULL) {exit(-1);} | |||
| memset(data, 'A', 100-1); | |||
| data[100-1] = '\0'; | |||
| /* FIX: Do not free data in the source */ | |||
| } | |||
| if(5==5) | |||
| { | |||
| /* POTENTIAL FLAW: Use of data that may have been freed */ | |||
| printLine(data); | |||
| /* POTENTIAL INCIDENTAL - Possible memory leak here if data was not freed */ | |||
| } | |||
| } | |||
| void CWE416_Use_After_Free__malloc_free_char_03_good() | |||
| { | |||
| goodB2G1(); | |||
| goodB2G2(); | |||
| goodG2B1(); | |||
| goodG2B2(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| its own for testing or for building a binary to use in testing binary | |||
| analysis tools. It is not used when compiling all the testcases as one | |||
| application, which is how source code analysis tools are tested. */ | |||
| #ifdef INCLUDEMAIN | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| CWE416_Use_After_Free__malloc_free_char_03_good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| CWE416_Use_After_Free__malloc_free_char_03_bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,81 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE476_NULL_Pointer_Dereference__binary_if_01.c | |||
| Label Definition File: CWE476_NULL_Pointer_Dereference.pointflaw.label.xml | |||
| Template File: point-flaw-01.tmpl.c | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 476 NULL Pointer Dereference | |||
| * Sinks: binary_if | |||
| * GoodSink: Do not check for NULL after the pointer has been dereferenced | |||
| * BadSink : Check for NULL after a pointer has already been dereferenced | |||
| * Flow Variant: 01 Baseline | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #ifndef OMITBAD | |||
| void CWE476_NULL_Pointer_Dereference__binary_if_01_bad() | |||
| { | |||
| { | |||
| twoIntsStruct *twoIntsStructPointer = NULL; | |||
| /* FLAW: Using a single & in the if statement will cause both sides of the expression to be evaluated | |||
| * thus causing a NPD */ | |||
| if ((twoIntsStructPointer != NULL) & (twoIntsStructPointer->intOne == 5)) | |||
| { | |||
| printLine("intOne == 5"); | |||
| } | |||
| } | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| static void good1() | |||
| { | |||
| { | |||
| twoIntsStruct *twoIntsStructPointer = NULL; | |||
| /* FIX: Use && in the if statement so that if the left side of the expression fails then | |||
| * the right side will not be evaluated */ | |||
| if ((twoIntsStructPointer != NULL) && (twoIntsStructPointer->intOne == 5)) | |||
| { | |||
| printLine("intOne == 5"); | |||
| } | |||
| } | |||
| } | |||
| void CWE476_NULL_Pointer_Dereference__binary_if_01_good() | |||
| { | |||
| good1(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| its own for testing or for building a binary to use in testing binary | |||
| analysis tools. It is not used when compiling all the testcases as one | |||
| application, which is how source code analysis tools are tested. */ | |||
| #ifdef INCLUDEMAIN | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| CWE476_NULL_Pointer_Dereference__binary_if_01_good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| CWE476_NULL_Pointer_Dereference__binary_if_01_bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,111 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE476_NULL_Pointer_Dereference__binary_if_02.c | |||
| Label Definition File: CWE476_NULL_Pointer_Dereference.pointflaw.label.xml | |||
| Template File: point-flaw-02.tmpl.c | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 476 NULL Pointer Dereference | |||
| * Sinks: binary_if | |||
| * GoodSink: Do not check for NULL after the pointer has been dereferenced | |||
| * BadSink : Check for NULL after a pointer has already been dereferenced | |||
| * Flow Variant: 02 Control flow: if(1) and if(0) | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #ifndef OMITBAD | |||
| void CWE476_NULL_Pointer_Dereference__binary_if_02_bad() | |||
| { | |||
| if(1) | |||
| { | |||
| { | |||
| twoIntsStruct *twoIntsStructPointer = NULL; | |||
| /* FLAW: Using a single & in the if statement will cause both sides of the expression to be evaluated | |||
| * thus causing a NPD */ | |||
| if ((twoIntsStructPointer != NULL) & (twoIntsStructPointer->intOne == 5)) | |||
| { | |||
| printLine("intOne == 5"); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* good1() uses if(0) instead of if(1) */ | |||
| static void good1() | |||
| { | |||
| if(0) | |||
| { | |||
| /* INCIDENTAL: CWE 561 Dead Code, the code below will never run */ | |||
| printLine("Benign, fixed string"); | |||
| } | |||
| else | |||
| { | |||
| { | |||
| twoIntsStruct *twoIntsStructPointer = NULL; | |||
| /* FIX: Use && in the if statement so that if the left side of the expression fails then | |||
| * the right side will not be evaluated */ | |||
| if ((twoIntsStructPointer != NULL) && (twoIntsStructPointer->intOne == 5)) | |||
| { | |||
| printLine("intOne == 5"); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /* good2() reverses the bodies in the if statement */ | |||
| static void good2() | |||
| { | |||
| if(1) | |||
| { | |||
| { | |||
| twoIntsStruct *twoIntsStructPointer = NULL; | |||
| /* FIX: Use && in the if statement so that if the left side of the expression fails then | |||
| * the right side will not be evaluated */ | |||
| if ((twoIntsStructPointer != NULL) && (twoIntsStructPointer->intOne == 5)) | |||
| { | |||
| printLine("intOne == 5"); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| void CWE476_NULL_Pointer_Dereference__binary_if_02_good() | |||
| { | |||
| good1(); | |||
| good2(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| its own for testing or for building a binary to use in testing binary | |||
| analysis tools. It is not used when compiling all the testcases as one | |||
| application, which is how source code analysis tools are tested. */ | |||
| #ifdef INCLUDEMAIN | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| CWE476_NULL_Pointer_Dereference__binary_if_02_good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| CWE476_NULL_Pointer_Dereference__binary_if_02_bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,111 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE476_NULL_Pointer_Dereference__binary_if_03.c | |||
| Label Definition File: CWE476_NULL_Pointer_Dereference.pointflaw.label.xml | |||
| Template File: point-flaw-03.tmpl.c | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 476 NULL Pointer Dereference | |||
| * Sinks: binary_if | |||
| * GoodSink: Do not check for NULL after the pointer has been dereferenced | |||
| * BadSink : Check for NULL after a pointer has already been dereferenced | |||
| * Flow Variant: 03 Control flow: if(5==5) and if(5!=5) | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #ifndef OMITBAD | |||
| void CWE476_NULL_Pointer_Dereference__binary_if_03_bad() | |||
| { | |||
| if(5==5) | |||
| { | |||
| { | |||
| twoIntsStruct *twoIntsStructPointer = NULL; | |||
| /* FLAW: Using a single & in the if statement will cause both sides of the expression to be evaluated | |||
| * thus causing a NPD */ | |||
| if ((twoIntsStructPointer != NULL) & (twoIntsStructPointer->intOne == 5)) | |||
| { | |||
| printLine("intOne == 5"); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* good1() uses if(5!=5) instead of if(5==5) */ | |||
| static void good1() | |||
| { | |||
| if(5!=5) | |||
| { | |||
| /* INCIDENTAL: CWE 561 Dead Code, the code below will never run */ | |||
| printLine("Benign, fixed string"); | |||
| } | |||
| else | |||
| { | |||
| { | |||
| twoIntsStruct *twoIntsStructPointer = NULL; | |||
| /* FIX: Use && in the if statement so that if the left side of the expression fails then | |||
| * the right side will not be evaluated */ | |||
| if ((twoIntsStructPointer != NULL) && (twoIntsStructPointer->intOne == 5)) | |||
| { | |||
| printLine("intOne == 5"); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /* good2() reverses the bodies in the if statement */ | |||
| static void good2() | |||
| { | |||
| if(5==5) | |||
| { | |||
| { | |||
| twoIntsStruct *twoIntsStructPointer = NULL; | |||
| /* FIX: Use && in the if statement so that if the left side of the expression fails then | |||
| * the right side will not be evaluated */ | |||
| if ((twoIntsStructPointer != NULL) && (twoIntsStructPointer->intOne == 5)) | |||
| { | |||
| printLine("intOne == 5"); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| void CWE476_NULL_Pointer_Dereference__binary_if_03_good() | |||
| { | |||
| good1(); | |||
| good2(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| its own for testing or for building a binary to use in testing binary | |||
| analysis tools. It is not used when compiling all the testcases as one | |||
| application, which is how source code analysis tools are tested. */ | |||
| #ifdef INCLUDEMAIN | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| CWE476_NULL_Pointer_Dereference__binary_if_03_good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| CWE476_NULL_Pointer_Dereference__binary_if_03_bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,117 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE476_NULL_Pointer_Dereference__binary_if_04.c | |||
| Label Definition File: CWE476_NULL_Pointer_Dereference.pointflaw.label.xml | |||
| Template File: point-flaw-04.tmpl.c | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 476 NULL Pointer Dereference | |||
| * Sinks: binary_if | |||
| * GoodSink: Do not check for NULL after the pointer has been dereferenced | |||
| * BadSink : Check for NULL after a pointer has already been dereferenced | |||
| * Flow Variant: 04 Control flow: if(STATIC_CONST_TRUE) and if(STATIC_CONST_FALSE) | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| /* The two variables below are declared "const", so a tool should | |||
| be able to identify that reads of these will always return their | |||
| initialized values. */ | |||
| static const int STATIC_CONST_TRUE = 1; /* true */ | |||
| static const int STATIC_CONST_FALSE = 0; /* false */ | |||
| #ifndef OMITBAD | |||
| void CWE476_NULL_Pointer_Dereference__binary_if_04_bad() | |||
| { | |||
| if(STATIC_CONST_TRUE) | |||
| { | |||
| { | |||
| twoIntsStruct *twoIntsStructPointer = NULL; | |||
| /* FLAW: Using a single & in the if statement will cause both sides of the expression to be evaluated | |||
| * thus causing a NPD */ | |||
| if ((twoIntsStructPointer != NULL) & (twoIntsStructPointer->intOne == 5)) | |||
| { | |||
| printLine("intOne == 5"); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* good1() uses if(STATIC_CONST_FALSE) instead of if(STATIC_CONST_TRUE) */ | |||
| static void good1() | |||
| { | |||
| if(STATIC_CONST_FALSE) | |||
| { | |||
| /* INCIDENTAL: CWE 561 Dead Code, the code below will never run */ | |||
| printLine("Benign, fixed string"); | |||
| } | |||
| else | |||
| { | |||
| { | |||
| twoIntsStruct *twoIntsStructPointer = NULL; | |||
| /* FIX: Use && in the if statement so that if the left side of the expression fails then | |||
| * the right side will not be evaluated */ | |||
| if ((twoIntsStructPointer != NULL) && (twoIntsStructPointer->intOne == 5)) | |||
| { | |||
| printLine("intOne == 5"); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /* good2() reverses the bodies in the if statement */ | |||
| static void good2() | |||
| { | |||
| if(STATIC_CONST_TRUE) | |||
| { | |||
| { | |||
| twoIntsStruct *twoIntsStructPointer = NULL; | |||
| /* FIX: Use && in the if statement so that if the left side of the expression fails then | |||
| * the right side will not be evaluated */ | |||
| if ((twoIntsStructPointer != NULL) && (twoIntsStructPointer->intOne == 5)) | |||
| { | |||
| printLine("intOne == 5"); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| void CWE476_NULL_Pointer_Dereference__binary_if_04_good() | |||
| { | |||
| good1(); | |||
| good2(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| its own for testing or for building a binary to use in testing binary | |||
| analysis tools. It is not used when compiling all the testcases as one | |||
| application, which is how source code analysis tools are tested. */ | |||
| #ifdef INCLUDEMAIN | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| CWE476_NULL_Pointer_Dereference__binary_if_04_good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| CWE476_NULL_Pointer_Dereference__binary_if_04_bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,447 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE606_Unchecked_Loop_Condition__char_connect_socket_02.c | |||
| Label Definition File: CWE606_Unchecked_Loop_Condition.label.xml | |||
| Template File: sources-sinks-02.tmpl.c | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 606 Unchecked Input For Loop Condition | |||
| * BadSource: connect_socket Read data using a connect socket (client side) | |||
| * GoodSource: Input a number less than MAX_LOOP | |||
| * Sinks: | |||
| * GoodSink: Use data as the for loop variant after checking to see if it is less than MAX_LOOP | |||
| * BadSink : Use data as the for loop variant without checking its size | |||
| * Flow Variant: 02 Control flow: if(1) and if(0) | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #define MAX_LOOP 10000 | |||
| #ifndef _WIN32 | |||
| #include <wchar.h> | |||
| #endif | |||
| #ifdef _WIN32 | |||
| #include <winsock2.h> | |||
| #include <windows.h> | |||
| #include <direct.h> | |||
| #pragma comment(lib, "ws2_32") /* include ws2_32.lib when linking */ | |||
| #define CLOSE_SOCKET closesocket | |||
| #else /* NOT _WIN32 */ | |||
| #include <sys/types.h> | |||
| #include <sys/socket.h> | |||
| #include <netinet/in.h> | |||
| #include <arpa/inet.h> | |||
| #include <unistd.h> | |||
| #define INVALID_SOCKET -1 | |||
| #define SOCKET_ERROR -1 | |||
| #define CLOSE_SOCKET close | |||
| #define SOCKET int | |||
| #endif | |||
| #define TCP_PORT 27015 | |||
| #define IP_ADDRESS "127.0.0.1" | |||
| #ifndef OMITBAD | |||
| void CWE606_Unchecked_Loop_Condition__char_connect_socket_02_bad() | |||
| { | |||
| char * data; | |||
| char dataBuffer[100] = ""; | |||
| data = dataBuffer; | |||
| if(1) | |||
| { | |||
| { | |||
| #ifdef _WIN32 | |||
| WSADATA wsaData; | |||
| int wsaDataInit = 0; | |||
| #endif | |||
| int recvResult; | |||
| struct sockaddr_in service; | |||
| char *replace; | |||
| SOCKET connectSocket = INVALID_SOCKET; | |||
| size_t dataLen = strlen(data); | |||
| do | |||
| { | |||
| #ifdef _WIN32 | |||
| if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| wsaDataInit = 1; | |||
| #endif | |||
| /* POTENTIAL FLAW: Read data using a connect socket */ | |||
| connectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |||
| if (connectSocket == INVALID_SOCKET) | |||
| { | |||
| break; | |||
| } | |||
| memset(&service, 0, sizeof(service)); | |||
| service.sin_family = AF_INET; | |||
| service.sin_addr.s_addr = inet_addr(IP_ADDRESS); | |||
| service.sin_port = htons(TCP_PORT); | |||
| if (connect(connectSocket, (struct sockaddr*)&service, sizeof(service)) == SOCKET_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| /* Abort on error or the connection was closed, make sure to recv one | |||
| * less char than is in the recv_buf in order to append a terminator */ | |||
| /* Abort on error or the connection was closed */ | |||
| recvResult = recv(connectSocket, (char *)(data + dataLen), sizeof(char) * (100 - dataLen - 1), 0); | |||
| if (recvResult == SOCKET_ERROR || recvResult == 0) | |||
| { | |||
| break; | |||
| } | |||
| /* Append null terminator */ | |||
| data[dataLen + recvResult / sizeof(char)] = '\0'; | |||
| /* Eliminate CRLF */ | |||
| replace = strchr(data, '\r'); | |||
| if (replace) | |||
| { | |||
| *replace = '\0'; | |||
| } | |||
| replace = strchr(data, '\n'); | |||
| if (replace) | |||
| { | |||
| *replace = '\0'; | |||
| } | |||
| } | |||
| while (0); | |||
| if (connectSocket != INVALID_SOCKET) | |||
| { | |||
| CLOSE_SOCKET(connectSocket); | |||
| } | |||
| #ifdef _WIN32 | |||
| if (wsaDataInit) | |||
| { | |||
| WSACleanup(); | |||
| } | |||
| #endif | |||
| } | |||
| } | |||
| if(1) | |||
| { | |||
| { | |||
| int i, n, intVariable; | |||
| if (sscanf(data, "%d", &n) == 1) | |||
| { | |||
| /* POTENTIAL FLAW: user-supplied value 'n' could lead to very large loop iteration */ | |||
| intVariable = 0; | |||
| for (i = 0; i < n; i++) | |||
| { | |||
| /* INCIDENTAL: CWE 561: Dead Code - non-avoidable if n <= 0 */ | |||
| intVariable++; /* avoid a dead/empty code block issue */ | |||
| } | |||
| printIntLine(intVariable); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* goodB2G1() - use badsource and goodsink by changing the second 1 to 0 */ | |||
| static void goodB2G1() | |||
| { | |||
| char * data; | |||
| char dataBuffer[100] = ""; | |||
| data = dataBuffer; | |||
| if(1) | |||
| { | |||
| { | |||
| #ifdef _WIN32 | |||
| WSADATA wsaData; | |||
| int wsaDataInit = 0; | |||
| #endif | |||
| int recvResult; | |||
| struct sockaddr_in service; | |||
| char *replace; | |||
| SOCKET connectSocket = INVALID_SOCKET; | |||
| size_t dataLen = strlen(data); | |||
| do | |||
| { | |||
| #ifdef _WIN32 | |||
| if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| wsaDataInit = 1; | |||
| #endif | |||
| /* POTENTIAL FLAW: Read data using a connect socket */ | |||
| connectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |||
| if (connectSocket == INVALID_SOCKET) | |||
| { | |||
| break; | |||
| } | |||
| memset(&service, 0, sizeof(service)); | |||
| service.sin_family = AF_INET; | |||
| service.sin_addr.s_addr = inet_addr(IP_ADDRESS); | |||
| service.sin_port = htons(TCP_PORT); | |||
| if (connect(connectSocket, (struct sockaddr*)&service, sizeof(service)) == SOCKET_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| /* Abort on error or the connection was closed, make sure to recv one | |||
| * less char than is in the recv_buf in order to append a terminator */ | |||
| /* Abort on error or the connection was closed */ | |||
| recvResult = recv(connectSocket, (char *)(data + dataLen), sizeof(char) * (100 - dataLen - 1), 0); | |||
| if (recvResult == SOCKET_ERROR || recvResult == 0) | |||
| { | |||
| break; | |||
| } | |||
| /* Append null terminator */ | |||
| data[dataLen + recvResult / sizeof(char)] = '\0'; | |||
| /* Eliminate CRLF */ | |||
| replace = strchr(data, '\r'); | |||
| if (replace) | |||
| { | |||
| *replace = '\0'; | |||
| } | |||
| replace = strchr(data, '\n'); | |||
| if (replace) | |||
| { | |||
| *replace = '\0'; | |||
| } | |||
| } | |||
| while (0); | |||
| if (connectSocket != INVALID_SOCKET) | |||
| { | |||
| CLOSE_SOCKET(connectSocket); | |||
| } | |||
| #ifdef _WIN32 | |||
| if (wsaDataInit) | |||
| { | |||
| WSACleanup(); | |||
| } | |||
| #endif | |||
| } | |||
| } | |||
| if(0) | |||
| { | |||
| /* INCIDENTAL: CWE 561 Dead Code, the code below will never run */ | |||
| printLine("Benign, fixed string"); | |||
| } | |||
| else | |||
| { | |||
| { | |||
| int i, n, intVariable; | |||
| if (sscanf(data, "%d", &n) == 1) | |||
| { | |||
| /* FIX: limit loop iteration counts */ | |||
| if (n < MAX_LOOP) | |||
| { | |||
| intVariable = 0; | |||
| for (i = 0; i < n; i++) | |||
| { | |||
| /* INCIDENTAL: CWE 561: Dead Code - non-avoidable if n <= 0 */ | |||
| intVariable++; /* avoid a dead/empty code block issue */ | |||
| } | |||
| printIntLine(intVariable); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /* goodB2G2() - use badsource and goodsink by reversing the blocks in the second if */ | |||
| static void goodB2G2() | |||
| { | |||
| char * data; | |||
| char dataBuffer[100] = ""; | |||
| data = dataBuffer; | |||
| if(1) | |||
| { | |||
| { | |||
| #ifdef _WIN32 | |||
| WSADATA wsaData; | |||
| int wsaDataInit = 0; | |||
| #endif | |||
| int recvResult; | |||
| struct sockaddr_in service; | |||
| char *replace; | |||
| SOCKET connectSocket = INVALID_SOCKET; | |||
| size_t dataLen = strlen(data); | |||
| do | |||
| { | |||
| #ifdef _WIN32 | |||
| if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| wsaDataInit = 1; | |||
| #endif | |||
| /* POTENTIAL FLAW: Read data using a connect socket */ | |||
| connectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |||
| if (connectSocket == INVALID_SOCKET) | |||
| { | |||
| break; | |||
| } | |||
| memset(&service, 0, sizeof(service)); | |||
| service.sin_family = AF_INET; | |||
| service.sin_addr.s_addr = inet_addr(IP_ADDRESS); | |||
| service.sin_port = htons(TCP_PORT); | |||
| if (connect(connectSocket, (struct sockaddr*)&service, sizeof(service)) == SOCKET_ERROR) | |||
| { | |||
| break; | |||
| } | |||
| /* Abort on error or the connection was closed, make sure to recv one | |||
| * less char than is in the recv_buf in order to append a terminator */ | |||
| /* Abort on error or the connection was closed */ | |||
| recvResult = recv(connectSocket, (char *)(data + dataLen), sizeof(char) * (100 - dataLen - 1), 0); | |||
| if (recvResult == SOCKET_ERROR || recvResult == 0) | |||
| { | |||
| break; | |||
| } | |||
| /* Append null terminator */ | |||
| data[dataLen + recvResult / sizeof(char)] = '\0'; | |||
| /* Eliminate CRLF */ | |||
| replace = strchr(data, '\r'); | |||
| if (replace) | |||
| { | |||
| *replace = '\0'; | |||
| } | |||
| replace = strchr(data, '\n'); | |||
| if (replace) | |||
| { | |||
| *replace = '\0'; | |||
| } | |||
| } | |||
| while (0); | |||
| if (connectSocket != INVALID_SOCKET) | |||
| { | |||
| CLOSE_SOCKET(connectSocket); | |||
| } | |||
| #ifdef _WIN32 | |||
| if (wsaDataInit) | |||
| { | |||
| WSACleanup(); | |||
| } | |||
| #endif | |||
| } | |||
| } | |||
| if(1) | |||
| { | |||
| { | |||
| int i, n, intVariable; | |||
| if (sscanf(data, "%d", &n) == 1) | |||
| { | |||
| /* FIX: limit loop iteration counts */ | |||
| if (n < MAX_LOOP) | |||
| { | |||
| intVariable = 0; | |||
| for (i = 0; i < n; i++) | |||
| { | |||
| /* INCIDENTAL: CWE 561: Dead Code - non-avoidable if n <= 0 */ | |||
| intVariable++; /* avoid a dead/empty code block issue */ | |||
| } | |||
| printIntLine(intVariable); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /* goodG2B1() - use goodsource and badsink by changing the first 1 to 0 */ | |||
| static void goodG2B1() | |||
| { | |||
| char * data; | |||
| char dataBuffer[100] = ""; | |||
| data = dataBuffer; | |||
| if(0) | |||
| { | |||
| /* INCIDENTAL: CWE 561 Dead Code, the code below will never run */ | |||
| printLine("Benign, fixed string"); | |||
| } | |||
| else | |||
| { | |||
| /* FIX: Set data to a number less than MAX_LOOP */ | |||
| strcpy(data, "15"); | |||
| } | |||
| if(1) | |||
| { | |||
| { | |||
| int i, n, intVariable; | |||
| if (sscanf(data, "%d", &n) == 1) | |||
| { | |||
| /* POTENTIAL FLAW: user-supplied value 'n' could lead to very large loop iteration */ | |||
| intVariable = 0; | |||
| for (i = 0; i < n; i++) | |||
| { | |||
| /* INCIDENTAL: CWE 561: Dead Code - non-avoidable if n <= 0 */ | |||
| intVariable++; /* avoid a dead/empty code block issue */ | |||
| } | |||
| printIntLine(intVariable); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /* goodG2B2() - use goodsource and badsink by reversing the blocks in the first if */ | |||
| static void goodG2B2() | |||
| { | |||
| char * data; | |||
| char dataBuffer[100] = ""; | |||
| data = dataBuffer; | |||
| if(1) | |||
| { | |||
| /* FIX: Set data to a number less than MAX_LOOP */ | |||
| strcpy(data, "15"); | |||
| } | |||
| if(1) | |||
| { | |||
| { | |||
| int i, n, intVariable; | |||
| if (sscanf(data, "%d", &n) == 1) | |||
| { | |||
| /* POTENTIAL FLAW: user-supplied value 'n' could lead to very large loop iteration */ | |||
| intVariable = 0; | |||
| for (i = 0; i < n; i++) | |||
| { | |||
| /* INCIDENTAL: CWE 561: Dead Code - non-avoidable if n <= 0 */ | |||
| intVariable++; /* avoid a dead/empty code block issue */ | |||
| } | |||
| printIntLine(intVariable); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| void CWE606_Unchecked_Loop_Condition__char_connect_socket_02_good() | |||
| { | |||
| goodB2G1(); | |||
| goodB2G2(); | |||
| goodG2B1(); | |||
| goodG2B2(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| its own for testing or for building a binary to use in testing binary | |||
| analysis tools. It is not used when compiling all the testcases as one | |||
| application, which is how source code analysis tools are tested. */ | |||
| #ifdef INCLUDEMAIN | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| CWE606_Unchecked_Loop_Condition__char_connect_socket_02_good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| CWE606_Unchecked_Loop_Condition__char_connect_socket_02_bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,164 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE606_Unchecked_Loop_Condition__char_environment_01.c | |||
| Label Definition File: CWE606_Unchecked_Loop_Condition.label.xml | |||
| Template File: sources-sinks-01.tmpl.c | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 606 Unchecked Input For Loop Condition | |||
| * BadSource: environment Read input from an environment variable | |||
| * GoodSource: Input a number less than MAX_LOOP | |||
| * Sinks: | |||
| * GoodSink: Use data as the for loop variant after checking to see if it is less than MAX_LOOP | |||
| * BadSink : Use data as the for loop variant without checking its size | |||
| * Flow Variant: 01 Baseline | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #define MAX_LOOP 10000 | |||
| #ifndef _WIN32 | |||
| #include <wchar.h> | |||
| #endif | |||
| #define ENV_VARIABLE "ADD" | |||
| #ifdef _WIN32 | |||
| #define GETENV getenv | |||
| #else | |||
| #define GETENV getenv | |||
| #endif | |||
| #ifndef OMITBAD | |||
| void CWE606_Unchecked_Loop_Condition__char_environment_01_bad() | |||
| { | |||
| char * data; | |||
| char dataBuffer[100] = ""; | |||
| data = dataBuffer; | |||
| { | |||
| /* Append input from an environment variable to data */ | |||
| size_t dataLen = strlen(data); | |||
| char * environment = GETENV(ENV_VARIABLE); | |||
| /* If there is data in the environment variable */ | |||
| if (environment != NULL) | |||
| { | |||
| /* POTENTIAL FLAW: Read data from an environment variable */ | |||
| strncat(data+dataLen, environment, 100-dataLen-1); | |||
| } | |||
| } | |||
| { | |||
| int i, n, intVariable; | |||
| if (sscanf(data, "%d", &n) == 1) | |||
| { | |||
| /* POTENTIAL FLAW: user-supplied value 'n' could lead to very large loop iteration */ | |||
| intVariable = 0; | |||
| for (i = 0; i < n; i++) | |||
| { | |||
| /* INCIDENTAL: CWE 561: Dead Code - non-avoidable if n <= 0 */ | |||
| intVariable++; /* avoid a dead/empty code block issue */ | |||
| } | |||
| printIntLine(intVariable); | |||
| } | |||
| } | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* goodG2B uses the GoodSource with the BadSink */ | |||
| static void goodG2B() | |||
| { | |||
| char * data; | |||
| char dataBuffer[100] = ""; | |||
| data = dataBuffer; | |||
| /* FIX: Set data to a number less than MAX_LOOP */ | |||
| strcpy(data, "15"); | |||
| { | |||
| int i, n, intVariable; | |||
| if (sscanf(data, "%d", &n) == 1) | |||
| { | |||
| /* POTENTIAL FLAW: user-supplied value 'n' could lead to very large loop iteration */ | |||
| intVariable = 0; | |||
| for (i = 0; i < n; i++) | |||
| { | |||
| /* INCIDENTAL: CWE 561: Dead Code - non-avoidable if n <= 0 */ | |||
| intVariable++; /* avoid a dead/empty code block issue */ | |||
| } | |||
| printIntLine(intVariable); | |||
| } | |||
| } | |||
| } | |||
| /* goodB2G uses the BadSource with the GoodSink */ | |||
| static void goodB2G() | |||
| { | |||
| char * data; | |||
| char dataBuffer[100] = ""; | |||
| data = dataBuffer; | |||
| { | |||
| /* Append input from an environment variable to data */ | |||
| size_t dataLen = strlen(data); | |||
| char * environment = GETENV(ENV_VARIABLE); | |||
| /* If there is data in the environment variable */ | |||
| if (environment != NULL) | |||
| { | |||
| /* POTENTIAL FLAW: Read data from an environment variable */ | |||
| strncat(data+dataLen, environment, 100-dataLen-1); | |||
| } | |||
| } | |||
| { | |||
| int i, n, intVariable; | |||
| if (sscanf(data, "%d", &n) == 1) | |||
| { | |||
| /* FIX: limit loop iteration counts */ | |||
| if (n < MAX_LOOP) | |||
| { | |||
| intVariable = 0; | |||
| for (i = 0; i < n; i++) | |||
| { | |||
| /* INCIDENTAL: CWE 561: Dead Code - non-avoidable if n <= 0 */ | |||
| intVariable++; /* avoid a dead/empty code block issue */ | |||
| } | |||
| printIntLine(intVariable); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| void CWE606_Unchecked_Loop_Condition__char_environment_01_good() | |||
| { | |||
| goodG2B(); | |||
| goodB2G(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| its own for testing or for building a binary to use in testing binary | |||
| analysis tools. It is not used when compiling all the testcases as one | |||
| application, which is how source code analysis tools are tested. */ | |||
| #ifdef INCLUDEMAIN | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| CWE606_Unchecked_Loop_Condition__char_environment_01_good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| CWE606_Unchecked_Loop_Condition__char_environment_01_bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,138 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE606_Unchecked_Loop_Condition__char_file_22b.c | |||
| Label Definition File: CWE606_Unchecked_Loop_Condition.label.xml | |||
| Template File: sources-sinks-22b.tmpl.c | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 606 Unchecked Input For Loop Condition | |||
| * BadSource: file Read input from a file | |||
| * GoodSource: Input a number less than MAX_LOOP | |||
| * Sinks: | |||
| * GoodSink: Use data as the for loop variant after checking to see if it is less than MAX_LOOP | |||
| * BadSink : Use data as the for loop variant without checking its size | |||
| * Flow Variant: 22 Control flow: Flow controlled by value of a global variable. Sink functions are in a separate file from sources. | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #define MAX_LOOP 10000 | |||
| #ifndef _WIN32 | |||
| #include <wchar.h> | |||
| #endif | |||
| #ifndef OMITBAD | |||
| /* The global variable below is used to drive control flow in the sink function */ | |||
| extern int CWE606_Unchecked_Loop_Condition__char_file_22_badGlobal; | |||
| void CWE606_Unchecked_Loop_Condition__char_file_22_badSink(char * data) | |||
| { | |||
| if(CWE606_Unchecked_Loop_Condition__char_file_22_badGlobal) | |||
| { | |||
| { | |||
| int i, n, intVariable; | |||
| if (sscanf(data, "%d", &n) == 1) | |||
| { | |||
| /* POTENTIAL FLAW: user-supplied value 'n' could lead to very large loop iteration */ | |||
| intVariable = 0; | |||
| for (i = 0; i < n; i++) | |||
| { | |||
| /* INCIDENTAL: CWE 561: Dead Code - non-avoidable if n <= 0 */ | |||
| intVariable++; /* avoid a dead/empty code block issue */ | |||
| } | |||
| printIntLine(intVariable); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* The global variables below are used to drive control flow in the sink functions. */ | |||
| extern int CWE606_Unchecked_Loop_Condition__char_file_22_goodB2G1Global; | |||
| extern int CWE606_Unchecked_Loop_Condition__char_file_22_goodB2G2Global; | |||
| extern int CWE606_Unchecked_Loop_Condition__char_file_22_goodG2BGlobal; | |||
| /* goodB2G1() - use badsource and goodsink by setting the static variable to false instead of true */ | |||
| void CWE606_Unchecked_Loop_Condition__char_file_22_goodB2G1Sink(char * data) | |||
| { | |||
| if(CWE606_Unchecked_Loop_Condition__char_file_22_goodB2G1Global) | |||
| { | |||
| /* INCIDENTAL: CWE 561 Dead Code, the code below will never run */ | |||
| printLine("Benign, fixed string"); | |||
| } | |||
| else | |||
| { | |||
| { | |||
| int i, n, intVariable; | |||
| if (sscanf(data, "%d", &n) == 1) | |||
| { | |||
| /* FIX: limit loop iteration counts */ | |||
| if (n < MAX_LOOP) | |||
| { | |||
| intVariable = 0; | |||
| for (i = 0; i < n; i++) | |||
| { | |||
| /* INCIDENTAL: CWE 561: Dead Code - non-avoidable if n <= 0 */ | |||
| intVariable++; /* avoid a dead/empty code block issue */ | |||
| } | |||
| printIntLine(intVariable); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /* goodB2G2() - use badsource and goodsink by reversing the blocks in the if in the sink function */ | |||
| void CWE606_Unchecked_Loop_Condition__char_file_22_goodB2G2Sink(char * data) | |||
| { | |||
| if(CWE606_Unchecked_Loop_Condition__char_file_22_goodB2G2Global) | |||
| { | |||
| { | |||
| int i, n, intVariable; | |||
| if (sscanf(data, "%d", &n) == 1) | |||
| { | |||
| /* FIX: limit loop iteration counts */ | |||
| if (n < MAX_LOOP) | |||
| { | |||
| intVariable = 0; | |||
| for (i = 0; i < n; i++) | |||
| { | |||
| /* INCIDENTAL: CWE 561: Dead Code - non-avoidable if n <= 0 */ | |||
| intVariable++; /* avoid a dead/empty code block issue */ | |||
| } | |||
| printIntLine(intVariable); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /* goodG2B() - use goodsource and badsink */ | |||
| void CWE606_Unchecked_Loop_Condition__char_file_22_goodG2BSink(char * data) | |||
| { | |||
| if(CWE606_Unchecked_Loop_Condition__char_file_22_goodG2BGlobal) | |||
| { | |||
| { | |||
| int i, n, intVariable; | |||
| if (sscanf(data, "%d", &n) == 1) | |||
| { | |||
| /* POTENTIAL FLAW: user-supplied value 'n' could lead to very large loop iteration */ | |||
| intVariable = 0; | |||
| for (i = 0; i < n; i++) | |||
| { | |||
| /* INCIDENTAL: CWE 561: Dead Code - non-avoidable if n <= 0 */ | |||
| intVariable++; /* avoid a dead/empty code block issue */ | |||
| } | |||
| printIntLine(intVariable); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| @@ -0,0 +1,51 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE690_NULL_Deref_From_Return__char_calloc_82.h | |||
| Label Definition File: CWE690_NULL_Deref_From_Return.free.label.xml | |||
| Template File: source-sinks-82.tmpl.h | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 690 Unchecked Return Value To NULL Pointer | |||
| * BadSource: calloc Allocate data using calloc() | |||
| * Sinks: | |||
| * GoodSink: Check to see if the data allocation failed and if not, use data | |||
| * BadSink : Don't check for NULL and use data | |||
| * Flow Variant: 82 Data flow: data passed in a parameter to an virtual method called via a pointer | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #include <wchar.h> | |||
| namespace CWE690_NULL_Deref_From_Return__char_calloc_82 | |||
| { | |||
| class CWE690_NULL_Deref_From_Return__char_calloc_82_base | |||
| { | |||
| public: | |||
| /* pure virtual function */ | |||
| virtual void action(char * data) = 0; | |||
| }; | |||
| #ifndef OMITBAD | |||
| class CWE690_NULL_Deref_From_Return__char_calloc_82_bad : public CWE690_NULL_Deref_From_Return__char_calloc_82_base | |||
| { | |||
| public: | |||
| void action(char * data); | |||
| }; | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| class CWE690_NULL_Deref_From_Return__char_calloc_82_goodB2G : public CWE690_NULL_Deref_From_Return__char_calloc_82_base | |||
| { | |||
| public: | |||
| void action(char * data); | |||
| }; | |||
| #endif /* OMITGOOD */ | |||
| } | |||
| @@ -0,0 +1,87 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE690_NULL_Deref_From_Return__char_calloc_82a.cpp | |||
| Label Definition File: CWE690_NULL_Deref_From_Return.free.label.xml | |||
| Template File: source-sinks-82a.tmpl.cpp | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 690 Unchecked Return Value To NULL Pointer | |||
| * BadSource: calloc Allocate data using calloc() | |||
| * Sinks: | |||
| * GoodSink: Check to see if the data allocation failed and if not, use data | |||
| * BadSink : Don't check for NULL and use data | |||
| * Flow Variant: 82 Data flow: data passed in a parameter to an virtual method called via a pointer | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #include "CWE690_NULL_Deref_From_Return__char_calloc_82.h" | |||
| namespace CWE690_NULL_Deref_From_Return__char_calloc_82 | |||
| { | |||
| #ifndef OMITBAD | |||
| void bad() | |||
| { | |||
| char * data; | |||
| data = NULL; /* Initialize data */ | |||
| /* POTENTIAL FLAW: Allocate memory without checking if the memory allocation function failed */ | |||
| data = (char *)calloc(20, sizeof(char)); | |||
| CWE690_NULL_Deref_From_Return__char_calloc_82_base* baseObject = new CWE690_NULL_Deref_From_Return__char_calloc_82_bad; | |||
| baseObject->action(data); | |||
| delete baseObject; | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* goodB2G uses the BadSource with the GoodSink */ | |||
| static void goodB2G() | |||
| { | |||
| char * data; | |||
| data = NULL; /* Initialize data */ | |||
| /* POTENTIAL FLAW: Allocate memory without checking if the memory allocation function failed */ | |||
| data = (char *)calloc(20, sizeof(char)); | |||
| CWE690_NULL_Deref_From_Return__char_calloc_82_base* baseObject = new CWE690_NULL_Deref_From_Return__char_calloc_82_goodB2G; | |||
| baseObject->action(data); | |||
| delete baseObject; | |||
| } | |||
| void good() | |||
| { | |||
| goodB2G(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| } /* close namespace */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| its own for testing or for building a binary to use in testing binary | |||
| analysis tools. It is not used when compiling all the testcases as one | |||
| application, which is how source code analysis tools are tested. */ | |||
| #ifdef INCLUDEMAIN | |||
| using namespace CWE690_NULL_Deref_From_Return__char_calloc_82; /* so that we can use good and bad easily */ | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,51 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE690_NULL_Deref_From_Return__char_malloc_82.h | |||
| Label Definition File: CWE690_NULL_Deref_From_Return.free.label.xml | |||
| Template File: source-sinks-82.tmpl.h | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 690 Unchecked Return Value To NULL Pointer | |||
| * BadSource: malloc Allocate data using malloc() | |||
| * Sinks: | |||
| * GoodSink: Check to see if the data allocation failed and if not, use data | |||
| * BadSink : Don't check for NULL and use data | |||
| * Flow Variant: 82 Data flow: data passed in a parameter to an virtual method called via a pointer | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #include <wchar.h> | |||
| namespace CWE690_NULL_Deref_From_Return__char_malloc_82 | |||
| { | |||
| class CWE690_NULL_Deref_From_Return__char_malloc_82_base | |||
| { | |||
| public: | |||
| /* pure virtual function */ | |||
| virtual void action(char * data) = 0; | |||
| }; | |||
| #ifndef OMITBAD | |||
| class CWE690_NULL_Deref_From_Return__char_malloc_82_bad : public CWE690_NULL_Deref_From_Return__char_malloc_82_base | |||
| { | |||
| public: | |||
| void action(char * data); | |||
| }; | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| class CWE690_NULL_Deref_From_Return__char_malloc_82_goodB2G : public CWE690_NULL_Deref_From_Return__char_malloc_82_base | |||
| { | |||
| public: | |||
| void action(char * data); | |||
| }; | |||
| #endif /* OMITGOOD */ | |||
| } | |||
| @@ -0,0 +1,87 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE690_NULL_Deref_From_Return__char_malloc_82a.cpp | |||
| Label Definition File: CWE690_NULL_Deref_From_Return.free.label.xml | |||
| Template File: source-sinks-82a.tmpl.cpp | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 690 Unchecked Return Value To NULL Pointer | |||
| * BadSource: malloc Allocate data using malloc() | |||
| * Sinks: | |||
| * GoodSink: Check to see if the data allocation failed and if not, use data | |||
| * BadSink : Don't check for NULL and use data | |||
| * Flow Variant: 82 Data flow: data passed in a parameter to an virtual method called via a pointer | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #include "CWE690_NULL_Deref_From_Return__char_malloc_82.h" | |||
| namespace CWE690_NULL_Deref_From_Return__char_malloc_82 | |||
| { | |||
| #ifndef OMITBAD | |||
| void bad() | |||
| { | |||
| char * data; | |||
| data = NULL; /* Initialize data */ | |||
| /* POTENTIAL FLAW: Allocate memory without checking if the memory allocation function failed */ | |||
| data = (char *)malloc(20*sizeof(char)); | |||
| CWE690_NULL_Deref_From_Return__char_malloc_82_base* baseObject = new CWE690_NULL_Deref_From_Return__char_malloc_82_bad; | |||
| baseObject->action(data); | |||
| delete baseObject; | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* goodB2G uses the BadSource with the GoodSink */ | |||
| static void goodB2G() | |||
| { | |||
| char * data; | |||
| data = NULL; /* Initialize data */ | |||
| /* POTENTIAL FLAW: Allocate memory without checking if the memory allocation function failed */ | |||
| data = (char *)malloc(20*sizeof(char)); | |||
| CWE690_NULL_Deref_From_Return__char_malloc_82_base* baseObject = new CWE690_NULL_Deref_From_Return__char_malloc_82_goodB2G; | |||
| baseObject->action(data); | |||
| delete baseObject; | |||
| } | |||
| void good() | |||
| { | |||
| goodB2G(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| } /* close namespace */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| its own for testing or for building a binary to use in testing binary | |||
| analysis tools. It is not used when compiling all the testcases as one | |||
| application, which is how source code analysis tools are tested. */ | |||
| #ifdef INCLUDEMAIN | |||
| using namespace CWE690_NULL_Deref_From_Return__char_malloc_82; /* so that we can use good and bad easily */ | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,52 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE690_NULL_Deref_From_Return__char_realloc_84.h | |||
| Label Definition File: CWE690_NULL_Deref_From_Return.free.label.xml | |||
| Template File: source-sinks-84.tmpl.h | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 690 Unchecked Return Value To NULL Pointer | |||
| * BadSource: realloc Allocate data using realloc() | |||
| * Sinks: | |||
| * GoodSink: Check to see if the data allocation failed and if not, use data | |||
| * BadSink : Don't check for NULL and use data | |||
| * Flow Variant: 84 Data flow: data passed to class constructor and destructor by declaring the class object on the heap and deleting it after use | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #include <wchar.h> | |||
| namespace CWE690_NULL_Deref_From_Return__char_realloc_84 | |||
| { | |||
| #ifndef OMITBAD | |||
| class CWE690_NULL_Deref_From_Return__char_realloc_84_bad | |||
| { | |||
| public: | |||
| CWE690_NULL_Deref_From_Return__char_realloc_84_bad(char * dataCopy); | |||
| ~CWE690_NULL_Deref_From_Return__char_realloc_84_bad(); | |||
| private: | |||
| char * data; | |||
| }; | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| class CWE690_NULL_Deref_From_Return__char_realloc_84_goodB2G | |||
| { | |||
| public: | |||
| CWE690_NULL_Deref_From_Return__char_realloc_84_goodB2G(char * dataCopy); | |||
| ~CWE690_NULL_Deref_From_Return__char_realloc_84_goodB2G(); | |||
| private: | |||
| char * data; | |||
| }; | |||
| #endif /* OMITGOOD */ | |||
| } | |||
| @@ -0,0 +1,81 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE690_NULL_Deref_From_Return__char_realloc_84a.cpp | |||
| Label Definition File: CWE690_NULL_Deref_From_Return.free.label.xml | |||
| Template File: source-sinks-84a.tmpl.cpp | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 690 Unchecked Return Value To NULL Pointer | |||
| * BadSource: realloc Allocate data using realloc() | |||
| * Sinks: | |||
| * GoodSink: Check to see if the data allocation failed and if not, use data | |||
| * BadSink : Don't check for NULL and use data | |||
| * Flow Variant: 84 Data flow: data passed to class constructor and destructor by declaring the class object on the heap and deleting it after use | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #include "CWE690_NULL_Deref_From_Return__char_realloc_84.h" | |||
| namespace CWE690_NULL_Deref_From_Return__char_realloc_84 | |||
| { | |||
| #ifndef OMITBAD | |||
| void bad() | |||
| { | |||
| char * data; | |||
| data = NULL; /* Initialize data */ | |||
| CWE690_NULL_Deref_From_Return__char_realloc_84_bad * badObject = new CWE690_NULL_Deref_From_Return__char_realloc_84_bad(data); | |||
| delete badObject; | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* goodB2G uses the BadSource with the GoodSink */ | |||
| static void goodB2G() | |||
| { | |||
| char * data; | |||
| data = NULL; /* Initialize data */ | |||
| CWE690_NULL_Deref_From_Return__char_realloc_84_goodB2G * goodB2GObject = new CWE690_NULL_Deref_From_Return__char_realloc_84_goodB2G(data); | |||
| delete goodB2GObject; | |||
| } | |||
| void good() | |||
| { | |||
| goodB2G(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| } /* close namespace */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| its own for testing or for building a binary to use in testing binary | |||
| analysis tools. It is not used when compiling all the testcases as one | |||
| application, which is how source code analysis tools are tested. */ | |||
| #ifdef INCLUDEMAIN | |||
| using namespace CWE690_NULL_Deref_From_Return__char_realloc_84; /* so that we can use good and bad easily */ | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,49 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE690_NULL_Deref_From_Return__fopen_82.h | |||
| Label Definition File: CWE690_NULL_Deref_From_Return.fclose.label.xml | |||
| Template File: source-sinks-82.tmpl.h | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 690 Unchecked Return Value To NULL Pointer | |||
| * BadSource: fopen Open data with fopen() | |||
| * Sinks: 0 | |||
| * GoodSink: Check data for NULL | |||
| * BadSink : Do not check data for NULL | |||
| * Flow Variant: 82 Data flow: data passed in a parameter to an virtual method called via a pointer | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| namespace CWE690_NULL_Deref_From_Return__fopen_82 | |||
| { | |||
| class CWE690_NULL_Deref_From_Return__fopen_82_base | |||
| { | |||
| public: | |||
| /* pure virtual function */ | |||
| virtual void action(FILE * data) = 0; | |||
| }; | |||
| #ifndef OMITBAD | |||
| class CWE690_NULL_Deref_From_Return__fopen_82_bad : public CWE690_NULL_Deref_From_Return__fopen_82_base | |||
| { | |||
| public: | |||
| void action(FILE * data); | |||
| }; | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| class CWE690_NULL_Deref_From_Return__fopen_82_goodB2G : public CWE690_NULL_Deref_From_Return__fopen_82_base | |||
| { | |||
| public: | |||
| void action(FILE * data); | |||
| }; | |||
| #endif /* OMITGOOD */ | |||
| } | |||
| @@ -0,0 +1,89 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE690_NULL_Deref_From_Return__fopen_82a.cpp | |||
| Label Definition File: CWE690_NULL_Deref_From_Return.fclose.label.xml | |||
| Template File: source-sinks-82a.tmpl.cpp | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 690 Unchecked Return Value To NULL Pointer | |||
| * BadSource: fopen Open data with fopen() | |||
| * Sinks: 0 | |||
| * GoodSink: Check data for NULL | |||
| * BadSink : Do not check data for NULL | |||
| * Flow Variant: 82 Data flow: data passed in a parameter to an virtual method called via a pointer | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #include "CWE690_NULL_Deref_From_Return__fopen_82.h" | |||
| namespace CWE690_NULL_Deref_From_Return__fopen_82 | |||
| { | |||
| #ifndef OMITBAD | |||
| void bad() | |||
| { | |||
| FILE * data; | |||
| /* Initialize data */ | |||
| data = NULL; | |||
| /* POTENTIAL FLAW: Open a file without checking the return value for NULL */ | |||
| data = fopen("file.txt", "w+"); | |||
| CWE690_NULL_Deref_From_Return__fopen_82_base* baseObject = new CWE690_NULL_Deref_From_Return__fopen_82_bad; | |||
| baseObject->action(data); | |||
| delete baseObject; | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* goodB2G uses the BadSource with the GoodSink */ | |||
| static void goodB2G() | |||
| { | |||
| FILE * data; | |||
| /* Initialize data */ | |||
| data = NULL; | |||
| /* POTENTIAL FLAW: Open a file without checking the return value for NULL */ | |||
| data = fopen("file.txt", "w+"); | |||
| CWE690_NULL_Deref_From_Return__fopen_82_base* baseObject = new CWE690_NULL_Deref_From_Return__fopen_82_goodB2G; | |||
| baseObject->action(data); | |||
| delete baseObject; | |||
| } | |||
| void good() | |||
| { | |||
| goodB2G(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| } /* close namespace */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| its own for testing or for building a binary to use in testing binary | |||
| analysis tools. It is not used when compiling all the testcases as one | |||
| application, which is how source code analysis tools are tested. */ | |||
| #ifdef INCLUDEMAIN | |||
| using namespace CWE690_NULL_Deref_From_Return__fopen_82; /* so that we can use good and bad easily */ | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,51 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE690_NULL_Deref_From_Return__struct_realloc_82.h | |||
| Label Definition File: CWE690_NULL_Deref_From_Return.free.label.xml | |||
| Template File: source-sinks-82.tmpl.h | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 690 Unchecked Return Value To NULL Pointer | |||
| * BadSource: realloc Allocate data using realloc() | |||
| * Sinks: | |||
| * GoodSink: Check to see if the data allocation failed and if not, use data | |||
| * BadSink : Don't check for NULL and use data | |||
| * Flow Variant: 82 Data flow: data passed in a parameter to an virtual method called via a pointer | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #include <wchar.h> | |||
| namespace CWE690_NULL_Deref_From_Return__struct_realloc_82 | |||
| { | |||
| class CWE690_NULL_Deref_From_Return__struct_realloc_82_base | |||
| { | |||
| public: | |||
| /* pure virtual function */ | |||
| virtual void action(twoIntsStruct * data) = 0; | |||
| }; | |||
| #ifndef OMITBAD | |||
| class CWE690_NULL_Deref_From_Return__struct_realloc_82_bad : public CWE690_NULL_Deref_From_Return__struct_realloc_82_base | |||
| { | |||
| public: | |||
| void action(twoIntsStruct * data); | |||
| }; | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| class CWE690_NULL_Deref_From_Return__struct_realloc_82_goodB2G : public CWE690_NULL_Deref_From_Return__struct_realloc_82_base | |||
| { | |||
| public: | |||
| void action(twoIntsStruct * data); | |||
| }; | |||
| #endif /* OMITGOOD */ | |||
| } | |||
| @@ -0,0 +1,87 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE690_NULL_Deref_From_Return__struct_realloc_82a.cpp | |||
| Label Definition File: CWE690_NULL_Deref_From_Return.free.label.xml | |||
| Template File: source-sinks-82a.tmpl.cpp | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 690 Unchecked Return Value To NULL Pointer | |||
| * BadSource: realloc Allocate data using realloc() | |||
| * Sinks: | |||
| * GoodSink: Check to see if the data allocation failed and if not, use data | |||
| * BadSink : Don't check for NULL and use data | |||
| * Flow Variant: 82 Data flow: data passed in a parameter to an virtual method called via a pointer | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #include "CWE690_NULL_Deref_From_Return__struct_realloc_82.h" | |||
| namespace CWE690_NULL_Deref_From_Return__struct_realloc_82 | |||
| { | |||
| #ifndef OMITBAD | |||
| void bad() | |||
| { | |||
| twoIntsStruct * data; | |||
| data = NULL; /* Initialize data */ | |||
| /* POTENTIAL FLAW: Allocate memory without checking if the memory allocation function failed */ | |||
| data = (twoIntsStruct *)realloc(data, 1*sizeof(twoIntsStruct)); | |||
| CWE690_NULL_Deref_From_Return__struct_realloc_82_base* baseObject = new CWE690_NULL_Deref_From_Return__struct_realloc_82_bad; | |||
| baseObject->action(data); | |||
| delete baseObject; | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* goodB2G uses the BadSource with the GoodSink */ | |||
| static void goodB2G() | |||
| { | |||
| twoIntsStruct * data; | |||
| data = NULL; /* Initialize data */ | |||
| /* POTENTIAL FLAW: Allocate memory without checking if the memory allocation function failed */ | |||
| data = (twoIntsStruct *)realloc(data, 1*sizeof(twoIntsStruct)); | |||
| CWE690_NULL_Deref_From_Return__struct_realloc_82_base* baseObject = new CWE690_NULL_Deref_From_Return__struct_realloc_82_goodB2G; | |||
| baseObject->action(data); | |||
| delete baseObject; | |||
| } | |||
| void good() | |||
| { | |||
| goodB2G(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| } /* close namespace */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| its own for testing or for building a binary to use in testing binary | |||
| analysis tools. It is not used when compiling all the testcases as one | |||
| application, which is how source code analysis tools are tested. */ | |||
| #ifdef INCLUDEMAIN | |||
| using namespace CWE690_NULL_Deref_From_Return__struct_realloc_82; /* so that we can use good and bad easily */ | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,80 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE775_Missing_Release_of_File_Descriptor_or_Handle__fopen_no_close_01.c | |||
| Label Definition File: CWE775_Missing_Release_of_File_Descriptor_or_Handle__fopen_no_close.label.xml | |||
| Template File: source-sinks-01.tmpl.c | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 775 Missing Release of File Descriptor or Handle After Effective Lifetime | |||
| * BadSource: Open a file using fopen() | |||
| * Sinks: | |||
| * GoodSink: Close the file using fclose() | |||
| * BadSink : Do not close file | |||
| * Flow Variant: 01 Baseline | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #ifndef OMITBAD | |||
| void CWE775_Missing_Release_of_File_Descriptor_or_Handle__fopen_no_close_01_bad() | |||
| { | |||
| FILE * data; | |||
| data = NULL; | |||
| /* POTENTIAL FLAW: Open a file without closing it */ | |||
| data = fopen("BadSource_fopen.txt", "w+"); | |||
| /* FLAW: No attempt to close the file */ | |||
| ; /* empty statement needed for some flow variants */ | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* goodB2G() uses the BadSource with the GoodSink */ | |||
| static void goodB2G() | |||
| { | |||
| FILE * data; | |||
| data = NULL; | |||
| /* POTENTIAL FLAW: Open a file without closing it */ | |||
| data = fopen("BadSource_fopen.txt", "w+"); | |||
| /* FIX: If the file is still opened, close it */ | |||
| if (data != NULL) | |||
| { | |||
| fclose(data); | |||
| } | |||
| } | |||
| void CWE775_Missing_Release_of_File_Descriptor_or_Handle__fopen_no_close_01_good() | |||
| { | |||
| goodB2G(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| its own for testing or for building a binary to use in testing binary | |||
| analysis tools. It is not used when compiling all the testcases as one | |||
| application, which is how source code analysis tools are tested. */ | |||
| #ifdef INCLUDEMAIN | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| CWE775_Missing_Release_of_File_Descriptor_or_Handle__fopen_no_close_01_good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| CWE775_Missing_Release_of_File_Descriptor_or_Handle__fopen_no_close_01_bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,99 @@ | |||
| /* TEMPLATE GENERATED TESTCASE FILE | |||
| Filename: CWE775_Missing_Release_of_File_Descriptor_or_Handle__fopen_no_close_73a.cpp | |||
| Label Definition File: CWE775_Missing_Release_of_File_Descriptor_or_Handle__fopen_no_close.label.xml | |||
| Template File: source-sinks-73a.tmpl.cpp | |||
| */ | |||
| /* | |||
| * @description | |||
| * CWE: 775 Missing Release of File Descriptor or Handle After Effective Lifetime | |||
| * BadSource: Open a file using fopen() | |||
| * Sinks: | |||
| * GoodSink: Close the file using fclose() | |||
| * BadSink : Do not close file | |||
| * Flow Variant: 73 Data flow: data passed in a list from one function to another in different source files | |||
| * | |||
| * */ | |||
| #include "std_testcase.h" | |||
| #include <list> | |||
| using namespace std; | |||
| namespace CWE775_Missing_Release_of_File_Descriptor_or_Handle__fopen_no_close_73 | |||
| { | |||
| #ifndef OMITBAD | |||
| /* bad function declaration */ | |||
| void badSink(list<FILE *> dataList); | |||
| void bad() | |||
| { | |||
| FILE * data; | |||
| list<FILE *> dataList; | |||
| data = NULL; | |||
| /* POTENTIAL FLAW: Open a file without closing it */ | |||
| data = fopen("BadSource_fopen.txt", "w+"); | |||
| /* Put data in a list */ | |||
| dataList.push_back(data); | |||
| dataList.push_back(data); | |||
| dataList.push_back(data); | |||
| badSink(dataList); | |||
| } | |||
| #endif /* OMITBAD */ | |||
| #ifndef OMITGOOD | |||
| /* goodB2G uses the BadSource with the GoodSink */ | |||
| void goodB2GSink(list<FILE *> dataList); | |||
| static void goodB2G() | |||
| { | |||
| FILE * data; | |||
| list<FILE *> dataList; | |||
| data = NULL; | |||
| /* POTENTIAL FLAW: Open a file without closing it */ | |||
| data = fopen("BadSource_fopen.txt", "w+"); | |||
| dataList.push_back(data); | |||
| dataList.push_back(data); | |||
| dataList.push_back(data); | |||
| goodB2GSink(dataList); | |||
| } | |||
| void good() | |||
| { | |||
| goodB2G(); | |||
| } | |||
| #endif /* OMITGOOD */ | |||
| } /* close namespace */ | |||
| /* Below is the main(). It is only used when building this testcase on | |||
| its own for testing or for building a binary to use in testing binary | |||
| analysis tools. It is not used when compiling all the testcases as one | |||
| application, which is how source code analysis tools are tested. */ | |||
| #ifdef INCLUDEMAIN | |||
| using namespace CWE775_Missing_Release_of_File_Descriptor_or_Handle__fopen_no_close_73; /* so that we can use good and bad easily */ | |||
| int main(int argc, char * argv[]) | |||
| { | |||
| /* seed randomness */ | |||
| srand( (unsigned)time(NULL) ); | |||
| #ifndef OMITGOOD | |||
| printLine("Calling good()..."); | |||
| good(); | |||
| printLine("Finished good()"); | |||
| #endif /* OMITGOOD */ | |||
| #ifndef OMITBAD | |||
| printLine("Calling bad()..."); | |||
| bad(); | |||
| printLine("Finished bad()"); | |||
| #endif /* OMITBAD */ | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,211 @@ | |||
| #include <inttypes.h> // for PRId64 | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <wctype.h> | |||
| #include "std_testcase.h" | |||
| #ifndef _WIN32 | |||
| #include <wchar.h> | |||
| #endif | |||
| void printLine (const char * line) | |||
| { | |||
| if(line != NULL) | |||
| { | |||
| printf("%s\n", line); | |||
| } | |||
| } | |||
| void printWLine (const wchar_t * line) | |||
| { | |||
| if(line != NULL) | |||
| { | |||
| wprintf(L"%ls\n", line); | |||
| } | |||
| } | |||
| void printIntLine (int intNumber) | |||
| { | |||
| printf("%d\n", intNumber); | |||
| } | |||
| void printShortLine (short shortNumber) | |||
| { | |||
| printf("%hd\n", shortNumber); | |||
| } | |||
| void printFloatLine (float floatNumber) | |||
| { | |||
| printf("%f\n", floatNumber); | |||
| } | |||
| void printLongLine (long longNumber) | |||
| { | |||
| printf("%ld\n", longNumber); | |||
| } | |||
| void printLongLongLine (int64_t longLongIntNumber) | |||
| { | |||
| printf("%" PRId64 "\n", longLongIntNumber); | |||
| } | |||
| void printSizeTLine (size_t sizeTNumber) | |||
| { | |||
| printf("%zu\n", sizeTNumber); | |||
| } | |||
| void printHexCharLine (char charHex) | |||
| { | |||
| printf("%02x\n", charHex); | |||
| } | |||
| void printWcharLine(wchar_t wideChar) | |||
| { | |||
| /* ISO standard dictates wchar_t can be ref'd only with %ls, so we must make a | |||
| * string to print a wchar */ | |||
| wchar_t s[2]; | |||
| s[0] = wideChar; | |||
| s[1] = L'\0'; | |||
| printf("%ls\n", s); | |||
| } | |||
| void printUnsignedLine(unsigned unsignedNumber) | |||
| { | |||
| printf("%u\n", unsignedNumber); | |||
| } | |||
| void printHexUnsignedCharLine(unsigned char unsignedCharacter) | |||
| { | |||
| printf("%02x\n", unsignedCharacter); | |||
| } | |||
| void printDoubleLine(double doubleNumber) | |||
| { | |||
| printf("%g\n", doubleNumber); | |||
| } | |||
| void printStructLine (const twoIntsStruct * structTwoIntsStruct) | |||
| { | |||
| printf("%d -- %d\n", structTwoIntsStruct->intOne, structTwoIntsStruct->intTwo); | |||
| } | |||
| void printBytesLine(const unsigned char * bytes, size_t numBytes) | |||
| { | |||
| size_t i; | |||
| for (i = 0; i < numBytes; ++i) | |||
| { | |||
| printf("%02x", bytes[i]); | |||
| } | |||
| puts(""); /* output newline */ | |||
| } | |||
| /* Decode a string of hex characters into the bytes they represent. The second | |||
| * parameter specifies the length of the output buffer. The number of bytes | |||
| * actually written to the output buffer is returned. */ | |||
| size_t decodeHexChars(unsigned char * bytes, size_t numBytes, const char * hex) | |||
| { | |||
| size_t numWritten = 0; | |||
| /* We can't sscanf directly into the byte array since %02x expects a pointer to int, | |||
| * not a pointer to unsigned char. Also, since we expect an unbroken string of hex | |||
| * characters, we check for that before calling sscanf; otherwise we would get a | |||
| * framing error if there's whitespace in the input string. */ | |||
| while (numWritten < numBytes && isxdigit(hex[2 * numWritten]) && isxdigit(hex[2 * numWritten + 1])) | |||
| { | |||
| int byte; | |||
| sscanf(&hex[2 * numWritten], "%02x", &byte); | |||
| bytes[numWritten] = (unsigned char) byte; | |||
| ++numWritten; | |||
| } | |||
| return numWritten; | |||
| } | |||
| /* Decode a string of hex characters into the bytes they represent. The second | |||
| * parameter specifies the length of the output buffer. The number of bytes | |||
| * actually written to the output buffer is returned. */ | |||
| size_t decodeHexWChars(unsigned char * bytes, size_t numBytes, const wchar_t * hex) | |||
| { | |||
| size_t numWritten = 0; | |||
| /* We can't swscanf directly into the byte array since %02x expects a pointer to int, | |||
| * not a pointer to unsigned char. Also, since we expect an unbroken string of hex | |||
| * characters, we check for that before calling swscanf; otherwise we would get a | |||
| * framing error if there's whitespace in the input string. */ | |||
| while (numWritten < numBytes && iswxdigit(hex[2 * numWritten]) && iswxdigit(hex[2 * numWritten + 1])) | |||
| { | |||
| int byte; | |||
| swscanf(&hex[2 * numWritten], L"%02x", &byte); | |||
| bytes[numWritten] = (unsigned char) byte; | |||
| ++numWritten; | |||
| } | |||
| return numWritten; | |||
| } | |||
| /* The two functions always return 1 or 0, so a tool should be able to | |||
| identify that uses of these functions will always return these values */ | |||
| int globalReturnsTrue() | |||
| { | |||
| return 1; | |||
| } | |||
| int globalReturnsFalse() | |||
| { | |||
| return 0; | |||
| } | |||
| int globalReturnsTrueOrFalse() | |||
| { | |||
| return (rand() % 2); | |||
| } | |||
| /* The variables below are declared "const", so a tool should | |||
| be able to identify that reads of these will always return their | |||
| initialized values. */ | |||
| const int GLOBAL_CONST_TRUE = 1; /* true */ | |||
| const int GLOBAL_CONST_FALSE = 0; /* false */ | |||
| const int GLOBAL_CONST_FIVE = 5; | |||
| /* The variables below are not defined as "const", but are never | |||
| assigned any other value, so a tool should be able to identify that | |||
| reads of these will always return their initialized values. */ | |||
| int globalTrue = 1; /* true */ | |||
| int globalFalse = 0; /* false */ | |||
| int globalFive = 5; | |||
| /* define a bunch of these as empty functions so that if a test case forgets | |||
| to make their's statically scoped, we'll get a linker error */ | |||
| void good1() { } | |||
| void good2() { } | |||
| void good3() { } | |||
| void good4() { } | |||
| void good5() { } | |||
| void good6() { } | |||
| void good7() { } | |||
| void good8() { } | |||
| void good9() { } | |||
| /* shouldn't be used, but just in case */ | |||
| void bad1() { } | |||
| void bad2() { } | |||
| void bad3() { } | |||
| void bad4() { } | |||
| void bad5() { } | |||
| void bad6() { } | |||
| void bad7() { } | |||
| void bad8() { } | |||
| void bad9() { } | |||
| /* define global argc and argv */ | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| int globalArgc = 0; | |||
| char** globalArgv = NULL; | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,126 @@ | |||
| #ifndef _STD_TESTCASE_H | |||
| #define _STD_TESTCASE_H | |||
| /* This file exists in order to: | |||
| * 1) Include lots of standardized headers in one place | |||
| * 2) To avoid #include-ing things in the middle of your code | |||
| * #include-ing in the middle of a C/C++ file is apt to cause compiler errors | |||
| * 3) To get good #define's in place | |||
| * | |||
| * In reality you need a complex interaction of scripts of build processes to do | |||
| * this correctly (i.e., autoconf) | |||
| */ | |||
| #ifdef _WIN32 | |||
| /* Ensure the CRT does not disable the "insecure functions" | |||
| * Ensure not to generate warnings about ANSI C functions. | |||
| */ | |||
| #define _CRT_SECURE_NO_DEPRECATE 1 | |||
| #define _CRT_SECURE_NO_WARNING 1 | |||
| /* We do not use _malloca as it sometimes allocates memory on the heap and we | |||
| * do not want this to happen in test cases that expect stack-allocated memory | |||
| * Also, _alloca_s cannot be used as it is deprecated and has been replaced | |||
| * with _malloca */ | |||
| #define ALLOCA _alloca | |||
| /* disable warnings about use of POSIX names for functions like execl() | |||
| Visual Studio wants you to use the ISO C++ name, such as _execl() */ | |||
| #pragma warning(disable:4996) | |||
| #else | |||
| /* Linux/GNU wants this macro, otherwise stdint.h and limits.h are mostly useless */ | |||
| # define __STDC_LIMIT_MACROS 1 | |||
| #define ALLOCA alloca | |||
| #endif | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <stddef.h> | |||
| #include <time.h> | |||
| #include <limits.h> | |||
| #include <string.h> | |||
| #include <stdint.h> | |||
| #ifndef _WIN32 | |||
| /* SIZE_MAX, int64_t, etc. are in this file on Linux */ | |||
| # include <stdint.h> | |||
| #endif | |||
| #include <ctype.h> | |||
| #include <fcntl.h> | |||
| #include <sys/types.h> | |||
| #include <sys/stat.h> | |||
| #ifdef _WIN32 | |||
| #include <io.h> /* for open/close etc */ | |||
| #endif | |||
| #ifdef __cplusplus | |||
| #include <new> // for placement new | |||
| /* classes used in some test cases as a custom type */ | |||
| class TwoIntsClass | |||
| { | |||
| public: // Needed to access variables from label files | |||
| int intOne; | |||
| int intTwo; | |||
| }; | |||
| class OneIntClass | |||
| { | |||
| public: // Needed to access variables from label files | |||
| int intOne; | |||
| }; | |||
| #endif | |||
| #ifndef __cplusplus | |||
| /* Define true and false, which are included in C++, but not in C */ | |||
| #define true 1 | |||
| #define false 0 | |||
| #endif /* end ifndef __cplusplus */ | |||
| /* rand only returns 15 bits, so we xor 3 calls together to get the full result (13 bits overflow, but that is okay) */ | |||
| // shifting signed values might overflow and be undefined | |||
| #define URAND31() (((unsigned)rand()<<30) ^ ((unsigned)rand()<<15) ^ rand()) | |||
| // choose to produce a positive or a negative number. Note: conditional only evaluates one URAND31 | |||
| #define RAND32() ((int)(rand() & 1 ? URAND31() : -URAND31() - 1)) | |||
| /* rand only returns 15 bits, so we xor 5 calls together to get the full result (11 bits overflow, but that is okay) */ | |||
| // shifting signed values might overflow and be undefined | |||
| #define URAND63() (((uint64_t)rand()<<60) ^ ((uint64_t)rand()<<45) ^ ((uint64_t)rand()<<30) ^ ((uint64_t)rand()<<15) ^ rand()) | |||
| // choose to produce a positive or a negative number. Note: conditional only evaluates one URAND63 | |||
| #define RAND64() ((int64_t)(rand() & 1 ? URAND63() : -URAND63() - 1)) | |||
| /* struct used in some test cases as a custom type */ | |||
| typedef struct _twoIntsStruct | |||
| { | |||
| int intOne; | |||
| int intTwo; | |||
| } twoIntsStruct; | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| /* The variables below are declared "const", so a tool should | |||
| be able to identify that reads of these will always return their | |||
| initialized values. */ | |||
| extern const int GLOBAL_CONST_TRUE; /* true */ | |||
| extern const int GLOBAL_CONST_FALSE; /* false */ | |||
| extern const int GLOBAL_CONST_FIVE; /* 5 */ | |||
| /* The variables below are not defined as "const", but are never | |||
| assigned any other value, so a tool should be able to identify that | |||
| reads of these will always return their initialized values. */ | |||
| extern int globalTrue; /* true */ | |||
| extern int globalFalse; /* false */ | |||
| extern int globalFive; /* 5 */ | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #include "std_testcase_io.h" | |||
| #endif | |||
| @@ -0,0 +1,62 @@ | |||
| /* header file to define functions in io.c. Not named io.h | |||
| because that name is already taken by a system header on | |||
| Windows */ | |||
| #ifndef _STD_TESTCASE_IO_H | |||
| #define _STD_TESTCASE_IO_H | |||
| #include "std_testcase.h" /* needed for the twoint struct */ | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| void printLine(const char * line); | |||
| void printWLine(const wchar_t * line); | |||
| void printIntLine (int intNumber); | |||
| void printShortLine (short shortNumber); | |||
| void printFloatLine (float floatNumber); | |||
| void printLongLine(long longNumber); | |||
| void printLongLongLine(int64_t longLongIntNumber); | |||
| void printSizeTLine(size_t sizeTNumber); | |||
| void printHexCharLine(char charHex); | |||
| void printWcharLine(wchar_t wideChar); | |||
| void printUnsignedLine(unsigned unsignedNumber); | |||
| void printHexUnsignedCharLine(unsigned char unsignedCharacter); | |||
| void printDoubleLine(double doubleNumber); | |||
| void printStructLine(const twoIntsStruct * structTwoIntsStruct); | |||
| void printBytesLine(const unsigned char * bytes, size_t numBytes); | |||
| size_t decodeHexChars(unsigned char * bytes, size_t numBytes, const char * hex); | |||
| size_t decodeHexWChars(unsigned char * bytes, size_t numBytes, const wchar_t * hex); | |||
| int globalReturnsTrue(); | |||
| int globalReturnsFalse(); | |||
| int globalReturnsTrueOrFalse(); | |||
| /* Define some global variables that will get argc and argv */ | |||
| extern int globalArgc; | |||
| extern char** globalArgv; | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif | |||
| @@ -0,0 +1,212 @@ | |||
| #ifdef _WIN32 | |||
| /* windows.h needs to be the top-most header usually */ | |||
| # include <windows.h> | |||
| #endif | |||
| #include "std_testcase.h" | |||
| #ifdef _WIN32 | |||
| # include <process.h> | |||
| #else | |||
| # include <pthread.h> | |||
| #endif | |||
| #include "std_thread.h" | |||
| struct _stdThread { | |||
| #ifdef _WIN32 | |||
| uintptr_t handle; | |||
| #else | |||
| pthread_t handle; | |||
| #endif | |||
| stdThreadRoutine start; | |||
| void *args; | |||
| }; | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| #ifdef _WIN32 | |||
| static unsigned __stdcall internal_start(void *args) | |||
| #else | |||
| static void *internal_start(void *args) | |||
| #endif | |||
| { | |||
| stdThread thread = (stdThread)args; | |||
| thread->start(thread->args); | |||
| #ifdef _WIN32 | |||
| _endthreadex(0); | |||
| /* dead code, but return to avoid warnings */ | |||
| return 0; | |||
| #else | |||
| pthread_exit(NULL); | |||
| /* dead code, but return to avoid warnings */ | |||
| return NULL; | |||
| #endif | |||
| } | |||
| int stdThreadCreate(stdThreadRoutine start, void *args, stdThread *thread) | |||
| { | |||
| #ifdef _WIN32 | |||
| uintptr_t handle; | |||
| #else | |||
| pthread_t handle; | |||
| #endif | |||
| stdThread my_thread; | |||
| *thread = NULL; | |||
| my_thread = (stdThread)malloc(sizeof(*my_thread)); | |||
| if (my_thread == NULL) { | |||
| return 0; | |||
| } | |||
| my_thread->start = start; | |||
| my_thread->args = args; | |||
| #ifdef _WIN32 | |||
| handle = _beginthreadex(NULL, 0, internal_start, my_thread, 0, NULL); | |||
| if (handle == 0) { | |||
| free(my_thread); | |||
| return 0; | |||
| } | |||
| #else | |||
| if (0 != pthread_create(&handle, NULL, internal_start, my_thread)) { | |||
| free(my_thread); | |||
| return 0; | |||
| } | |||
| #endif | |||
| /* clearly, you cannot access _stdThread.handle from within the thread | |||
| * itself, because initialization of this field is not synchronized w.r.t. | |||
| * multiple threads | |||
| */ | |||
| my_thread->handle = handle; | |||
| *thread = my_thread; | |||
| return 1; | |||
| } | |||
| int stdThreadJoin(stdThread thread) | |||
| { | |||
| #ifdef _WIN32 | |||
| DWORD value; | |||
| value = WaitForSingleObject((HANDLE)thread->handle, INFINITE); | |||
| if (value != WAIT_OBJECT_0) return 0; | |||
| #else | |||
| void *dummy; | |||
| if (0 != pthread_join(thread->handle, &dummy)) return 0; | |||
| #endif | |||
| return 1; | |||
| } | |||
| int stdThreadDestroy(stdThread thread) | |||
| { | |||
| #ifdef _WIN32 | |||
| CloseHandle((HANDLE)thread->handle); | |||
| #else | |||
| #endif | |||
| free(thread); | |||
| return 1; | |||
| } | |||
| #ifdef __cplusplus | |||
| } /* end extern "C" */ | |||
| #endif | |||
| struct _stdThreadLock { | |||
| #ifdef _WIN32 | |||
| CRITICAL_SECTION CriticalSection; | |||
| #else | |||
| pthread_mutex_t mutex; | |||
| #endif | |||
| }; | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| int stdThreadLockCreate(stdThreadLock *lock) | |||
| { | |||
| stdThreadLock my_lock = NULL; | |||
| *lock = NULL; | |||
| my_lock = (stdThreadLock)malloc(sizeof(*my_lock)); | |||
| if (my_lock == NULL) return 0; | |||
| #ifdef _WIN32 | |||
| __try { | |||
| InitializeCriticalSection(&my_lock->CriticalSection); | |||
| } __except (GetExceptionCode() == STATUS_NO_MEMORY) { | |||
| free(my_lock); | |||
| return 0; | |||
| } | |||
| #else | |||
| if (0 != pthread_mutex_init(&my_lock->mutex, NULL)) { | |||
| free(lock); | |||
| return 0; | |||
| } | |||
| #endif | |||
| *lock = my_lock; | |||
| return 1; | |||
| } | |||
| void stdThreadLockAcquire(stdThreadLock lock) | |||
| { | |||
| /* pthread_mutex's and CRITICAL_SECTIONS differ | |||
| * | |||
| * CRITICAL_SECTION's are recursive, meaning a thread can acquire a | |||
| * CRITICAL_SECTION multiple times, so long as it then releases it | |||
| * the same number of times. | |||
| * | |||
| * pthread_mutex's seem to be undefined with regards to recursion, | |||
| * meaning that acquiring the same mutex twice leads to undefined | |||
| * behavior (it could deadlock, crash, act recursively, who knows) | |||
| * | |||
| * Therefore, we will define multiple acquisitions of a lock in a | |||
| * single thread as "undefined" behavior, thereby allowing us to | |||
| * ignore the platform compatibility issues here. | |||
| */ | |||
| #ifdef _WIN32 | |||
| /* may throw an exception in Windows 2000 but documentation says to let | |||
| * it terminate the process (i.e., don't handle it) | |||
| */ | |||
| EnterCriticalSection(&lock->CriticalSection); | |||
| #else | |||
| pthread_mutex_lock(&lock->mutex); | |||
| #endif | |||
| } | |||
| void stdThreadLockRelease(stdThreadLock lock) | |||
| { | |||
| /* see comments in stdThreadLockAcquire with regards to lock | |||
| * recursion */ | |||
| #ifdef _WIN32 | |||
| LeaveCriticalSection(&lock->CriticalSection); | |||
| #else | |||
| pthread_mutex_unlock(&lock->mutex); | |||
| #endif | |||
| } | |||
| void stdThreadLockDestroy(stdThreadLock lock)\ | |||
| { | |||
| #ifdef _WIN32 | |||
| DeleteCriticalSection(&lock->CriticalSection); | |||
| #else | |||
| pthread_mutex_destroy(&lock->mutex); | |||
| #endif | |||
| free(lock); | |||
| } | |||
| #ifdef __cplusplus | |||
| } /* end extern "C" */ | |||
| #endif | |||
| @@ -0,0 +1,27 @@ | |||
| #ifndef _STD_THREAD_H | |||
| #define _STD_THREAD_H | |||
| typedef struct _stdThread *stdThread; | |||
| typedef struct _stdThreadLock *stdThreadLock; | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| typedef void (*stdThreadRoutine)(void *args); | |||
| /* All of these return positive ('true') on success, zero ('false') on failure */ | |||
| int stdThreadCreate(stdThreadRoutine start, void *args, stdThread *thread); | |||
| int stdThreadJoin(stdThread thread); | |||
| int stdThreadDestroy(stdThread thread); | |||
| int stdThreadLockCreate(stdThreadLock *lock); | |||
| void stdThreadLockAcquire(stdThreadLock lock); | |||
| void stdThreadLockRelease(stdThreadLock lock); | |||
| void stdThreadLockDestroy(stdThreadLock lock); | |||
| #ifdef __cplusplus | |||
| }; | |||
| #endif | |||
| #endif | |||