I have code like below, and I use cppcheck to do static analysis.
I found that it cannot report null pointer for data.
#define MY_FREE(p) if(p) {free(p);(p)=NULL;}
for(i=0; i<10; i++)
{
ret = list_insert(list, data);
if (1 != ret)
{
MY_FREE(data);
}
other_process(data->item);
}
But if I expand macro "MY_FREE" directly, it worked.
for(i=0; i<10; i++)
{
ret = list_insert(list, data);
if (1 != ret)
{
if(data) {free(data);(data)=NULL;};
}
other_process(data->item);
}
Is there any configuration can resolve it?
I am a Cppcheck developer. What is the exact code your testing? Cppcheck warns about this code:
#define MY_FREE(p) if(p) {free(p);(p)=NULL;}
void f() {
struct Data *data;
for(i=0; i<10; i++)
{
ret = list_insert(list, data);
if (1 != ret)
{
MY_FREE(data);
}
other_process(data->item);
}
}
Reported warning:
[1.c:12]: (warning) Possible null pointer dereference: data
In your code.. it sounds like that we have false negatives for some reason.
Related
Program execute result:
zsh: segmentation fault ./test.out
Coverity analyse output:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// uaf
void test_1(void *p) {
free(p);
CID 358676: Read from pointer after free (USE_AFTER_FREE) [select issue]
printf("%x\n", *((int *)p));
}
// loop write
void test_2(int total, char *p) {
char a[100];
for(int i=0;i < total; i++) {
a[i] = *(p + i);
}
}
typedef struct {
char name[100];
}Person;
// uint8 *p
void test_3(Person *p) {
unsigned char *ptr = (unsigned char *)p;
for(int i=0; i < sizeof(Person) + 100; i++) {
*ptr = 'a';
}
free(p);
CID 358686: Read from pointer after free (USE_AFTER_FREE) [select issue]
printf("%x\n", *((int *)p));
}
// state machine
enum {
S_START,
S_IDLE,
S_BUSY,
S_UNKNOWN
};
int gState = S_START;
void *gPtr = NULL;
void handle_start() {
int size;
printf("input malloc size:\n");
CID 358721: Unchecked return value from library (CHECKED_RETURN) [select issue]
scanf("%d", &size);
CID 134591: Untrusted allocation size (TAINTED_SCALAR) [select issue]
gPtr = malloc(size);
gState = S_BUSY;
printf("S_START -> S_BUSY\n");
}
void handle_busy() {
char buff[100];
printf("input string:\n");
CID 358720: Unchecked return value from library (CHECKED_RETURN) [select issue]
CID 358719: Calling risky function (DC.STREAM_BUFFER) [select issue]
scanf("%s", buff);
strcpy(gPtr, buff);
puts(gPtr);
gState = S_IDLE;
printf("S_BUSY -> S_IDLE\n");
}
void handle_idle(void *p) {
char cmd;
printf("continue or exit(C/E)?");
CID 358718: Unchecked return value from library (CHECKED_RETURN) [select issue]
scanf("%c", &cmd);
if (cmd == 'c' || cmd == 'C') {
gState = S_BUSY;
printf("S_IDLE -> S_BUSY\n");
} else {
free(p);
printf("S_IDLE -> S_START\n");
printf("exit\n");
exit(0);
}
}
void process(void *p) {
switch (gState) {
case S_START:
handle_idle(p);
handle_start();
break;
case S_BUSY:
handle_busy();
break;
case S_IDLE:
handle_idle(p);
break;
default:
break;
}
}
void test_4(void *p) {
while (1)
{
process(p);
}
}
void test_5(void *pData) {
int kind = 0;
void *ptr = NULL;
printf("input kind:\n");
CID 358724: Unchecked return value from library (CHECKED_RETURN) [select issue]
scanf("%d", &kind);
1. Switch case default.
switch (kind) {
case 1:
ptr = malloc(100);
break;
case 2:
ptr = malloc(200);
break;
default:
2. alloc_fn: Storage is returned from allocation function malloc.
3. var_assign: Assigning: ptr = storage returned from malloc(64UL).
ptr = malloc(64);
4. Breaking from switch.
break;
}
5. Switch case default.
switch(kind) {
case 1:
memcpy(ptr, pData, 1000);
break;
case 2:
memcpy(ptr, pData, 2000);
break;
default:
6. noescape: Resource ptr is not freed or pointed-to in memcpy.
memcpy(ptr, pData, 64);
7. Breaking from switch.
break;
}
8. noescape: Resource (char *)ptr is not freed or pointed-to in printf.
printf("result: %s\n", (char *)ptr);
CID 358723 (#1-3 of 3): Resource leak (RESOURCE_LEAK)
9. leaked_storage: Variable ptr going out of scope leaks the storage it points to.
}
void test_6_sub(void *p) {
if (p == NULL) {
return;
}
free(p);
}
void test_6(void *p) {
test_6_sub(p);
}
int *n() {
return 0;
}
int main(void)
{
// int a;
// printf("input copy length: ");
// scanf("%d",&a);
// printf("copy %d bytes\n",a);
// void *p = malloc(100);
// memcpy(p, (char *)&a, a);
// printf("%s", (char *)&a);
gPtr = malloc(100);
char *p = gPtr;
free(gPtr);
char *name = "adfsasdfasdfasdfasdfasdf";
// test_4(p);
// test_6(p);
return *(n());
}
After analyse by coverity, I just do not get the vulnerability infomation what I want.
According to the introduction of Coverity
should be find the free of Null pointer vulnerability.
should be find the dead code
should be find the function call chains
But I got nothing
Is something wrong?
I got this test result at https://scan.coverity.com
Is the online service has some restrict?
The answer to the question in the title, "Does Coverity support Interprocedural-Analysis", is yes. The Coverity analysis indeed examines how functions call one another in an attempt to discover inconsistencies.
However, there are limitations to the precision of that interprocedural analysis. In particular, although it tries to keep track of relationships involving (at least) parameters, return values, and things pointed to by those, in most cases it cannot track relationships between global variables across function calls. (The reason for that is there are simply too many such variables and too many potential relationships, so trying to track them all would result in the analysis never terminating.)
In your example, there is an intended invariant that gPtr is a valid pointer if and only if gState == S_IDLE. Consequently, the handle_idle() function can only be called when gState == S_IDLE. The process() function violates that requirement by calling handle_idle() while gState == S_START, which (based on the clarification in the comments) is the bug you want to find. That deduction is unfortunately beyond the capabilities of the tool, so it does not report it.
I'm trying to translate a, b, c, d = iterable to Python's C/API.
I'm looking for a function similar to PyArg_ParseTuple, just for iterables.
In other words, something in the area of PyIter_Parse or PyObject_ParseIterable, if such functions would have existed.
Any tips how to implement it?
No, there is no helper function that can do this for you.
You'd have to use PyIter_Next() up to max times to retrieve values, raise an exception when you can't get at least min values, and then just build a tuple from that.
Something like (untested, largely pilfered from PySequence_Tuple()):
int
PyIter_LimitedTuple(PyObject *v, Py_ssize_t min, Py_ssize_t max)
{
PyObject *it; /* iter(v) */
PyObject *result = NULL;
Py_ssize_t j;
it = PyObject_GetIter(v);
if (it == NULL)
return NULL;
/* allocate space. */
result = PyTuple_New(max);
if (result == NULL)
goto Fail;
/* Fill the tuple. */
for (j = 0; ; ++j) {
PyObject *item = PyIter_Next(it);
if (item == NULL) {
if (PyErr_Occurred())
goto Fail;
break;
}
if (j > max) {
PyErr_Format(PyExc_ValueError,
"too many values to unpack");
goto Fail;
}
PyTuple_SET_ITEM(result, j, item);
}
if (j < min) {
PyErr_Format(PyExc_ValueError,
"need more than %d value to unpack",
j);
goto Fail;
}
/* Cut tuple back if fewer than max items were available. */
if (j < max &&
_PyTuple_Resize(&result, j) != 0)
goto Fail;
Py_DECREF(it);
return result;
Fail:
Py_XDECREF(result);
Py_DECREF(it);
return NULL;
}
then pass the resulting tuple to PyArg_UnpackTuple().
Below this program to retrieve the list of adapters and print it on the screen :
#include <stdio.h>
#include <pcap.h>
int main()
{
pcap_if_t *alldevs;
pcap_if_t *d;
int i=0;
char errbuf[PCAP_ERRBUF_SIZE];
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
{
fprintf(stderr,"Error in pcap_findalldevs_ex: %s/n", errbuf);
exit(1);
}
for(d= alldevs; d != NULL; d= d->next)
{
printf("%d. %s", ++i, d->name);
if (d->description)
printf(" (%s)/n", d->description);
else
printf(" (No description available)/n");
}
if (i == 0)
{
printf("/nNo interfaces found! Make sure WinPcap is installed./n");
return 0;
}
pcap_freealldevs(alldevs);
}
It is compile But Give an Error :
Every body have These Errors, while using pcap.h, go to bellow link and download pcap, after it Install it :
http://www.winpcap.org/install/default.htm
I'm currently working on a string tokenizer in C++ and am getting a strange result.
char *mystrtok(char *str, const char *delim)
{
char * LeftOver;
bool lastToken;
int i=0;
if(str != NULL)
{
LeftOver = str;
lastToken = false;
}else
{
str = LeftOver;
}
for(i = 0; str[i] != '\0'; i++)
{
for(int j=0; delim[j] != '\0'; j++)
{
//If I take out this line then it returns weird characters
cout << "\tstr[" << i <<" ]" << "=" << str[i] << endl;
if(LeftOver[i] == delim[j])
{
str[i] = '\0';
LeftOver = str + i+1;
return str;
}
}
}
if(LeftOver[i] == '\0' && !lastToken)
{
lastToken = true;
return str;
}
return NULL;
}
What's really weird is that if I take out the cout then it returns weird characters
Any idea what could be causing this?
Here's a sample output
//passed
"ls -l -a | wc -c >> myfile"
returned: ls
▒M.▒
I saw several problems with this code, first
str = LeftOver;
At this line, LeftOver has not been initialized at all. But you use it to initialize str. You want to make LeftOver static?
Second, your test for LastToken,
if(LeftOver[i] == '\0' && !lastToken)
It will aways true for !lastToken since before this line it is always false, you want to make it static too?
For example,in Windows,if I want to make the error message of gethostbyname meaningful,I would need to manually map the error code to message, as follows,
#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
int
main(void)
{
struct hostent *host;
WSAData wsaData;
int errcode;
if (WSAStartup(MAKEWORD(2, 2), &wsaData)) {
perror("WSAStartup failed");
exit(-1);
}
host = gethostbyname("www.google.com");
if (host != NULL) {
printf("the offical name of the host is: %s\n", host->h_name);
} else {
errcode = WSAGetLastError();
printf("the error code is %d\n", errcode);
if (errcode == WSAENETDOWN)
perror("network down");
else if (errcode == WSANOTINITIALISED)
perror("call WSAStartup before");
else if ...
perror("gethostbyname failed");
return -1;
}
return 0;
}
Is there easy way to do this?
thanks.
I think you codes is in the easy way already, check the error code and return the error message. If you just want to make your codes more elegant, you could use an array of custom struct like below.
struct ErrorInfo
{
int Code;
const char* Message;
};
ErrorInfo* errorMap =
{
{ WSAENETDOWN, "network down" },
{ WSANOTINITIALISED, "call WSAStartup before" },
};
const char* GetErrorMessage(int errorCode)
{
for(int i=0; i<sizeof(errorMap)/sizeof(ErrorInfo)); i++)
{
if(errorMap[i].Code == errorCode)
return errorMap[i].Message;
}
return "";
}