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 // ---------------------------------------------------------------------------
280 // ---------------------------------------------------------------------------
281 // Increment isomorphisms
282 // ---------------------------------------------------------------------------
284 // equivalences between i++, +=1, etc.
285 // note: there is an addition in this SP.
290 i++; <=> ++i; <=> i+=1; <=> i=i+1;
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
306 for(X;Y;i++) S <=> for(X;Y;++i) S
309 // ---------------------------------------------------------------------------
310 // Pointer isomorphisms
311 // ---------------------------------------------------------------------------
313 // the space at the beginning of the line is very important!
320 // the space at the beginning of the line is very important!
331 X == NULL <=> NULL == X => !X
337 X != NULL <=> NULL != X
345 // pointer arithmetic equivalences
347 // ---------------------------------------------------------------------------
348 // Statement isomorphisms
349 // ---------------------------------------------------------------------------
360 if (X) S1 else S2 => if (X != 0) S1 else S2 <=> if (0 != X) S1 else S2
367 if (X) S => if (X != 0) S <=> if (0 != X) S
374 if (X) S1 else S2 => if (X != NULL) S1 else S2 => if (NULL != X) S1 else S2
381 if (X) S => if (X != NULL) S <=> if (NULL != X) S
383 // ---------------------------------------------------------------------------
384 // Value isomorphisms
385 // ---------------------------------------------------------------------------
387 // There is also equal_c_int in cocci_vs_c to dealing with other
388 // integer decimal/hexadecimal isomorphisms.
389 // an argexpression applies only at top level, in the argument of a
390 // function call, or on the right-hand side of an assignment
392 @ zero_multiple_format @
396 // ****************************************************************************
397 // gcc specific isomorphisms
398 // ****************************************************************************
400 // likely and unlikely are used to give hints to gcc to improve performance.
416 // ****************************************************************************
417 // if structure isomorphisms
418 // ****************************************************************************
420 // these after after the above so that the introduced negation will distribute
421 // properly over the argument to likely/unlikely
428 if (X) S1 else S2 => if (!X) S2 else S1
437 if (E) S1 else S2 => if (E) S1
441 expression E1, E2, E3;
444 E1 ? E2 : E3 => !E1 ? E3 : E2
447 // if (X) Y else Z <=> X ? Y : Z sometimes.
453 // ---------------------------------------------------------------------------
454 // Optional initializers
455 // ---------------------------------------------------------------------------
456 // this is not safe when the declaration is replaced
457 // attempt to indicate that by requiring that Z is context
458 // no optional static/extern for isos
462 context identifier Z;
477 context identifier Z;
479 extern T Z; => extern T Z = ...;
482 @ const_extern_decl_init @
487 extern T Z; => extern T Z = C;
492 context identifier Z;
494 static T Z; => static T Z = ...;
497 @ const_static_decl_init @
502 static T Z; => static T Z = C;
504 // ---------------------------------------------------------------------------
505 // Branch (or compound) isomorphisms
506 // ---------------------------------------------------------------------------
507 // maybe a cocci patch should require something that looks like what is on
508 // the left above to occur in a if or while
510 // could worry that this has to be a simple statement, but this should work
511 // better as it allows + code on S
539 return ...; => return;
542 // ---------------------------------------------------------------------------
543 // Declaration isomorphisms
544 // ---------------------------------------------------------------------------
545 // They are handled in engine (TODO)
547 // int i,j,k; <=> int i; int j; int k;
550 // ---------------------------------------------------------------------------
551 // Affectation/initialisation isomorphism
552 // ---------------------------------------------------------------------------
553 // They are handled in engine.
554 // 'X = Y' should also match 'type X = Y';
556 // ---------------------------------------------------------------------------
557 // Parenthesis isomorphisms
558 // ---------------------------------------------------------------------------
560 //@@ expression E; @@
564 // todo: isomorphism avec les () around ? cf sizeof 3.
565 // (E) => E with some conditions.
574 // ---------------------------------------------------------------------------
575 // Pointer/Array isomorphisms
576 // ---------------------------------------------------------------------------
578 // pointer arithmetic equivalences
581 // ---------------------------------------------------------------------------
582 // Pointer/Field isomorphisms
583 // ---------------------------------------------------------------------------
587 expression E1, E2; // was pure, not sure why that's needed, not good for rule27
591 E1->fld => E1[E2].fld
604 E.fld = E1; => T I = { .fld = E1, };
606 // ---------------------------------------------------------------------------
607 // more pointer field iso
608 // ---------------------------------------------------------------------------
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
626 // ---------------------------------------------------------------------------
627 // sizeof isomorphisms
628 // ---------------------------------------------------------------------------
630 // The following is made redundant by the paren isomorphism
636 // sizeof(E) => sizeof E
641 pure type T; // pure because we drop a metavar
645 sizeof(T) => sizeof(E)
649 // expression list ES;
653 // E.fld(ES) <=> (*E.fld)(ES)
656 // ****************************************************************************
657 // Linux specific isomorphisms
658 // ****************************************************************************
660 // Examples: many functions are equivalent/related, and one SP modifying
661 // such a function should also modify the equivalent/related one.
664 // ---------------------------------------------------------------------------
665 // in rule18, needed ?
666 // ---------------------------------------------------------------------------
668 // - test_and_set_bit(ev, &bcs->event);
670 // - set_bit(ev, &bcs->event);
672 // - bcs->event |= 1 << ev; // the only case that is used
675 // ****************************************************************************
676 // Everything that is required to be in last position, for ugly reasons ...
677 // ****************************************************************************