allocators.cocci

text/plain

Filename: allocators.cocci
Type: text/plain
Part: 1
Message: Re: Fix mismatched deallocation functions
// Skip pointers that are also assigned from libc allocators (e.g. #ifdef FRONTEND)
@ palloc_skip exists @
type T;
T *ptr;
identifier libc_alloc =~ "^(malloc|calloc|realloc|strdup)$";
identifier dealloc =~ "^(free|pg_free)$";
position p;
@@
ptr = libc_alloc(...);
...
dealloc@p(ptr);

// palloc-family allocated memory must be freed with pfree, not free/pg_free.
// Handles: ptr = palloc(...);
@ exists @
type T;
T *ptr;
identifier alloc =~ "^p(strdup|nstrdup|alloc|alloc0|alloc_extended|sprintf)$";
identifier dealloc =~ "^(free|pg_free)$";
position p != palloc_skip.p;
@@
ptr = alloc(...);
... when any
- dealloc@p(ptr);
+ pfree(ptr);

// palloc-family with chained assignment: x = ptr = palloc(...);
@ exists @
type T;
T *ptr;
expression E;
identifier alloc =~ "^p(strdup|nstrdup|alloc|alloc0|alloc_extended|sprintf)$";
identifier dealloc =~ "^(free|pg_free)$";
position p != palloc_skip.p;
@@
E = ptr = alloc(...);
... when any
- dealloc@p(ptr);
+ pfree(ptr);

// palloc-family with typedef'd pointer: T ptr = palloc(...);
@ exists @
type T;
T ptr;
identifier alloc =~ "^p(strdup|nstrdup|alloc|alloc0|alloc_extended|sprintf)$";
identifier dealloc =~ "^(free|pg_free)$";
position p != palloc_skip.p;
@@
ptr = alloc(...);
... when any
- dealloc@p(ptr);
+ pfree(ptr);

// palloc-family with cast: ptr = (C *) palloc(...);
@ exists @
type T, C;
T *ptr;
identifier alloc =~ "^p(strdup|nstrdup|alloc|alloc0|alloc_extended|sprintf)$";
identifier dealloc =~ "^(free|pg_free)$";
position p != palloc_skip.p;
@@
ptr = (C *) alloc(...);
... when any
- dealloc@p(ptr);
+ pfree(ptr);

// palloc-family with declaration: T *ptr = palloc(...);
@ exists @
type T;
identifier ptr;
identifier alloc =~ "^p(strdup|nstrdup|alloc|alloc0|alloc_extended|sprintf)$";
identifier dealloc =~ "^(free|pg_free)$";
position p != palloc_skip.p;
@@
T *ptr = alloc(...);
... when any
- dealloc@p(ptr);
+ pfree(ptr);

// palloc-family with declaration and cast: T *ptr = (C *) palloc(...);
@ exists @
type T, C;
identifier ptr;
identifier alloc =~ "^p(strdup|nstrdup|alloc|alloc0|alloc_extended|sprintf)$";
identifier dealloc =~ "^(free|pg_free)$";
position p != palloc_skip.p;
@@
T *ptr = (C *) alloc(...);
... when any
- dealloc@p(ptr);
+ pfree(ptr);

// Skip pointers that are also assigned from libc allocators for pg_malloc rules
@ pgmalloc_skip exists @
type T;
T *ptr;
identifier libc_alloc =~ "^(malloc|calloc|realloc|strdup)$";
identifier dealloc =~ "^(free|pfree)$";
position p;
@@
ptr = libc_alloc(...);
...
dealloc@p(ptr);

// pg_malloc-family allocated memory must be freed with pg_free, not free/pfree.
// Handles: ptr = pg_malloc(...);
@ exists @
type T;
T *ptr;
identifier alloc =~ "^pg_(strdup|nstrdup|malloc|malloc0|malloc_array|malloc0_array|malloc_object|malloc0_object|malloc_extended|sprintf)$";
identifier dealloc =~ "^(free|pfree)$";
position p != pgmalloc_skip.p;
@@
ptr = alloc(...);
... when any
- dealloc@p(ptr);
+ pg_free(ptr);

// pg_malloc-family with chained assignment: x = ptr = pg_malloc(...);
@ exists @
type T;
T *ptr;
expression E;
identifier alloc =~ "^pg_(strdup|nstrdup|malloc|malloc0|malloc_array|malloc0_array|malloc_object|malloc0_object|malloc_extended|sprintf)$";
identifier dealloc =~ "^(free|pfree)$";
position p != pgmalloc_skip.p;
@@
E = ptr = alloc(...);
... when any
- dealloc@p(ptr);
+ pg_free(ptr);

// pg_malloc-family with typedef'd pointer: T ptr = pg_malloc(...);
@ exists @
type T;
T ptr;
identifier alloc =~ "^pg_(strdup|nstrdup|malloc|malloc0|malloc_array|malloc0_array|malloc_object|malloc0_object|malloc_extended|sprintf)$";
identifier dealloc =~ "^(free|pfree)$";
position p != pgmalloc_skip.p;
@@
ptr = alloc(...);
... when any
- dealloc@p(ptr);
+ pg_free(ptr);

// pg_malloc-family with cast: ptr = (C *) pg_malloc(...);
@ exists @
type T, C;
T *ptr;
identifier alloc =~ "^pg_(strdup|nstrdup|malloc|malloc0|malloc_array|malloc0_array|malloc_object|malloc0_object|malloc_extended|sprintf)$";
identifier dealloc =~ "^(free|pfree)$";
position p != pgmalloc_skip.p;
@@
ptr = (C *) alloc(...);
... when any
- dealloc@p(ptr);
+ pg_free(ptr);

// pg_malloc-family with declaration: T *ptr = pg_malloc(...);
@ exists @
type T;
identifier ptr;
identifier alloc =~ "^pg_(strdup|nstrdup|malloc|malloc0|malloc_array|malloc0_array|malloc_object|malloc0_object|malloc_extended|sprintf)$";
identifier dealloc =~ "^(free|pfree)$";
position p != pgmalloc_skip.p;
@@
T *ptr = alloc(...);
... when any
- dealloc@p(ptr);
+ pg_free(ptr);

// pg_malloc-family with declaration and cast: T *ptr = (C *) pg_malloc(...);
@ exists @
type T, C;
identifier ptr;
identifier alloc =~ "^pg_(strdup|nstrdup|malloc|malloc0|malloc_array|malloc0_array|malloc_object|malloc0_object|malloc_extended|sprintf)$";
identifier dealloc =~ "^(free|pfree)$";
position p != pgmalloc_skip.p;
@@
T *ptr = (C *) alloc(...);
... when any
- dealloc@p(ptr);
+ pg_free(ptr);

// pg_malloc-family: free before re-allocation of same pointer
@ exists @
type T;
T *ptr;
identifier alloc =~ "^pg_(strdup|nstrdup|malloc|malloc0|malloc_array|malloc0_array|malloc_object|malloc0_object|malloc_extended|sprintf)$";
identifier dealloc =~ "^(free|pfree)$";
position p != pgmalloc_skip.p;
@@
- dealloc@p(ptr);
+ pg_free(ptr);
... when any
ptr = alloc(...);

// palloc-family: free before re-allocation of same pointer
@ exists @
type T;
T *ptr;
identifier alloc =~ "^p(strdup|nstrdup|alloc|alloc0|alloc_extended|sprintf)$";
identifier dealloc =~ "^(free|pg_free)$";
position p != palloc_skip.p;
@@
- dealloc@p(ptr);
+ pfree(ptr);
... when any
ptr = alloc(...);