1 // ****************************************************************************
3 // ****************************************************************************
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:
11 // - optional_qualifier
13 // See parse_cocci.ml, pattern.ml, transformation.ml.
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
20 // iso2 = i++ <=> i=i+1;
24 // in C we have i=1+i;
26 // Does the SP matches the C ?
27 // - Yes if iso2 precedes iso1 in this file,
31 // ****************************************************************************
32 // Standard C isomorphisms
33 // ****************************************************************************
35 // ---------------------------------------------------------------------------
36 // Spacing (include comments) isomorphisms
37 // ---------------------------------------------------------------------------
38 // They are handled at lex time.
40 // ---------------------------------------------------------------------------
41 // Dataflow isomorphisms (copy propagation, assignments)
42 // ---------------------------------------------------------------------------
43 // They are handled in engine (TODO).
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.
53 // chip = (ak4117_t *)snd_magic_kcalloc(ak4117_t, 0, GFP_KERNEL);
55 // X = snd_magic_kcalloc(T, 0, C)
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)
66 // in the following, the space at the beginning of the line is very important!
77 unsigned => unsigned int
85 // ---------------------------------------------------------------------------
87 // ---------------------------------------------------------------------------
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.
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
127 // ---------------------------------------------------------------------------
128 // Typedef isomorphisms
129 // ---------------------------------------------------------------------------
130 // They are handled in engine.
133 // ---------------------------------------------------------------------------
134 // Boolean isomorphisms
135 // ---------------------------------------------------------------------------
137 // the space at the beginning of the line is very important!
144 // the space at the beginning of the line is very important!
155 X == 0 <=> 0 == X => !X
161 X != 0 <=> 0 != X => X
175 // only if side effect free in theory, perhaps makes no sense
189 // ---------------------------------------------------------------------------
190 // Arithmetic isomorphisms
191 // ---------------------------------------------------------------------------
192 //todo: require check side-effect free expression
201 // needed in kcalloc CE, where have a -kzalloc(c * sizeof(T), E)
212 // note space before (
213 (X + Y) + Z <=> X + Y + Z
220 (X - Y) - Z <=> X - Y - Z
223 @ plus_minus_assoc1 @
227 (X + Y) - Z <=> X + Y - Z
230 @ plus_minus_assoc2 @
234 (X - Y) + Z <=> X - Y + Z
241 (X * Y) * Z <=> X * Y * Z
248 (X / Y) / Z <=> X / Y / Z
255 (X * Y) / Z <=> X * Y / Z
262 (X / Y) * Z <=> X / Y * Z
264 // ---------------------------------------------------------------------------
265 // Relational isomorphisms
266 // ---------------------------------------------------------------------------
274 // ---------------------------------------------------------------------------
275 // Increment isomorphisms
276 // ---------------------------------------------------------------------------
278 // equivalences between i++, +=1, etc.
279 // note: there is an addition in this SP.
284 i++; <=> ++i; <=> i+=1; <=> i=i+1;
286 // I would like to avoid the following rule, but we cant transform a ++i
287 // in i++ everywhere. We can do it only when the instruction is alone,
288 // such as when there is not stuff around it (not as in x = i++) That's why in
289 // the previous iso, we have explicitely force the i++ do be alone with
290 // the ';'. But unfortunately in the last expression of the for there is
291 // no ';' so the previous rule cannot be applied, hence this special
300 for(X;Y;i++) S <=> for(X;Y;++i) S
303 // ---------------------------------------------------------------------------
304 // Pointer isomorphisms
305 // ---------------------------------------------------------------------------
307 // the space at the beginning of the line is very important!
314 // the space at the beginning of the line is very important!
325 X == NULL <=> NULL == X => !X
331 X != NULL <=> NULL != X
339 // pointer arithmetic equivalences
341 // ---------------------------------------------------------------------------
342 // Statement isomorphisms
343 // ---------------------------------------------------------------------------
354 if (X) S1 else S2 => if (X != 0) S1 else S2 <=> if (0 != X) S1 else S2
361 if (X) S => if (X != 0) S <=> if (0 != X) S
368 if (X) S1 else S2 => if (X != NULL) S1 else S2 => if (NULL != X) S1 else S2
375 if (X) S => if (X != NULL) S <=> if (NULL != X) S
377 // ---------------------------------------------------------------------------
378 // Value isomorphisms
379 // ---------------------------------------------------------------------------
381 // There is also equal_c_int in cocci_vs_c to dealing with other
382 // integer decimal/hexadecimal isomorphisms.
383 // an argexpression applies only at top level, in the argument of a
384 // function call, or on the right-hand side of an assignment
386 @ zero_multiple_format @
390 // ****************************************************************************
391 // gcc specific isomorphisms
392 // ****************************************************************************
394 // likely and unlikely are used to give hints to gcc to improve performance.
410 // ****************************************************************************
411 // if structure isomorphisms
412 // ****************************************************************************
414 // these after after the above so that the introduced negation will distribute
415 // properly over the argument to likely/unlikely
422 if (X) S1 else S2 => if (!X) S2 else S1
431 if (E) S1 else S2 => if (E) S1
435 expression E1, E2, E3;
438 E1 ? E2 : E3 => !E1 ? E3 : E2
441 // if (X) Y else Z <=> X ? Y : Z sometimes.
447 // ---------------------------------------------------------------------------
448 // Optional initializers
449 // ---------------------------------------------------------------------------
450 // this is not safe when the declaration is replaced
451 // attempt to indicate that by requiring that Z is context
452 // no optional static/extern for isos
456 context identifier Z;
471 context identifier Z;
473 extern T Z; => extern T Z = ...;
476 @ const_extern_decl_init @
481 extern T Z; => extern T Z = C;
486 context identifier Z;
488 static T Z; => static T Z = ...;
491 @ const_static_decl_init @
496 static T Z; => static T Z = C;
498 // ---------------------------------------------------------------------------
499 // Branch (or compound) isomorphisms
500 // ---------------------------------------------------------------------------
501 // maybe a cocci patch should require something that looks like what is on
502 // the left above to occur in a if or while
504 // could worry that this has to be a simple statement, but this should work
505 // better as it allows + code on S
533 return ...; => return;
536 // ---------------------------------------------------------------------------
537 // Declaration isomorphisms
538 // ---------------------------------------------------------------------------
539 // They are handled in engine (TODO)
541 // int i,j,k; <=> int i; int j; int k;
544 // ---------------------------------------------------------------------------
545 // Affectation/initialisation isomorphism
546 // ---------------------------------------------------------------------------
547 // They are handled in engine.
548 // 'X = Y' should also match 'type X = Y';
550 // ---------------------------------------------------------------------------
551 // Parenthesis isomorphisms
552 // ---------------------------------------------------------------------------
554 //@@ expression E; @@
558 // todo: isomorphism avec les () around ? cf sizeof 3.
559 // (E) => E with some conditions.
568 // ---------------------------------------------------------------------------
569 // Pointer/Array isomorphisms
570 // ---------------------------------------------------------------------------
572 // pointer arithmetic equivalences
575 // ---------------------------------------------------------------------------
576 // Pointer/Field isomorphisms
577 // ---------------------------------------------------------------------------
581 expression E1, E2; // was pure, not sure why that's needed, not good for rule27
585 E1->fld => E1[E2].fld
598 E.fld = E1; => T I = { .fld = E1, };
600 // ---------------------------------------------------------------------------
601 // more pointer field iso
602 // ---------------------------------------------------------------------------
604 // pure means that either the whole field reference expression is dropped,
605 // or E is context code and has no attached + code
606 // not really... pure means matches a unitary unplussed metavariable
607 // but this rule doesn't work anyway
620 // ---------------------------------------------------------------------------
621 // sizeof isomorphisms
622 // ---------------------------------------------------------------------------
624 // The following is made redundant by the paren isomorphism
630 // sizeof(E) => sizeof E
635 pure type T; // pure because we drop a metavar
639 sizeof(T) => sizeof(E)
643 // expression list ES;
647 // E.fld(ES) <=> (*E.fld)(ES)
650 // ****************************************************************************
651 // Linux specific isomorphisms
652 // ****************************************************************************
654 // Examples: many functions are equivalent/related, and one SP modifying
655 // such a function should also modify the equivalent/related one.
658 // ---------------------------------------------------------------------------
659 // in rule18, needed ?
660 // ---------------------------------------------------------------------------
662 // - test_and_set_bit(ev, &bcs->event);
664 // - set_bit(ev, &bcs->event);
666 // - bcs->event |= 1 << ev; // the only case that is used
669 // ****************************************************************************
670 // Everything that is required to be in last position, for ugly reasons ...
671 // ****************************************************************************