Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions scripts/coccinelle/api/alloc_cast.cocci
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Coccinelle script to remove redundant casts from memory allocation functions.
// In C, void * is implicitly convertible to any pointer type, so casting the return value of malloc/calloc/realloc/memalign is redundant.

virtual patch
virtual context
virtual report

// [Pattern Matcher] Find explicit casts on memory allocation functions
@r1@
type T;
position p;
@@

(T *)
\(malloc@p\|calloc@p\|realloc@p\|memalign@p\)(...)

// [Filter] Ignore C++ files where void* cast is mandatory
@script:python@
p << r1.p;
@@

if p[0].file.endswith(('.cpp', '.cc', '.cxx', '.hpp', '.hh', '.C', '.H')):
cocci.include_match(False)

// [Patch Mode] Action: Remove redundant cast from memory allocation functions
@depends on patch@
type T;
position r1.p;
@@

- (T *)
\(malloc@p\|calloc@p\|realloc@p\|memalign@p\)(...)

// [Report Mode] Output Formatter: Print warning to console
@script:python depends on report@
p << r1.p;
t << r1.T;
@@

msg = "WARNING: casting value returned by memory allocation function to (%s *) is useless in C." % (t)
coccilib.report.print_report(p[0], msg)
154 changes: 154 additions & 0 deletions scripts/coccinelle/api/strdup.cocci
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
// Coccinelle script to use strdup() instead of manual memory allocation and string copy.
// strdup(src) is equivalent to malloc(strlen(src) + 1) followed by strcpy/memcpy/strlcpy.

virtual patch
virtual context
virtual report

// [Filter] Exclude strdup and strndup implementation functions
@ignore@
identifier fn = {strdup, strndup};
position p;
@@

fn(...) {
...
(
malloc@p(...)
|
calloc@p(...)
)
...
}

// [Patch Mode] Action: Replace manual allocation and copy (without length variable) with strdup()
@depends on patch@
expression from, to;
expression E1, E2;
statement S;
position p != ignore.p;
@@

(
- to = malloc@p(strlen(from) + 1);
+ to = strdup(from);
|
- to = calloc@p(1, strlen(from) + 1);
+ to = strdup(from);
|
- to = calloc@p(strlen(from) + 1, 1);
+ to = strdup(from);
)
... when != \(from = E1 \| to = E1 \)
if (to == NULL || ...) S
... when != \(from = E2 \| to = E2 \)
(
- strcpy(to, from);
|
- strlcpy(to, from, strlen(from) + 1);
|
- memcpy(to, from, strlen(from) + 1);
)

// [Patch Mode] Action: Replace manual allocation and copy (with length variable) with strdup()
@depends on patch@
expression x, from, to;
expression E1, E2, E3;
statement S;
position p != ignore.p;
@@

- x = strlen(from) + 1;
... when != \( x = E1 \| from = E1 \)
(
- to = malloc@p(x);
+ to = strdup(from);
|
- to = calloc@p(1, x);
+ to = strdup(from);
|
- to = calloc@p(x, 1);
+ to = strdup(from);
)
... when != \(x = E2 \| from = E2 \| to = E2 \)
if (to == NULL || ...) S
... when != \(x = E3 \| from = E3 \| to = E3 \)
(
- memcpy(to, from, x);
|
- strlcpy(to, from, x);
|
- strcpy(to, from);
)

// [Context/Report Mode] Pattern Matcher: Find manual allocation and copy without length variable
@r1 depends on !patch exists@
expression from, to;
expression E1, E2;
statement S;
position p1 != ignore.p, p2;
@@

(
* to = malloc@p1(strlen(from) + 1);
|
* to = calloc@p1(1, strlen(from) + 1);
|
* to = calloc@p1(strlen(from) + 1, 1);
)
... when != \(from = E1 \| to = E1 \)
if (to == NULL || ...) S
... when != \(from = E2 \| to = E2 \)
(
* strcpy@p2(to, from);
|
* strlcpy@p2(to, from, strlen(from) + 1);
|
* memcpy@p2(to, from, strlen(from) + 1);
)

// [Context/Report Mode] Pattern Matcher: Find manual allocation and copy with length variable
@r2 depends on !patch exists@
expression x, from, to;
expression E1, E2, E3;
statement S;
position p1 != ignore.p, p2;
@@

* x = strlen(from) + 1;
... when != \( x = E1 \| from = E1 \)
(
* to = malloc@p1(x);
|
* to = calloc@p1(1, x);
|
* to = calloc@p1(x, 1);
)
... when != \(x = E2 \| from = E2 \| to = E2 \)
if (to == NULL || ...) S
... when != \(x = E3 \| from = E3 \| to = E3 \)
(
* memcpy@p2(to, from, x);
|
* strlcpy@p2(to, from, x);
|
* strcpy@p2(to, from);
)

// [Report Mode] Output Formatter: Print warning for r1 to console
@script:python depends on report@
p1 << r1.p1;
p2 << r1.p2;
@@

msg = "WARNING opportunity for strdup (copy on line %s)" % (p2[0].line)
coccilib.report.print_report(p1[0], msg)

// [Report Mode] Output Formatter: Print warning for r2 to console
@script:python depends on report@
p1 << r2.p1;
p2 << r2.p2;
@@

msg = "WARNING opportunity for strdup (copy on line %s)" % (p2[0].line)
coccilib.report.print_report(p1[0], msg)
40 changes: 40 additions & 0 deletions scripts/coccinelle/free/ifnullfree.cocci
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Coccinelle script to remove redundant NULL checks before free().
// free(NULL) is safe, so "if (x) free(x);" can be simplified to "free(x);".

virtual patch
virtual context
virtual report

// [Context/Patch Mode] Pattern Matcher: Find redundant NULL checks
@r depends on context || patch@
expression x;
position p;
@@

* if (x)@p
free(x);

// [Patch Mode] Action: Remove the redundant 'if' check
@depends on patch && r@
expression x;
@@

- if (x)
free(x);

// [Report Mode] Pattern Matcher: Find redundant NULL checks
@r2 depends on report@
expression x;
position p;
@@

if (x)@p
free(x);

// [Report Mode] Output Formatter: Print warning to console
@script:python depends on report@
p << r2.p;
@@

msg = "WARNING: redundant NULL check before free"
coccilib.report.print_report(p[0], msg)
63 changes: 63 additions & 0 deletions scripts/coccinelle/misc/countof.cocci
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Coccinelle script to use countof macro instead of opencoded division.
// Replace division of sizeof array by sizeof element with countof(E).

virtual patch
virtual context
virtual report

// [Filter] Include LK compiler header
@i@
@@

#include <lk/compiler.h>

// [Context Mode] Pattern Matcher: Find division of sizeof array by sizeof element
@depends on context@
type T;
T[] E;
@@
(
* (sizeof(E)/sizeof(*E))
|
* (sizeof(E)/sizeof(E[...]))
|
* (sizeof(E)/sizeof(T))
)

// [Patch Mode] Action: Replace opencoded array size division with countof(E)
@depends on patch@
type T;
T[] E;
@@
(
- (sizeof(E)/sizeof(*E))
+ countof(E)
|
- (sizeof(E)/sizeof(E[...]))
+ countof(E)
|
- (sizeof(E)/sizeof(T))
+ countof(E)
)

// [Report Mode] Pattern Matcher: Find division of sizeof array by sizeof element
@r depends on report@
type T;
T[] E;
position p;
@@
(
(sizeof(E)@p /sizeof(*E))
|
(sizeof(E)@p /sizeof(E[...]))
|
(sizeof(E)@p /sizeof(T))
)

// [Report Mode] Output Formatter: Print warning for r to console
@script:python depends on report@
p << r.p;
@@

msg = "WARNING: Use countof"
coccilib.report.print_report(p[0], msg)
Loading