diff options
Diffstat (limited to 'scripts/coccinelle')
22 files changed, 1048 insertions, 1 deletions
diff --git a/scripts/coccinelle/alloc/drop_kmalloc_cast.cocci b/scripts/coccinelle/api/alloc/drop_kmalloc_cast.cocci index 7d4771d449c3..7d4771d449c3 100644 --- a/scripts/coccinelle/alloc/drop_kmalloc_cast.cocci +++ b/scripts/coccinelle/api/alloc/drop_kmalloc_cast.cocci | |||
diff --git a/scripts/coccinelle/alloc/kzalloc-simple.cocci b/scripts/coccinelle/api/alloc/kzalloc-simple.cocci index 2eae828fc657..046b9b16f8f9 100644 --- a/scripts/coccinelle/alloc/kzalloc-simple.cocci +++ b/scripts/coccinelle/api/alloc/kzalloc-simple.cocci | |||
| @@ -1,5 +1,9 @@ | |||
| 1 | /// | 1 | /// |
| 2 | /// kzalloc should be used rather than kmalloc followed by memset 0 | 2 | /// Use kzalloc rather than kmalloc followed by memset with 0 |
| 3 | /// | ||
| 4 | /// This considers some simple cases that are common and easy to validate | ||
| 5 | /// Note in particular that there are no ...s in the rule, so all of the | ||
| 6 | /// matched code has to be contiguous | ||
| 3 | /// | 7 | /// |
| 4 | // Confidence: High | 8 | // Confidence: High |
| 5 | // Copyright: (C) 2009-2010 Julia Lawall, Nicolas Palix, DIKU. GPLv2. | 9 | // Copyright: (C) 2009-2010 Julia Lawall, Nicolas Palix, DIKU. GPLv2. |
diff --git a/scripts/coccinelle/err_cast.cocci b/scripts/coccinelle/api/err_cast.cocci index 2ce115000af6..2ce115000af6 100644 --- a/scripts/coccinelle/err_cast.cocci +++ b/scripts/coccinelle/api/err_cast.cocci | |||
diff --git a/scripts/coccinelle/api/kstrdup.cocci b/scripts/coccinelle/api/kstrdup.cocci new file mode 100644 index 000000000000..e0805ad08d39 --- /dev/null +++ b/scripts/coccinelle/api/kstrdup.cocci | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | /// Use kstrdup rather than duplicating its implementation | ||
| 2 | /// | ||
| 3 | // Confidence: High | ||
| 4 | // Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. | ||
| 5 | // Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. | ||
| 6 | // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. | ||
| 7 | // URL: http://coccinelle.lip6.fr/ | ||
| 8 | // Comments: | ||
| 9 | // Options: -no_includes -include_headers | ||
| 10 | |||
| 11 | virtual patch | ||
| 12 | |||
| 13 | @@ | ||
| 14 | expression from,to; | ||
| 15 | expression flag,E1,E2; | ||
| 16 | statement S; | ||
| 17 | @@ | ||
| 18 | |||
| 19 | - to = kmalloc(strlen(from) + 1,flag); | ||
| 20 | + to = kstrdup(from, flag); | ||
| 21 | ... when != \(from = E1 \| to = E1 \) | ||
| 22 | if (to==NULL || ...) S | ||
| 23 | ... when != \(from = E2 \| to = E2 \) | ||
| 24 | - strcpy(to, from); | ||
| 25 | |||
| 26 | @@ | ||
| 27 | expression x,from,to; | ||
| 28 | expression flag,E1,E2,E3; | ||
| 29 | statement S; | ||
| 30 | @@ | ||
| 31 | |||
| 32 | - x = strlen(from) + 1; | ||
| 33 | ... when != \( x = E1 \| from = E1 \) | ||
| 34 | - to = \(kmalloc\|kzalloc\)(x,flag); | ||
| 35 | + to = kstrdup(from, flag); | ||
| 36 | ... when != \(x = E2 \| from = E2 \| to = E2 \) | ||
| 37 | if (to==NULL || ...) S | ||
| 38 | ... when != \(x = E3 \| from = E3 \| to = E3 \) | ||
| 39 | - memcpy(to, from, x); | ||
diff --git a/scripts/coccinelle/api/memdup.cocci b/scripts/coccinelle/api/memdup.cocci new file mode 100644 index 000000000000..b5d722077dc1 --- /dev/null +++ b/scripts/coccinelle/api/memdup.cocci | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | /// Use kmemdup rather than duplicating its implementation | ||
| 2 | /// | ||
| 3 | // Confidence: High | ||
| 4 | // Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. | ||
| 5 | // Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. | ||
| 6 | // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. | ||
| 7 | // URL: http://coccinelle.lip6.fr/ | ||
| 8 | // Comments: | ||
| 9 | // Options: -no_includes -include_headers | ||
| 10 | |||
| 11 | virtual patch | ||
| 12 | |||
| 13 | @r1@ | ||
| 14 | expression from,to; | ||
| 15 | expression flag; | ||
| 16 | position p; | ||
| 17 | @@ | ||
| 18 | |||
| 19 | to = \(kmalloc@p\|kzalloc@p\)(strlen(from) + 1,flag); | ||
| 20 | |||
| 21 | @r2@ | ||
| 22 | expression x,from,to; | ||
| 23 | expression flag,E1; | ||
| 24 | position p; | ||
| 25 | @@ | ||
| 26 | |||
| 27 | x = strlen(from) + 1; | ||
| 28 | ... when != \( x = E1 \| from = E1 \) | ||
| 29 | to = \(kmalloc@p\|kzalloc@p\)(x,flag); | ||
| 30 | |||
| 31 | @@ | ||
| 32 | expression from,to,size,flag; | ||
| 33 | position p != {r1.p,r2.p}; | ||
| 34 | statement S; | ||
| 35 | @@ | ||
| 36 | |||
| 37 | - to = \(kmalloc@p\|kzalloc@p\)(size,flag); | ||
| 38 | + to = kmemdup(from,size,flag); | ||
| 39 | if (to==NULL || ...) S | ||
| 40 | - memcpy(to, from, size); | ||
diff --git a/scripts/coccinelle/api/memdup_user.cocci b/scripts/coccinelle/api/memdup_user.cocci new file mode 100644 index 000000000000..72ce012e878a --- /dev/null +++ b/scripts/coccinelle/api/memdup_user.cocci | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | /// Use kmemdup_user rather than duplicating its implementation | ||
| 2 | /// This is a little bit restricted to reduce false positives | ||
| 3 | /// | ||
| 4 | // Confidence: High | ||
| 5 | // Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. | ||
| 6 | // Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. | ||
| 7 | // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. | ||
| 8 | // URL: http://coccinelle.lip6.fr/ | ||
| 9 | // Comments: | ||
| 10 | // Options: -no_includes -include_headers | ||
| 11 | |||
| 12 | virtual patch | ||
| 13 | |||
| 14 | @@ | ||
| 15 | expression from,to,size,flag; | ||
| 16 | position p; | ||
| 17 | identifier l1,l2; | ||
| 18 | @@ | ||
| 19 | |||
| 20 | - to = \(kmalloc@p\|kzalloc@p\)(size,flag); | ||
| 21 | + to = memdup_user(from,size); | ||
| 22 | if ( | ||
| 23 | - to==NULL | ||
| 24 | + IS_ERR(to) | ||
| 25 | || ...) { | ||
| 26 | <+... when != goto l1; | ||
| 27 | - -ENOMEM | ||
| 28 | + PTR_ERR(to) | ||
| 29 | ...+> | ||
| 30 | } | ||
| 31 | - if (copy_from_user(to, from, size) != 0) { | ||
| 32 | - <+... when != goto l2; | ||
| 33 | - -EFAULT | ||
| 34 | - ...+> | ||
| 35 | - } | ||
diff --git a/scripts/coccinelle/resource_size.cocci b/scripts/coccinelle/api/resource_size.cocci index 1935a58b39d9..1935a58b39d9 100644 --- a/scripts/coccinelle/resource_size.cocci +++ b/scripts/coccinelle/api/resource_size.cocci | |||
diff --git a/scripts/coccinelle/free/kfree.cocci b/scripts/coccinelle/free/kfree.cocci new file mode 100644 index 000000000000..f9f79d9245ee --- /dev/null +++ b/scripts/coccinelle/free/kfree.cocci | |||
| @@ -0,0 +1,117 @@ | |||
| 1 | /// Find a use after free. | ||
| 2 | //# Values of variables may imply that some | ||
| 3 | //# execution paths are not possible, resulting in false positives. | ||
| 4 | //# Another source of false positives are macros such as | ||
| 5 | //# SCTP_DBG_OBJCNT_DEC that do not actually evaluate their argument | ||
| 6 | /// | ||
| 7 | // Confidence: Moderate | ||
| 8 | // Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. | ||
| 9 | // Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. | ||
| 10 | // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. | ||
| 11 | // URL: http://coccinelle.lip6.fr/ | ||
| 12 | // Comments: | ||
| 13 | // Options: -no_includes -include_headers | ||
| 14 | |||
| 15 | virtual org | ||
| 16 | virtual report | ||
| 17 | |||
| 18 | @free@ | ||
| 19 | expression E; | ||
| 20 | position p1; | ||
| 21 | @@ | ||
| 22 | |||
| 23 | kfree@p1(E) | ||
| 24 | |||
| 25 | @print expression@ | ||
| 26 | constant char *c; | ||
| 27 | expression free.E,E2; | ||
| 28 | type T; | ||
| 29 | position p; | ||
| 30 | identifier f; | ||
| 31 | @@ | ||
| 32 | |||
| 33 | ( | ||
| 34 | f(...,c,...,(T)E@p,...) | ||
| 35 | | | ||
| 36 | E@p == E2 | ||
| 37 | | | ||
| 38 | E@p != E2 | ||
| 39 | | | ||
| 40 | !E@p | ||
| 41 | | | ||
| 42 | E@p || ... | ||
| 43 | ) | ||
| 44 | |||
| 45 | @sz@ | ||
| 46 | expression free.E; | ||
| 47 | position p; | ||
| 48 | @@ | ||
| 49 | |||
| 50 | sizeof(<+...E@p...+>) | ||
| 51 | |||
| 52 | @loop exists@ | ||
| 53 | expression E; | ||
| 54 | identifier l; | ||
| 55 | position ok; | ||
| 56 | @@ | ||
| 57 | |||
| 58 | while (1) { ... | ||
| 59 | kfree@ok(E) | ||
| 60 | ... when != break; | ||
| 61 | when != goto l; | ||
| 62 | when forall | ||
| 63 | } | ||
| 64 | |||
| 65 | @r exists@ | ||
| 66 | expression free.E, subE<=free.E, E2; | ||
| 67 | expression E1; | ||
| 68 | iterator iter; | ||
| 69 | statement S; | ||
| 70 | position free.p1!=loop.ok,p2!={print.p,sz.p}; | ||
| 71 | @@ | ||
| 72 | |||
| 73 | kfree@p1(E,...) | ||
| 74 | ... | ||
| 75 | ( | ||
| 76 | iter(...,subE,...) S // no use | ||
| 77 | | | ||
| 78 | list_remove_head(E1,subE,...) | ||
| 79 | | | ||
| 80 | subE = E2 | ||
| 81 | | | ||
| 82 | subE++ | ||
| 83 | | | ||
| 84 | ++subE | ||
| 85 | | | ||
| 86 | --subE | ||
| 87 | | | ||
| 88 | subE-- | ||
| 89 | | | ||
| 90 | &subE | ||
| 91 | | | ||
| 92 | BUG(...) | ||
| 93 | | | ||
| 94 | BUG_ON(...) | ||
| 95 | | | ||
| 96 | return_VALUE(...) | ||
| 97 | | | ||
| 98 | return_ACPI_STATUS(...) | ||
| 99 | | | ||
| 100 | E@p2 // bad use | ||
| 101 | ) | ||
| 102 | |||
| 103 | @script:python depends on org@ | ||
| 104 | p1 << free.p1; | ||
| 105 | p2 << r.p2; | ||
| 106 | @@ | ||
| 107 | |||
| 108 | cocci.print_main("kfree",p1) | ||
| 109 | cocci.print_secs("ref",p2) | ||
| 110 | |||
| 111 | @script:python depends on report@ | ||
| 112 | p1 << free.p1; | ||
| 113 | p2 << r.p2; | ||
| 114 | @@ | ||
| 115 | |||
| 116 | msg = "reference preceded by free on line %s" % (p1[0].line) | ||
| 117 | coccilib.report.print_report(p2[0],msg) | ||
diff --git a/scripts/coccinelle/iterators/fen.cocci b/scripts/coccinelle/iterators/fen.cocci new file mode 100644 index 000000000000..77bc108c3f59 --- /dev/null +++ b/scripts/coccinelle/iterators/fen.cocci | |||
| @@ -0,0 +1,64 @@ | |||
| 1 | /// These iterators only exit normally when the loop cursor is NULL, so there | ||
| 2 | /// is no point to call of_node_put on the final value. | ||
| 3 | /// | ||
| 4 | // Confidence: High | ||
| 5 | // Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. | ||
| 6 | // Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. | ||
| 7 | // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. | ||
| 8 | // URL: http://coccinelle.lip6.fr/ | ||
| 9 | // Comments: | ||
| 10 | // Options: -no_includes -include_headers | ||
| 11 | |||
| 12 | virtual patch | ||
| 13 | |||
| 14 | @@ | ||
| 15 | iterator name for_each_node_by_name; | ||
| 16 | expression np,E; | ||
| 17 | identifier l; | ||
| 18 | @@ | ||
| 19 | |||
| 20 | for_each_node_by_name(np,...) { | ||
| 21 | ... when != break; | ||
| 22 | when != goto l; | ||
| 23 | } | ||
| 24 | ... when != np = E | ||
| 25 | - of_node_put(np); | ||
| 26 | |||
| 27 | @@ | ||
| 28 | iterator name for_each_node_by_type; | ||
| 29 | expression np,E; | ||
| 30 | identifier l; | ||
| 31 | @@ | ||
| 32 | |||
| 33 | for_each_node_by_type(np,...) { | ||
| 34 | ... when != break; | ||
| 35 | when != goto l; | ||
| 36 | } | ||
| 37 | ... when != np = E | ||
| 38 | - of_node_put(np); | ||
| 39 | |||
| 40 | @@ | ||
| 41 | iterator name for_each_compatible_node; | ||
| 42 | expression np,E; | ||
| 43 | identifier l; | ||
| 44 | @@ | ||
| 45 | |||
| 46 | for_each_compatible_node(np,...) { | ||
| 47 | ... when != break; | ||
| 48 | when != goto l; | ||
| 49 | } | ||
| 50 | ... when != np = E | ||
| 51 | - of_node_put(np); | ||
| 52 | |||
| 53 | @@ | ||
| 54 | iterator name for_each_matching_node; | ||
| 55 | expression np,E; | ||
| 56 | identifier l; | ||
| 57 | @@ | ||
| 58 | |||
| 59 | for_each_matching_node(np,...) { | ||
| 60 | ... when != break; | ||
| 61 | when != goto l; | ||
| 62 | } | ||
| 63 | ... when != np = E | ||
| 64 | - of_node_put(np); | ||
diff --git a/scripts/coccinelle/iterators/itnull.cocci b/scripts/coccinelle/iterators/itnull.cocci new file mode 100644 index 000000000000..baa4297a4ed1 --- /dev/null +++ b/scripts/coccinelle/iterators/itnull.cocci | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | /// Many iterators have the property that the first argument is always bound | ||
| 2 | /// to a real list element, never NULL. False positives arise for some | ||
| 3 | /// iterators that do not have this property, or in cases when the loop | ||
| 4 | /// cursor is reassigned. The latter should only happen when the matched | ||
| 5 | /// code is on the way to a loop exit (break, goto, or return). | ||
| 6 | /// | ||
| 7 | // Confidence: Moderate | ||
| 8 | // Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. | ||
| 9 | // Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. | ||
| 10 | // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. | ||
| 11 | // URL: http://coccinelle.lip6.fr/ | ||
| 12 | // Comments: | ||
| 13 | // Options: -no_includes -include_headers | ||
| 14 | |||
| 15 | virtual patch | ||
| 16 | |||
| 17 | @@ | ||
| 18 | iterator I; | ||
| 19 | expression x,E,E1,E2; | ||
| 20 | statement S,S1,S2; | ||
| 21 | @@ | ||
| 22 | |||
| 23 | I(x,...) { <... | ||
| 24 | ( | ||
| 25 | - if (x == NULL && ...) S | ||
| 26 | | | ||
| 27 | - if (x != NULL || ...) | ||
| 28 | S | ||
| 29 | | | ||
| 30 | - (x == NULL) || | ||
| 31 | E | ||
| 32 | | | ||
| 33 | - (x != NULL) && | ||
| 34 | E | ||
| 35 | | | ||
| 36 | - (x == NULL && ...) ? E1 : | ||
| 37 | E2 | ||
| 38 | | | ||
| 39 | - (x != NULL || ...) ? | ||
| 40 | E1 | ||
| 41 | - : E2 | ||
| 42 | | | ||
| 43 | - if (x == NULL && ...) S1 else | ||
| 44 | S2 | ||
| 45 | | | ||
| 46 | - if (x != NULL || ...) | ||
| 47 | S1 | ||
| 48 | - else S2 | ||
| 49 | | | ||
| 50 | + BAD( | ||
| 51 | x == NULL | ||
| 52 | + ) | ||
| 53 | | | ||
| 54 | + BAD( | ||
| 55 | x != NULL | ||
| 56 | + ) | ||
| 57 | ) | ||
| 58 | ...> } \ No newline at end of file | ||
diff --git a/scripts/coccinelle/iterators/list_entry_update.cocci b/scripts/coccinelle/iterators/list_entry_update.cocci new file mode 100644 index 000000000000..b2967475679b --- /dev/null +++ b/scripts/coccinelle/iterators/list_entry_update.cocci | |||
| @@ -0,0 +1,62 @@ | |||
| 1 | /// list_for_each_entry uses its first argument to get from one element of | ||
| 2 | /// the list to the next, so it is usually not a good idea to reassign it. | ||
| 3 | /// The first rule finds such a reassignment and the second rule checks | ||
| 4 | /// that there is a path from the reassignment back to the top of the loop. | ||
| 5 | /// | ||
| 6 | // Confidence: High | ||
| 7 | // Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. | ||
| 8 | // Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. | ||
| 9 | // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. | ||
| 10 | // URL: http://coccinelle.lip6.fr/ | ||
| 11 | // Comments: | ||
| 12 | // Options: -no_includes -include_headers | ||
| 13 | |||
| 14 | virtual context | ||
| 15 | virtual org | ||
| 16 | virtual report | ||
| 17 | |||
| 18 | @r@ | ||
| 19 | iterator name list_for_each_entry; | ||
| 20 | expression x,E; | ||
| 21 | position p1,p2; | ||
| 22 | @@ | ||
| 23 | |||
| 24 | list_for_each_entry@p1(x,...) { <... x =@p2 E ...> } | ||
| 25 | |||
| 26 | @depends on context && !org && !report@ | ||
| 27 | expression x,E; | ||
| 28 | position r.p1,r.p2; | ||
| 29 | statement S; | ||
| 30 | @@ | ||
| 31 | |||
| 32 | *x =@p2 E | ||
| 33 | ... | ||
| 34 | list_for_each_entry@p1(x,...) S | ||
| 35 | |||
| 36 | // ------------------------------------------------------------------------ | ||
| 37 | |||
| 38 | @back depends on (org || report) && !context exists@ | ||
| 39 | expression x,E; | ||
| 40 | position r.p1,r.p2; | ||
| 41 | statement S; | ||
| 42 | @@ | ||
| 43 | |||
| 44 | x =@p2 E | ||
| 45 | ... | ||
| 46 | list_for_each_entry@p1(x,...) S | ||
| 47 | |||
| 48 | @script:python depends on back && org@ | ||
| 49 | p1 << r.p1; | ||
| 50 | p2 << r.p2; | ||
| 51 | @@ | ||
| 52 | |||
| 53 | cocci.print_main("iterator",p1) | ||
| 54 | cocci.print_secs("update",p2) | ||
| 55 | |||
| 56 | @script:python depends on back && report@ | ||
| 57 | p1 << r.p1; | ||
| 58 | p2 << r.p2; | ||
| 59 | @@ | ||
| 60 | |||
| 61 | msg = "iterator with update on line %s" % (p2[0].line) | ||
| 62 | coccilib.report.print_report(p1[0],msg) | ||
diff --git a/scripts/coccinelle/locks/call_kern.cocci b/scripts/coccinelle/locks/call_kern.cocci new file mode 100644 index 000000000000..00af5344a68f --- /dev/null +++ b/scripts/coccinelle/locks/call_kern.cocci | |||
| @@ -0,0 +1,74 @@ | |||
| 1 | /// Find functions that refer to GFP_KERNEL but are called with locks held. | ||
| 2 | /// The proposed change of converting the GFP_KERNEL is not necessarily the | ||
| 3 | /// correct one. It may be desired to unlock the lock, or to not call the | ||
| 4 | /// function under the lock in the first place. | ||
| 5 | /// | ||
| 6 | // Confidence: Moderate | ||
| 7 | // Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. | ||
| 8 | // Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. | ||
| 9 | // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. | ||
| 10 | // URL: http://coccinelle.lip6.fr/ | ||
| 11 | // Comments: | ||
| 12 | // Options: -no_includes -include_headers | ||
| 13 | |||
| 14 | virtual patch | ||
| 15 | |||
| 16 | @gfp exists@ | ||
| 17 | identifier fn; | ||
| 18 | position p; | ||
| 19 | @@ | ||
| 20 | |||
| 21 | fn(...) { | ||
| 22 | ... when != read_unlock_irq(...) | ||
| 23 | when != write_unlock_irq(...) | ||
| 24 | when != read_unlock_irqrestore(...) | ||
| 25 | when != write_unlock_irqrestore(...) | ||
| 26 | when != spin_unlock(...) | ||
| 27 | when != spin_unlock_irq(...) | ||
| 28 | when != spin_unlock_irqrestore(...) | ||
| 29 | when != local_irq_enable(...) | ||
| 30 | when any | ||
| 31 | GFP_KERNEL@p | ||
| 32 | ... when any | ||
| 33 | } | ||
| 34 | |||
| 35 | @locked@ | ||
| 36 | identifier gfp.fn; | ||
| 37 | @@ | ||
| 38 | |||
| 39 | ( | ||
| 40 | read_lock_irq | ||
| 41 | | | ||
| 42 | write_lock_irq | ||
| 43 | | | ||
| 44 | read_lock_irqsave | ||
| 45 | | | ||
| 46 | write_lock_irqsave | ||
| 47 | | | ||
| 48 | spin_lock | ||
| 49 | | | ||
| 50 | spin_trylock | ||
| 51 | | | ||
| 52 | spin_lock_irq | ||
| 53 | | | ||
| 54 | spin_lock_irqsave | ||
| 55 | | | ||
| 56 | local_irq_disable | ||
| 57 | ) | ||
| 58 | (...) | ||
| 59 | ... when != read_unlock_irq(...) | ||
| 60 | when != write_unlock_irq(...) | ||
| 61 | when != read_unlock_irqrestore(...) | ||
| 62 | when != write_unlock_irqrestore(...) | ||
| 63 | when != spin_unlock(...) | ||
| 64 | when != spin_unlock_irq(...) | ||
| 65 | when != spin_unlock_irqrestore(...) | ||
| 66 | when != local_irq_enable(...) | ||
| 67 | fn(...) | ||
| 68 | |||
| 69 | @depends on locked@ | ||
| 70 | position gfp.p; | ||
| 71 | @@ | ||
| 72 | |||
| 73 | - GFP_KERNEL@p | ||
| 74 | + GFP_ATOMIC | ||
diff --git a/scripts/coccinelle/locks/double_lock.cocci b/scripts/coccinelle/locks/double_lock.cocci new file mode 100644 index 000000000000..63b24e682fad --- /dev/null +++ b/scripts/coccinelle/locks/double_lock.cocci | |||
| @@ -0,0 +1,92 @@ | |||
| 1 | /// Find double locks. False positives may occur when some paths cannot | ||
| 2 | /// occur at execution, due to the values of variables, and when there is | ||
| 3 | /// an intervening function call that releases the lock. | ||
| 4 | /// | ||
| 5 | // Confidence: Moderate | ||
| 6 | // Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. | ||
| 7 | // Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. | ||
| 8 | // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. | ||
| 9 | // URL: http://coccinelle.lip6.fr/ | ||
| 10 | // Comments: | ||
| 11 | // Options: -no_includes -include_headers | ||
| 12 | |||
| 13 | virtual org | ||
| 14 | virtual report | ||
| 15 | |||
| 16 | @locked@ | ||
| 17 | position p1; | ||
| 18 | expression E1; | ||
| 19 | position p; | ||
| 20 | @@ | ||
| 21 | |||
| 22 | ( | ||
| 23 | mutex_lock@p1 | ||
| 24 | | | ||
| 25 | mutex_trylock@p1 | ||
| 26 | | | ||
| 27 | spin_lock@p1 | ||
| 28 | | | ||
| 29 | spin_trylock@p1 | ||
| 30 | | | ||
| 31 | read_lock@p1 | ||
| 32 | | | ||
| 33 | read_trylock@p1 | ||
| 34 | | | ||
| 35 | write_lock@p1 | ||
| 36 | | | ||
| 37 | write_trylock@p1 | ||
| 38 | ) (E1@p,...); | ||
| 39 | |||
| 40 | @balanced@ | ||
| 41 | position p1 != locked.p1; | ||
| 42 | position locked.p; | ||
| 43 | identifier lock,unlock; | ||
| 44 | expression x <= locked.E1; | ||
| 45 | expression E,locked.E1; | ||
| 46 | expression E2; | ||
| 47 | @@ | ||
| 48 | |||
| 49 | if (E) { | ||
| 50 | <+... when != E1 | ||
| 51 | lock(E1@p,...) | ||
| 52 | ...+> | ||
| 53 | } | ||
| 54 | ... when != E1 | ||
| 55 | when != \(x = E2\|&x\) | ||
| 56 | when forall | ||
| 57 | if (E) { | ||
| 58 | <+... when != E1 | ||
| 59 | unlock@p1(E1,...) | ||
| 60 | ...+> | ||
| 61 | } | ||
| 62 | |||
| 63 | @r depends on !balanced exists@ | ||
| 64 | expression x <= locked.E1; | ||
| 65 | expression locked.E1; | ||
| 66 | expression E2; | ||
| 67 | identifier lock; | ||
| 68 | position locked.p,p1,p2; | ||
| 69 | @@ | ||
| 70 | |||
| 71 | lock@p1 (E1@p,...); | ||
| 72 | ... when != E1 | ||
| 73 | when != \(x = E2\|&x\) | ||
| 74 | lock@p2 (E1,...); | ||
| 75 | |||
| 76 | @script:python depends on org@ | ||
| 77 | p1 << r.p1; | ||
| 78 | p2 << r.p2; | ||
| 79 | lock << r.lock; | ||
| 80 | @@ | ||
| 81 | |||
| 82 | cocci.print_main(lock,p1) | ||
| 83 | cocci.print_secs("second lock",p2) | ||
| 84 | |||
| 85 | @script:python depends on report@ | ||
| 86 | p1 << r.p1; | ||
| 87 | p2 << r.p2; | ||
| 88 | lock << r.lock; | ||
| 89 | @@ | ||
| 90 | |||
| 91 | msg = "second lock on line %s" % (p2[0].line) | ||
| 92 | coccilib.report.print_report(p1[0],msg) | ||
diff --git a/scripts/coccinelle/locks/flags.cocci b/scripts/coccinelle/locks/flags.cocci new file mode 100644 index 000000000000..b4344d838097 --- /dev/null +++ b/scripts/coccinelle/locks/flags.cocci | |||
| @@ -0,0 +1,80 @@ | |||
| 1 | /// Find nested lock+irqsave functions that use the same flags variables | ||
| 2 | /// | ||
| 3 | // Confidence: High | ||
| 4 | // Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. | ||
| 5 | // Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. | ||
| 6 | // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. | ||
| 7 | // URL: http://coccinelle.lip6.fr/ | ||
| 8 | // Comments: | ||
| 9 | // Options: -no_includes -include_headers | ||
| 10 | |||
| 11 | virtual context | ||
| 12 | virtual org | ||
| 13 | virtual report | ||
| 14 | |||
| 15 | @r@ | ||
| 16 | expression lock1,lock2,flags; | ||
| 17 | position p1,p2; | ||
| 18 | @@ | ||
| 19 | |||
| 20 | ( | ||
| 21 | spin_lock_irqsave@p1(lock1,flags) | ||
| 22 | | | ||
| 23 | read_lock_irqsave@p1(lock1,flags) | ||
| 24 | | | ||
| 25 | write_lock_irqsave@p1(lock1,flags) | ||
| 26 | ) | ||
| 27 | ... when != flags | ||
| 28 | ( | ||
| 29 | spin_lock_irqsave(lock1,flags) | ||
| 30 | | | ||
| 31 | read_lock_irqsave(lock1,flags) | ||
| 32 | | | ||
| 33 | write_lock_irqsave(lock1,flags) | ||
| 34 | | | ||
| 35 | spin_lock_irqsave@p2(lock2,flags) | ||
| 36 | | | ||
| 37 | read_lock_irqsave@p2(lock2,flags) | ||
| 38 | | | ||
| 39 | write_lock_irqsave@p2(lock2,flags) | ||
| 40 | ) | ||
| 41 | |||
| 42 | @d@ | ||
| 43 | expression f <= r.flags; | ||
| 44 | expression lock1,lock2,flags; | ||
| 45 | position r.p1, r.p2; | ||
| 46 | @@ | ||
| 47 | |||
| 48 | ( | ||
| 49 | *spin_lock_irqsave@p1(lock1,flags) | ||
| 50 | | | ||
| 51 | *read_lock_irqsave@p1(lock1,flags) | ||
| 52 | | | ||
| 53 | *write_lock_irqsave@p1(lock1,flags) | ||
| 54 | ) | ||
| 55 | ... when != f | ||
| 56 | ( | ||
| 57 | *spin_lock_irqsave@p2(lock2,flags) | ||
| 58 | | | ||
| 59 | *read_lock_irqsave@p2(lock2,flags) | ||
| 60 | | | ||
| 61 | *write_lock_irqsave@p2(lock2,flags) | ||
| 62 | ) | ||
| 63 | |||
| 64 | // ---------------------------------------------------------------------- | ||
| 65 | |||
| 66 | @script:python depends on d && org@ | ||
| 67 | p1 << r.p1; | ||
| 68 | p2 << r.p2; | ||
| 69 | @@ | ||
| 70 | |||
| 71 | cocci.print_main("original lock",p1) | ||
| 72 | cocci.print_secs("nested lock+irqsave that reuses flags",p2) | ||
| 73 | |||
| 74 | @script:python depends on d && report@ | ||
| 75 | p1 << r.p1; | ||
| 76 | p2 << r.p2; | ||
| 77 | @@ | ||
| 78 | |||
| 79 | msg="ERROR: nested lock+irqsave that reuses flags from %s." % (p1[0].line) | ||
| 80 | coccilib.report.print_report(p2[0], msg) | ||
diff --git a/scripts/coccinelle/locks/mini_lock.cocci b/scripts/coccinelle/locks/mini_lock.cocci new file mode 100644 index 000000000000..7641a2925434 --- /dev/null +++ b/scripts/coccinelle/locks/mini_lock.cocci | |||
| @@ -0,0 +1,95 @@ | |||
| 1 | /// Find missing unlocks. This semantic match considers the specific case | ||
| 2 | /// where the unlock is missing from an if branch, and there is a lock | ||
| 3 | /// before the if and an unlock after the if. False positives are due to | ||
| 4 | /// cases where the if branch represents a case where the function is | ||
| 5 | /// supposed to exit with the lock held, or where there is some preceding | ||
| 6 | /// function call that releases the lock. | ||
| 7 | /// | ||
| 8 | // Confidence: Moderate | ||
| 9 | // Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. | ||
| 10 | // Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. | ||
| 11 | // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. | ||
| 12 | // URL: http://coccinelle.lip6.fr/ | ||
| 13 | // Comments: | ||
| 14 | // Options: -no_includes -include_headers | ||
| 15 | |||
| 16 | virtual org | ||
| 17 | virtual report | ||
| 18 | |||
| 19 | @prelocked@ | ||
| 20 | position p1,p; | ||
| 21 | expression E1; | ||
| 22 | @@ | ||
| 23 | |||
| 24 | ( | ||
| 25 | mutex_lock@p1 | ||
| 26 | | | ||
| 27 | mutex_trylock@p1 | ||
| 28 | | | ||
| 29 | spin_lock@p1 | ||
| 30 | | | ||
| 31 | spin_trylock@p1 | ||
| 32 | | | ||
| 33 | read_lock@p1 | ||
| 34 | | | ||
| 35 | read_trylock@p1 | ||
| 36 | | | ||
| 37 | write_lock@p1 | ||
| 38 | | | ||
| 39 | write_trylock@p1 | ||
| 40 | | | ||
| 41 | read_lock_irq@p1 | ||
| 42 | | | ||
| 43 | write_lock_irq@p1 | ||
| 44 | | | ||
| 45 | read_lock_irqsave@p1 | ||
| 46 | | | ||
| 47 | write_lock_irqsave@p1 | ||
| 48 | | | ||
| 49 | spin_lock_irq@p1 | ||
| 50 | | | ||
| 51 | spin_lock_irqsave@p1 | ||
| 52 | ) (E1@p,...); | ||
| 53 | |||
| 54 | @looped@ | ||
| 55 | position r; | ||
| 56 | @@ | ||
| 57 | |||
| 58 | for(...;...;...) { <+... return@r ...; ...+> } | ||
| 59 | |||
| 60 | @err@ | ||
| 61 | expression E1; | ||
| 62 | position prelocked.p; | ||
| 63 | position up != prelocked.p1; | ||
| 64 | position r!=looped.r; | ||
| 65 | identifier lock,unlock; | ||
| 66 | @@ | ||
| 67 | |||
| 68 | lock(E1@p,...); | ||
| 69 | <+... when != E1 | ||
| 70 | if (...) { | ||
| 71 | ... when != E1 | ||
| 72 | return@r ...; | ||
| 73 | } | ||
| 74 | ...+> | ||
| 75 | unlock@up(E1,...); | ||
| 76 | |||
| 77 | @script:python depends on org@ | ||
| 78 | p << prelocked.p1; | ||
| 79 | lock << err.lock; | ||
| 80 | unlock << err.unlock; | ||
| 81 | p2 << err.r; | ||
| 82 | @@ | ||
| 83 | |||
| 84 | cocci.print_main(lock,p) | ||
| 85 | cocci.print_secs(unlock,p2) | ||
| 86 | |||
| 87 | @script:python depends on report@ | ||
| 88 | p << prelocked.p1; | ||
| 89 | lock << err.lock; | ||
| 90 | unlock << err.unlock; | ||
| 91 | p2 << err.r; | ||
| 92 | @@ | ||
| 93 | |||
| 94 | msg = "preceding lock on line %s" % (p[0].line) | ||
| 95 | coccilib.report.print_report(p2[0],msg) | ||
diff --git a/scripts/coccinelle/misc/doubleinit.cocci b/scripts/coccinelle/misc/doubleinit.cocci new file mode 100644 index 000000000000..55d7dc19dfe0 --- /dev/null +++ b/scripts/coccinelle/misc/doubleinit.cocci | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | /// Find duplicate field initializations. This has a high rate of false | ||
| 2 | /// positives due to #ifdefs, which Coccinelle is not aware of in a structure | ||
| 3 | /// initialization. | ||
| 4 | /// | ||
| 5 | // Confidence: Low | ||
| 6 | // Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. | ||
| 7 | // Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. | ||
| 8 | // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. | ||
| 9 | // URL: http://coccinelle.lip6.fr/ | ||
| 10 | // Comments: | ||
| 11 | // Options: -no_includes -include_headers | ||
| 12 | |||
| 13 | virtual org | ||
| 14 | virtual report | ||
| 15 | |||
| 16 | @r@ | ||
| 17 | identifier I, s, fld; | ||
| 18 | position p0,p; | ||
| 19 | expression E; | ||
| 20 | @@ | ||
| 21 | |||
| 22 | struct I s =@p0 { ... .fld@p = E, ...}; | ||
| 23 | |||
| 24 | @s@ | ||
| 25 | identifier I, s, r.fld; | ||
| 26 | position r.p0,p; | ||
| 27 | expression E; | ||
| 28 | @@ | ||
| 29 | |||
| 30 | struct I s =@p0 { ... .fld@p = E, ...}; | ||
| 31 | |||
| 32 | @script:python depends on org@ | ||
| 33 | p0 << r.p0; | ||
| 34 | fld << r.fld; | ||
| 35 | ps << s.p; | ||
| 36 | pr << r.p; | ||
| 37 | @@ | ||
| 38 | |||
| 39 | if int(ps[0].line) < int(pr[0].line) or (int(ps[0].line) == int(pr[0].line) and int(ps[0].column) < int(pr[0].column)): | ||
| 40 | cocci.print_main(fld,p0) | ||
| 41 | cocci.print_secs("s",ps) | ||
| 42 | cocci.print_secs("r",pr) | ||
| 43 | |||
| 44 | @script:python depends on report@ | ||
| 45 | p0 << r.p0; | ||
| 46 | fld << r.fld; | ||
| 47 | ps << s.p; | ||
| 48 | pr << r.p; | ||
| 49 | @@ | ||
| 50 | |||
| 51 | if int(ps[0].line) < int(pr[0].line) or (int(ps[0].line) == int(pr[0].line) and int(ps[0].column) < int(pr[0].column)): | ||
| 52 | msg = "%s: first occurrence %s, second occurrence %s" % (fld,ps[0].line,pr[0].line) | ||
| 53 | coccilib.report.print_report(p0[0],msg) | ||
diff --git a/scripts/coccinelle/misc/ifcol.cocci b/scripts/coccinelle/misc/ifcol.cocci new file mode 100644 index 000000000000..b7ed91dbeb95 --- /dev/null +++ b/scripts/coccinelle/misc/ifcol.cocci | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | /// Find confusingly indented code in or after an if. An if branch should | ||
| 2 | /// be indented. The code following an if should not be indented. | ||
| 3 | /// Sometimes, code after an if that is indented is actually intended to be | ||
| 4 | /// part of the if branch. | ||
| 5 | /// | ||
| 6 | /// This has a high rate of false positives, because Coccinelle's column | ||
| 7 | /// calculation does not distinguish between spaces and tabs, so code that | ||
| 8 | /// is not visually aligned may be considered to be in the same column. | ||
| 9 | /// | ||
| 10 | // Confidence: Low | ||
| 11 | // Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. | ||
| 12 | // Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. | ||
| 13 | // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. | ||
| 14 | // URL: http://coccinelle.lip6.fr/ | ||
| 15 | // Comments: | ||
| 16 | // Options: -no_includes -include_headers | ||
| 17 | |||
| 18 | virtual org | ||
| 19 | virtual report | ||
| 20 | |||
| 21 | @r disable braces4@ | ||
| 22 | position p1,p2; | ||
| 23 | statement S1,S2; | ||
| 24 | @@ | ||
| 25 | |||
| 26 | ( | ||
| 27 | if (...) { ... } | ||
| 28 | | | ||
| 29 | if (...) S1@p1 S2@p2 | ||
| 30 | ) | ||
| 31 | |||
| 32 | @script:python depends on org@ | ||
| 33 | p1 << r.p1; | ||
| 34 | p2 << r.p2; | ||
| 35 | @@ | ||
| 36 | |||
| 37 | if (p1[0].column == p2[0].column): | ||
| 38 | cocci.print_main("branch",p1) | ||
| 39 | cocci.print_secs("after",p2) | ||
| 40 | |||
| 41 | @script:python depends on report@ | ||
| 42 | p1 << r.p1; | ||
| 43 | p2 << r.p2; | ||
| 44 | @@ | ||
| 45 | |||
| 46 | if (p1[0].column == p2[0].column): | ||
| 47 | msg = "code aligned with following code on line %s" % (p2[0].line) | ||
| 48 | coccilib.report.print_report(p1[0],msg) | ||
diff --git a/scripts/coccinelle/deref_null.cocci b/scripts/coccinelle/null/deref_null.cocci index 9969d76d0f4b..9969d76d0f4b 100644 --- a/scripts/coccinelle/deref_null.cocci +++ b/scripts/coccinelle/null/deref_null.cocci | |||
diff --git a/scripts/coccinelle/null/eno.cocci b/scripts/coccinelle/null/eno.cocci new file mode 100644 index 000000000000..4c9c52b9c413 --- /dev/null +++ b/scripts/coccinelle/null/eno.cocci | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | /// The various basic memory allocation functions don't return ERR_PTR | ||
| 2 | /// | ||
| 3 | // Confidence: High | ||
| 4 | // Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. | ||
| 5 | // Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. | ||
| 6 | // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. | ||
| 7 | // URL: http://coccinelle.lip6.fr/ | ||
| 8 | // Comments: | ||
| 9 | // Options: -no_includes -include_headers | ||
| 10 | |||
| 11 | virtual patch | ||
| 12 | |||
| 13 | @@ | ||
| 14 | expression x,E; | ||
| 15 | @@ | ||
| 16 | |||
| 17 | x = \(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\)(...) | ||
| 18 | ... when != x = E | ||
| 19 | - IS_ERR(x) | ||
| 20 | + !x | ||
diff --git a/scripts/coccinelle/null/kmerr.cocci b/scripts/coccinelle/null/kmerr.cocci new file mode 100644 index 000000000000..949bf656c64c --- /dev/null +++ b/scripts/coccinelle/null/kmerr.cocci | |||
| @@ -0,0 +1,72 @@ | |||
| 1 | /// This semantic patch looks for kmalloc etc that are not followed by a | ||
| 2 | /// NULL check. It only gives a report in the case where there is some | ||
| 3 | /// error handling code later in the function, which may be helpful | ||
| 4 | /// in determining what the error handling code for the call to kmalloc etc | ||
| 5 | /// should be. | ||
| 6 | /// | ||
| 7 | // Confidence: High | ||
| 8 | // Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. | ||
| 9 | // Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. | ||
| 10 | // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. | ||
| 11 | // URL: http://coccinelle.lip6.fr/ | ||
| 12 | // Comments: | ||
| 13 | // Options: -no_includes -include_headers | ||
| 14 | |||
| 15 | virtual context | ||
| 16 | virtual org | ||
| 17 | virtual report | ||
| 18 | |||
| 19 | @withtest@ | ||
| 20 | expression x; | ||
| 21 | position p; | ||
| 22 | identifier f,fld; | ||
| 23 | @@ | ||
| 24 | |||
| 25 | x@p = f(...); | ||
| 26 | ... when != x->fld | ||
| 27 | \(x == NULL \| x != NULL\) | ||
| 28 | |||
| 29 | @fixed depends on context && !org && !report@ | ||
| 30 | expression x,x1; | ||
| 31 | position p1 != withtest.p; | ||
| 32 | statement S; | ||
| 33 | position any withtest.p; | ||
| 34 | identifier f; | ||
| 35 | @@ | ||
| 36 | |||
| 37 | *x@p1 = \(kmalloc\|kzalloc\|kcalloc\)(...); | ||
| 38 | ... | ||
| 39 | *x1@p = f(...); | ||
| 40 | if (!x1) S | ||
| 41 | |||
| 42 | // ------------------------------------------------------------------------ | ||
| 43 | |||
| 44 | @rfixed depends on (org || report) && !context exists@ | ||
| 45 | expression x,x1; | ||
| 46 | position p1 != withtest.p; | ||
| 47 | position p2; | ||
| 48 | statement S; | ||
| 49 | position any withtest.p; | ||
| 50 | identifier f; | ||
| 51 | @@ | ||
| 52 | |||
| 53 | x@p1 = \(kmalloc\|kzalloc\|kcalloc\)(...); | ||
| 54 | ... | ||
| 55 | x1@p = f@p2(...); | ||
| 56 | if (!x1) S | ||
| 57 | |||
| 58 | @script:python depends on org@ | ||
| 59 | p1 << rfixed.p1; | ||
| 60 | p2 << rfixed.p2; | ||
| 61 | @@ | ||
| 62 | |||
| 63 | cocci.print_main("alloc call",p1) | ||
| 64 | cocci.print_secs("possible model",p2) | ||
| 65 | |||
| 66 | @script:python depends on report@ | ||
| 67 | p1 << rfixed.p1; | ||
| 68 | p2 << rfixed.p2; | ||
| 69 | @@ | ||
| 70 | |||
| 71 | msg = "alloc with no test, possible model on line %s" % (p2[0].line) | ||
| 72 | coccilib.report.print_report(p1[0],msg) | ||
diff --git a/scripts/coccinelle/tests/doublebitand.cocci b/scripts/coccinelle/tests/doublebitand.cocci new file mode 100644 index 000000000000..9ba73d05a77e --- /dev/null +++ b/scripts/coccinelle/tests/doublebitand.cocci | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | /// Find bit operations that include the same argument more than once | ||
| 2 | //# One source of false positives is when the argument performs a side | ||
| 3 | //# effect. Another source of false positives is when a neutral value | ||
| 4 | //# such as 0 for | is used to indicate no information, to maintain the | ||
| 5 | //# same structure as other similar expressions | ||
| 6 | /// | ||
| 7 | // Confidence: Moderate | ||
| 8 | // Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. | ||
| 9 | // Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. | ||
| 10 | // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. | ||
| 11 | // URL: http://coccinelle.lip6.fr/ | ||
| 12 | // Comments: | ||
| 13 | // Options: -no_includes -include_headers | ||
| 14 | |||
| 15 | virtual context | ||
| 16 | virtual org | ||
| 17 | virtual report | ||
| 18 | |||
| 19 | @r expression@ | ||
| 20 | expression E; | ||
| 21 | position p; | ||
| 22 | @@ | ||
| 23 | |||
| 24 | ( | ||
| 25 | * E@p | ||
| 26 | & ... & E | ||
| 27 | | | ||
| 28 | * E@p | ||
| 29 | | ... | E | ||
| 30 | | | ||
| 31 | * E@p | ||
| 32 | & ... & !E | ||
| 33 | | | ||
| 34 | * E@p | ||
| 35 | | ... | !E | ||
| 36 | | | ||
| 37 | * !E@p | ||
| 38 | & ... & E | ||
| 39 | | | ||
| 40 | * !E@p | ||
| 41 | | ... | E | ||
| 42 | ) | ||
| 43 | |||
| 44 | @script:python depends on org@ | ||
| 45 | p << r.p; | ||
| 46 | @@ | ||
| 47 | |||
| 48 | cocci.print_main("duplicated argument to & or |",p) | ||
| 49 | |||
| 50 | @script:python depends on report@ | ||
| 51 | p << r.p; | ||
| 52 | @@ | ||
| 53 | |||
| 54 | coccilib.report.print_report(p[0],"duplicated argument to & or |") | ||
diff --git a/scripts/coccinelle/tests/doubletest.cocci b/scripts/coccinelle/tests/doubletest.cocci new file mode 100644 index 000000000000..13a2c0e8a4bf --- /dev/null +++ b/scripts/coccinelle/tests/doubletest.cocci | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | /// Find &&/|| operations that include the same argument more than once | ||
| 2 | //# A common source of false positives is when the argument performs a side | ||
| 3 | //# effect. | ||
| 4 | /// | ||
| 5 | // Confidence: Moderate | ||
| 6 | // Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2. | ||
| 7 | // Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2. | ||
| 8 | // Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2. | ||
| 9 | // URL: http://coccinelle.lip6.fr/ | ||
| 10 | // Comments: | ||
| 11 | // Options: -no_includes -include_headers | ||
| 12 | |||
| 13 | virtual context | ||
| 14 | virtual org | ||
| 15 | virtual report | ||
| 16 | |||
| 17 | @r expression@ | ||
| 18 | expression E; | ||
| 19 | position p; | ||
| 20 | @@ | ||
| 21 | |||
| 22 | ( | ||
| 23 | * E@p | ||
| 24 | || ... || E | ||
| 25 | | | ||
| 26 | * E@p | ||
| 27 | && ... && E | ||
| 28 | ) | ||
| 29 | |||
| 30 | @script:python depends on org@ | ||
| 31 | p << r.p; | ||
| 32 | @@ | ||
| 33 | |||
| 34 | cocci.print_main("duplicated argument to && or ||",p) | ||
| 35 | |||
| 36 | @script:python depends on report@ | ||
| 37 | p << r.p; | ||
| 38 | @@ | ||
| 39 | |||
| 40 | coccilib.report.print_report(p[0],"duplicated argument to && or ||") | ||
