Release coccinelle-0.2.0
[bpt/coccinelle.git] / standard.iso
CommitLineData
34e49164
C
1// ****************************************************************************
2// Prelude
3// ****************************************************************************
4
5// Note: some isomorphisms are handled in the engine directly because they
6// require special support. They can not be easily described with a
7// XX <=> YY. But some of them have names, so they can be disabled, as for
8// any other isomorphism rule. That also means that those names can not
9// be used for regular isomorphism rule. Those reserved rule names are:
10// - optional_storage
11// - optional_qualifier
12// - value_format
13// See parse_cocci.ml, pattern.ml, transformation.ml.
14
15
16// Note: the order of the rules has some importance. As we don't do a fixpoint,
17// changing the order may impact the result. For instance, if we have
18//
19// iso1 = x+y <=> y+x
20// iso2 = i++ <=> i=i+1;
21//
22// and if
23// in SP we have i++;
24// in C we have i=1+i;
25//
26// Does the SP matches the C ?
27// - Yes if iso2 precedes iso1 in this file,
28// - No otherwise.
29
30
31// ****************************************************************************
32// Standard C isomorphisms
33// ****************************************************************************
34
35// ---------------------------------------------------------------------------
36// Spacing (include comments) isomorphisms
37// ---------------------------------------------------------------------------
38// They are handled at lex time.
39
40// ---------------------------------------------------------------------------
41// Dataflow isomorphisms (copy propagation, assignments)
42// ---------------------------------------------------------------------------
43// They are handled in engine (TODO).
44
45
46// ---------------------------------------------------------------------------
47// Iso-by-absence (optional qualifier, storage, sign, cast) isomorphisms
48// ---------------------------------------------------------------------------
49// Some of them are handled in cocci_vs_c. Some of them handled here.
50
51
52// We would like that
53// chip = (ak4117_t *)snd_magic_kcalloc(ak4117_t, 0, GFP_KERNEL);
54// also matches
55// X = snd_magic_kcalloc(T, 0, C)
56//
57// For the moment because the iso is (T) E => E and not <=>, it forces
58// us to rewrite the SP as X = (T) snd_magic_kcalloc(T, 0, C)
59
60Expression
61@ drop_cast @
62expression E;
63pure type T;
64@@
65
66// in the following, the space at the beginning of the line is very important!
67 (T)E => E
68
69Type
70@ add_signed @
71@@
72int => signed int
73
74Type
75@ add_int1 @
76@@
77unsigned => unsigned int
78
79Type
80@ add_int2 @
81@@
82signed => signed int
83
84
85// ---------------------------------------------------------------------------
86// Field isomorphisms
87// ---------------------------------------------------------------------------
88// Dereferences
89
90
91// Those iso were introduced for the 'generic program matching' paper,
92// with sgrep. The idea is that when we want to detect bugs,
93// we want to detect something like free(X) ... *X
94// meaning that you try to access something that have been freed.
95// But *X is not the only way to deference X, there is also
96// X->fld, hence those iso.
97
98// The following don't see like a good idea, because eg fld could be
99// instantiated in different ways in different places, meaning that the
100// two occurrences of "*E" would not refer to the same thing at all.
101// This could be addressed by making E pure, but then I think it would
102// have no purpose.
103
104// Expression
105// @@
106// expression E;
107// identifier fld;
108// @@
109//
110// *E => E->fld
111//
112// Expression
113// @@
114// expression E;
115// identifier fld;
116// @@
117//
118// *E => (E)->fld
119//
120// Expression
121// @@
122// expression E,E1;
123// @@
124//
125// *E => E[E1]
126
127// ---------------------------------------------------------------------------
128// Typedef isomorphisms
129// ---------------------------------------------------------------------------
130// They are handled in engine.
131
132
133// ---------------------------------------------------------------------------
134// Boolean isomorphisms
135// ---------------------------------------------------------------------------
136
137// the space at the beginning of the line is very important!
138Expression
139@ not_int1 @
140int X;
141@@
142 !X => 0 == X
143
144// the space at the beginning of the line is very important!
145Expression
146@ not_int2 @
147int X;
148@@
149 !X => X == 0
150
151Expression
152@ is_zero @
153expression X;
154@@
155X == 0 <=> 0 == X => !X
156
157Expression
158@ isnt_zero @
159expression X;
160@@
161X != 0 <=> 0 != X => X
162
163Expression
164@ bitor_comm @
165expression X,Y;
166@@
167X | Y => Y | X
168
169Expression
170@ bitand_comm @
171expression X,Y;
172@@
173X & Y => Y & X
174
faf9a90c
C
175// only if side effect free in theory, perhaps makes no sense
176// Expression
177// @ and_comm @
178// expression X,Y;
179// @@
180// X && Y => Y && X
34e49164 181
faf9a90c
C
182// Expression
183// @ or_comm @
184// expression X,Y;
185// @@
186// X || Y => Y || X
34e49164
C
187
188
189// ---------------------------------------------------------------------------
190// Arithmetic isomorphisms
191// ---------------------------------------------------------------------------
192//todo: require check side-effect free expression
193
194Expression
195@ plus_comm @
196expression X, Y;
197@@
198X + Y => Y + X
199
200
201// needed in kcalloc CE, where have a -kzalloc(c * sizeof(T), E)
202Expression
203@ mult_comm @
204expression X, Y;
205@@
206X * Y => Y * X
207
208Expression
209@ plus_assoc @
210expression X, Y, Z;
211@@
212 // note space before (
213 (X + Y) + Z <=> X + Y + Z
214
215Expression
216@ minus_assoc @
217expression X, Y, Z;
218@@
219
220 (X - Y) - Z <=> X - Y - Z
221
222Expression
223@ plus_minus_assoc1 @
224expression X, Y, Z;
225@@
226
227 (X + Y) - Z <=> X + Y - Z
228
229Expression
230@ plus_minus_assoc2 @
231expression X, Y, Z;
232@@
233
234 (X - Y) + Z <=> X - Y + Z
235
236Expression
237@ times_assoc @
238expression X, Y, Z;
239@@
240
241 (X * Y) * Z <=> X * Y * Z
242
243Expression
244@ div_assoc @
245expression X, Y, Z;
246@@
247
248 (X / Y) / Z <=> X / Y / Z
249
250Expression
251@ times_div_assoc1 @
252expression X, Y, Z;
253@@
254
255 (X * Y) / Z <=> X * Y / Z
256
257Expression
258@ times_div_assoc2 @
259expression X, Y, Z;
260@@
261
262 (X / Y) * Z <=> X / Y * Z
263
264// ---------------------------------------------------------------------------
265// Relational isomorphisms
266// ---------------------------------------------------------------------------
267
268Expression
269@ gtr_lss @
270expression X, Y;
271@@
272X < Y <=> Y > X
273
708f4980
C
274Expression
275@ gtr_lss_eq @
276expression X, Y;
277@@
278X <= Y <=> Y >= X
279
34e49164
C
280// ---------------------------------------------------------------------------
281// Increment isomorphisms
282// ---------------------------------------------------------------------------
283
284// equivalences between i++, +=1, etc.
285// note: there is an addition in this SP.
286Statement
287@ inc @
288identifier i;
289@@
290i++; <=> ++i; <=> i+=1; <=> i=i+1;
291
292// I would like to avoid the following rule, but we cant transform a ++i
293// in i++ everywhere. We can do it only when the instruction is alone,
294// such as when there is not stuff around it (not as in x = i++) That's why in
295// the previous iso, we have explicitely force the i++ do be alone with
296// the ';'. But unfortunately in the last expression of the for there is
297// no ';' so the previous rule cannot be applied, hence this special
298// case.
299
300Statement
301@ for_inc @
302expression X, Y;
303statement S;
304identifier i;
305@@
306for(X;Y;i++) S <=> for(X;Y;++i) S
307
308
7f004419
C
309// ****************************************************************************
310// gcc specific isomorphisms
311// ****************************************************************************
312
313// likely and unlikely are used to give hints to gcc to improve performance.
314
315Expression
9f8e26f4 316@ unlikely @
7f004419
C
317expression E;
318@@
319
320unlikely(E) <=> likely(E) => E
321
322// ---------------------------------------------------------------------------
323// Parenthesis isomorphisms
324// ---------------------------------------------------------------------------
325//Expression
326//@@ expression E; @@
327// E => (E)
328//// E => ((E))
329
330// todo: isomorphism avec les () around ? cf sizeof 3.
331// (E) => E with some conditions.
332
333Expression
334@ paren @
335expression E;
336@@
337
338 (E) => E
339
34e49164
C
340// ---------------------------------------------------------------------------
341// Pointer isomorphisms
342// ---------------------------------------------------------------------------
343
344// the space at the beginning of the line is very important!
345Expression
346@ not_ptr1 @
347expression *X;
348@@
349 !X => NULL == X
350
351// the space at the beginning of the line is very important!
352Expression
353@ not_ptr2 @
354expression *X;
355@@
356 !X => X == NULL
357
358Expression
359@ is_null @
360expression X;
361@@
362X == NULL <=> NULL == X => !X
363
364Expression
365@ isnt_null1 @
366expression X;
367@@
368X != NULL <=> NULL != X
369
370TestExpression
371@ isnt_null1 @
372expression X;
373@@
374NULL != X => X
375
376// pointer arithmetic equivalences
377
378// ---------------------------------------------------------------------------
379// Statement isomorphisms
380// ---------------------------------------------------------------------------
381
382// ----------------
383// If
384// ----------------
385
386Statement
387@ int_if_test1 @
388int X;
389statement S1, S2;
390@@
391if (X) S1 else S2 => if (X != 0) S1 else S2 <=> if (0 != X) S1 else S2
392
393Statement
394@ int_if_test2 @
395int X;
396statement S;
397@@
398if (X) S => if (X != 0) S <=> if (0 != X) S
399
400Statement
401@ ptr_if_test1 @
402expression *X;
403statement S1, S2;
404@@
405if (X) S1 else S2 => if (X != NULL) S1 else S2 => if (NULL != X) S1 else S2
406
407Statement
408@ ptr_if_test2 @
409expression *X;
410statement S;
411@@
412if (X) S => if (X != NULL) S <=> if (NULL != X) S
413
414// ---------------------------------------------------------------------------
415// Value isomorphisms
416// ---------------------------------------------------------------------------
417
418// There is also equal_c_int in cocci_vs_c to dealing with other
419// integer decimal/hexadecimal isomorphisms.
420// an argexpression applies only at top level, in the argument of a
421// function call, or on the right-hand side of an assignment
422ArgExpression
423@ zero_multiple_format @
424@@
425 0 => '\0'
426
34e49164
C
427// ****************************************************************************
428// if structure isomorphisms
429// ****************************************************************************
430
431// these after after the above so that the introduced negation will distribute
432// properly over the argument to likely/unlikely
433
434Statement
435@ neg_if @
436expression X;
437statement S1, S2;
438@@
439if (X) S1 else S2 => if (!X) S2 else S1
440
002099fc
C
441Statement
442@ ne_if @
443expression E1, E2;
444statement S1, S2;
445@@
446if (E1 != E2) S1 else S2 => if (E1 == E2) S2 else S1
447
34e49164
C
448Statement
449@ drop_else @
450expression E;
451statement S1;
452pure statement S2;
453@@
454
455if (E) S1 else S2 => if (E) S1
456
457Expression
458@ neg_if_exp @
459expression E1, E2, E3;
460@@
461
462E1 ? E2 : E3 => !E1 ? E3 : E2
463
464
465// if (X) Y else Z <=> X ? Y : Z sometimes.
466
467// ----------------
468// Loops
469// ----------------
470
471// ---------------------------------------------------------------------------
472// Optional initializers
473// ---------------------------------------------------------------------------
474// this is not safe when the declaration is replaced
475// attempt to indicate that by requiring that Z is context
476// no optional static/extern for isos
477Declaration
478@ decl_init @
479type T;
480context identifier Z;
481@@
482T Z; => T Z = ...;
483
484Declaration
485@ const_decl_init @
486type T;
487identifier Z;
488constant C;
489@@
490T Z; => T Z = C;
491
492Declaration
493@ extern_decl_init @
494type T;
495context identifier Z;
496@@
497extern T Z; => extern T Z = ...;
498
499Declaration
500@ const_extern_decl_init @
501type T;
502identifier Z;
503constant C;
504@@
505extern T Z; => extern T Z = C;
506
507Declaration
508@ static_decl_init @
509type T;
510context identifier Z;
511@@
512static T Z; => static T Z = ...;
513
514Declaration
515@ const_static_decl_init @
516type T;
517identifier Z;
518constant C;
519@@
520static T Z; => static T Z = C;
521
522// ---------------------------------------------------------------------------
523// Branch (or compound) isomorphisms
524// ---------------------------------------------------------------------------
525// maybe a cocci patch should require something that looks like what is on
526// the left above to occur in a if or while
527
528// could worry that this has to be a simple statement, but this should work
529// better as it allows + code on S
530Statement
531@ braces1 @
532statement S;
533@@
534{ ... S } => S
535
536Statement
537@ braces2 @
538statement S;
539@@
540{ ... S ... } => S
541
542Statement
543@ braces3 @
544statement S;
545@@
546{ S ... } => S
547
548Statement
549@ braces4 @
550statement S;
551@@
552{ S } => S
553
554Statement
555@ ret @
556@@
557return ...; => return;
558
559
560// ---------------------------------------------------------------------------
561// Declaration isomorphisms
562// ---------------------------------------------------------------------------
563// They are handled in engine (TODO)
564
565// int i,j,k; <=> int i; int j; int k;
566
567
568// ---------------------------------------------------------------------------
569// Affectation/initialisation isomorphism
570// ---------------------------------------------------------------------------
571// They are handled in engine.
572// 'X = Y' should also match 'type X = Y';
573
34e49164
C
574// ---------------------------------------------------------------------------
575// Pointer/Array isomorphisms
576// ---------------------------------------------------------------------------
577
578// pointer arithmetic equivalences
579// a + x <=> a[x]
580
581// ---------------------------------------------------------------------------
582// Pointer/Field isomorphisms
583// ---------------------------------------------------------------------------
584
585Expression
586@ ptr_to_array @
587expression E1, E2; // was pure, not sure why that's needed, not good for rule27
588identifier fld;
589@@
590
591E1->fld => E1[E2].fld
592
593
594
595TopLevel
596@ mkinit @
597type T;
598pure context T E;
599identifier I;
600identifier fld;
601expression E1;
602@@
603
604E.fld = E1; => T I = { .fld = E1, };
605
606// ---------------------------------------------------------------------------
607// more pointer field iso
608// ---------------------------------------------------------------------------
609
610// pure means that either the whole field reference expression is dropped,
611// or E is context code and has no attached + code
612// not really... pure means matches a unitary unplussed metavariable
613// but this rule doesn't work anyway
614
615Expression
616@ fld_to_ptr @
617type T;
618pure T E;
619pure T *E1;
620identifier fld;
621@@
622
623E.fld => E1->fld
624
625
626// ---------------------------------------------------------------------------
627// sizeof isomorphisms
628// ---------------------------------------------------------------------------
629
faf9a90c
C
630// The following is made redundant by the paren isomorphism
631// Expression
632// @ sizeof_parens @
633// expression E;
634// @@
34e49164 635
faf9a90c 636// sizeof(E) => sizeof E
34e49164
C
637
638
639Expression
640@ sizeof_type_expr @
641pure type T; // pure because we drop a metavar
642T E;
643@@
644
645sizeof(T) => sizeof(E)
646
485bce71
C
647// Expression
648// @ fld_func_call @
649// expression list ES;
650// identifier fld;
651// expression E;
652// @@
653// E.fld(ES) <=> (*E.fld)(ES)
654
34e49164
C
655
656// ****************************************************************************
657// Linux specific isomorphisms
658// ****************************************************************************
659
660// Examples: many functions are equivalent/related, and one SP modifying
661// such a function should also modify the equivalent/related one.
662
663
664// ---------------------------------------------------------------------------
665// in rule18, needed ?
666// ---------------------------------------------------------------------------
667// (
668// - test_and_set_bit(ev, &bcs->event);
669// |
670// - set_bit(ev, &bcs->event);
671// |
672// - bcs->event |= 1 << ev; // the only case that is used
673
674
675// ****************************************************************************
676// Everything that is required to be in last position, for ugly reasons ...
677// ****************************************************************************