| @@ -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 | |||||