Add support for cppcheck 2.17.0
cppcheck 2.17.0 adds checks that a NULL pointer returned from malloc() and calloc() is not used. We do this quite a lot. I've addressed this by adding functions g_malloc_nofail() and g_calloc_nofail() which either allocate memory or abort. functions are now called in places where we are not making these checks. Many of these checks are in test programs or example programs. I've modified the list16 module to handle out-of-memory conditions.
This commit is contained in:
+59
-40
@@ -70,27 +70,64 @@ list16_deinit(struct list16 *self)
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void
|
||||
list16_add_item(struct list16 *self, tui16 item)
|
||||
/**
|
||||
* Makes the data array larger
|
||||
*
|
||||
* @param self The list
|
||||
* @return 1 for success, 0 for failure
|
||||
*
|
||||
* On failure, the data array is unchanged
|
||||
*/
|
||||
static int
|
||||
expand_array(struct list16 *self)
|
||||
{
|
||||
tui16 *p;
|
||||
int i;
|
||||
|
||||
if (self->count >= self->max_count)
|
||||
int new_max_count = self->max_count + 4;
|
||||
if (self->items == self->mitems)
|
||||
{
|
||||
i = self->max_count;
|
||||
self->max_count += 4;
|
||||
p = (tui16 *)g_malloc(sizeof(tui16) * self->max_count, 1);
|
||||
g_memcpy(p, self->items, sizeof(tui16) * i);
|
||||
if (self->items != self->mitems)
|
||||
/* Previous allocation is static. Make a new dynamic allocation */
|
||||
p = (tui16 *)malloc(sizeof(tui16) * new_max_count);
|
||||
if (p == NULL)
|
||||
{
|
||||
g_free(self->items);
|
||||
return 0;
|
||||
}
|
||||
self->items = p;
|
||||
g_memcpy(p, self->items, sizeof(tui16) * self->max_count);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Try to reallocate the existing array */
|
||||
p = (tui16 *)realloc(self->items, sizeof(tui16) * new_max_count);
|
||||
if (p == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear the new elements */
|
||||
for (i = self->max_count; i < new_max_count; ++i)
|
||||
{
|
||||
p[i] = 0;
|
||||
}
|
||||
|
||||
self->max_count = new_max_count;
|
||||
self->items = p;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
list16_add_item(struct list16 *self, tui16 item)
|
||||
{
|
||||
if (self->count >= self->max_count && !expand_array(self))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
self->items[self->count] = item;
|
||||
self->count++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -153,40 +190,22 @@ list16_remove_item(struct list16 *self, int index)
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void
|
||||
int
|
||||
list16_insert_item(struct list16 *self, int index, tui16 item)
|
||||
{
|
||||
tui16 *p;
|
||||
int i;
|
||||
|
||||
if (index == self->count)
|
||||
/* Make sure there's at least one free element in the array */
|
||||
if (self->count >= self->max_count && !expand_array(self))
|
||||
{
|
||||
list16_add_item(self, item);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (index >= 0 && index < self->count)
|
||||
if (index < self->count)
|
||||
{
|
||||
self->count++;
|
||||
|
||||
if (self->count > self->max_count)
|
||||
{
|
||||
i = self->max_count;
|
||||
self->max_count += 4;
|
||||
p = (tui16 *)g_malloc(sizeof(tui16) * self->max_count, 1);
|
||||
g_memcpy(p, self->items, sizeof(tui16) * i);
|
||||
if (self->items != self->mitems)
|
||||
{
|
||||
g_free(self->items);
|
||||
}
|
||||
self->items = p;
|
||||
}
|
||||
|
||||
for (i = (self->count - 2); i >= index; i--)
|
||||
{
|
||||
self->items[i + 1] = self->items[i];
|
||||
}
|
||||
|
||||
self->items[index] = item;
|
||||
memmove(&self->items[index + 1], &self->items[index],
|
||||
(self->count - index) * sizeof(tui16));
|
||||
}
|
||||
|
||||
self->items[index] = item;
|
||||
self->count++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
+4
-2
@@ -40,7 +40,8 @@ void
|
||||
list16_init(struct list16 *self);
|
||||
void
|
||||
list16_deinit(struct list16 *self);
|
||||
void
|
||||
/* Returns != 0 if item added successfully */
|
||||
int
|
||||
list16_add_item(struct list16 *self, tui16 item);
|
||||
tui16
|
||||
list16_get_item(struct list16 *self, int index);
|
||||
@@ -50,7 +51,8 @@ int
|
||||
list16_index_of(struct list16 *self, tui16 item);
|
||||
void
|
||||
list16_remove_item(struct list16 *self, int index);
|
||||
void
|
||||
/* Returns != 0 if item added successfully */
|
||||
int
|
||||
list16_insert_item(struct list16 *self, int index, tui16 item);
|
||||
|
||||
#endif
|
||||
|
||||
+57
-1
@@ -138,6 +138,9 @@ union sock_info
|
||||
#endif
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
static oom_type g_out_of_memory_handler;
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
g_rm_temp_dir(void)
|
||||
@@ -3971,7 +3974,7 @@ g_save_to_bmp(const char *filename, char *data, int stride_bytes,
|
||||
data -= stride_bytes;
|
||||
if ((depth == 24) && (bits_per_pixel == 32))
|
||||
{
|
||||
line = (char *) malloc(file_stride_bytes);
|
||||
line = (char *) g_malloc_nofail(file_stride_bytes);
|
||||
memset(line, 0, file_stride_bytes);
|
||||
for (index = 0; index < height; index++)
|
||||
{
|
||||
@@ -4276,3 +4279,56 @@ g_qsort(void *base, size_t nitems, size_t size,
|
||||
{
|
||||
qsort(base, nitems, size, compar);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
oom_type
|
||||
g_set_out_of_memory_handler(oom_type new_handler)
|
||||
{
|
||||
oom_type old_handler = g_out_of_memory_handler;
|
||||
g_out_of_memory_handler = new_handler;
|
||||
return old_handler;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
static void
|
||||
out_of_memory(void)
|
||||
{
|
||||
if (g_out_of_memory_handler != NULL)
|
||||
{
|
||||
g_out_of_memory_handler();
|
||||
_exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void *
|
||||
g_malloc_nofail(size_t size)
|
||||
{
|
||||
void *res = malloc(size);
|
||||
if (res == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ALWAYS, "g_malloc_nofail() can't allocate %zu bytes",
|
||||
size);
|
||||
out_of_memory();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void *
|
||||
g_calloc_nofail(size_t nmemb, size_t size)
|
||||
{
|
||||
void *res = calloc(nmemb, size);
|
||||
if (res == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ALWAYS,
|
||||
"g_calloc_nofail() can't allocate %zu * %zu bytes",
|
||||
nmemb, size);
|
||||
out_of_memory();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
+49
-3
@@ -38,6 +38,9 @@ struct proc_exit_status
|
||||
|
||||
struct list;
|
||||
|
||||
/** Out-of-memory handler type */
|
||||
typedef void (*oom_type)(void);
|
||||
|
||||
#define g_tcp_can_recv g_sck_can_recv
|
||||
#define g_tcp_can_send g_sck_can_send
|
||||
#define g_tcp_recv g_sck_recv
|
||||
@@ -429,14 +432,57 @@ void
|
||||
g_qsort(void *base, size_t nitems, size_t size,
|
||||
int (*compar)(const void *, const void *));
|
||||
|
||||
/** Set the out-of-memory handler
|
||||
* @param new_handler Function to call if a memory allocation fails
|
||||
* @result old handler or NULL if none.
|
||||
*
|
||||
* After calling an out-of-memory handler, the program exits
|
||||
* If no out-of-memory handler is set, the program aborts
|
||||
*
|
||||
* Only use this function if there is urgent cleaning-up that must be done
|
||||
* before the program exits.
|
||||
*/
|
||||
oom_type
|
||||
g_set_out_of_memory_handler(oom_type new_handler);
|
||||
|
||||
/** Allocate memory with error-checking
|
||||
*
|
||||
* @param size Size of memory to allocate
|
||||
* @return Allocated memory
|
||||
*
|
||||
* If memory cannot be allocated, the out-of-memory handler is called and
|
||||
* the program exits
|
||||
*
|
||||
* Only use this function if you are unable to handle an out-of-memory
|
||||
* condition.
|
||||
*/
|
||||
void *
|
||||
g_malloc_nofail(size_t size);
|
||||
|
||||
/** Allocate memory with error-checking
|
||||
*
|
||||
* @param Number of elementst to allocate
|
||||
* @param size Size of each element
|
||||
* @return Allocated memory
|
||||
*
|
||||
* If memory cannot be allocated, the out-of-memory handler is called and
|
||||
* the program exits
|
||||
*
|
||||
* Only use this function if you are unable to handle an out-of-memory
|
||||
* condition.
|
||||
*/
|
||||
void *
|
||||
g_calloc_nofail(size_t nmemb, size_t size);
|
||||
|
||||
/* glib-style wrappers */
|
||||
#define g_new(struct_type, n_structs) \
|
||||
(struct_type *) malloc(sizeof(struct_type) * (n_structs))
|
||||
(struct_type *) g_malloc_nofail(sizeof(struct_type) * (n_structs))
|
||||
#define g_new0(struct_type, n_structs) \
|
||||
(struct_type *) calloc((n_structs), sizeof(struct_type))
|
||||
(struct_type *) g_calloc_nofail((n_structs), sizeof(struct_type))
|
||||
|
||||
/* remove these when no longer used */
|
||||
#define g_malloc(_size, _zero) (_zero ? calloc(1, _size) : malloc(_size))
|
||||
#define g_malloc(_size, _zero) \
|
||||
(_zero ? g_calloc_nofail(1, _size) : g_malloc_nofail(_size))
|
||||
#define g_free free
|
||||
#define g_memset memset
|
||||
#define g_memcpy memcpy
|
||||
|
||||
Reference in New Issue
Block a user