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 for int and pointer types
135 // ---------------------------------------------------------------------------
137 // the space at the beginning of the line is very important!
150 // the space at the beginning of the line is very important!
163 // ---------------------------------------------------------------------------
164 // Boolean isomorphisms
165 // ---------------------------------------------------------------------------
189 // X should be a test expression, but X!=0 doesn't have to be one
190 // not nice at all... ToTestExpression sets everything after the first
191 // pattern in the iso rule to be TestExpression
210 // ---------------------------------------------------------------------------
212 // ---------------------------------------------------------------------------
226 // only if side effect free in theory, perhaps makes no sense
240 // ---------------------------------------------------------------------------
241 // Arithmetic isomorphisms
242 // ---------------------------------------------------------------------------
243 //todo: require check side-effect free expression
252 // needed in kcalloc CE, where have a -kzalloc(c * sizeof(T), E)
263 // note space before (
264 (X + Y) + Z <=> X + Y + Z
271 (X - Y) - Z <=> X - Y - Z
274 @ plus_minus_assoc1 @
278 (X + Y) - Z <=> X + Y - Z
281 @ plus_minus_assoc2 @
285 (X - Y) + Z <=> X - Y + Z
292 (X * Y) * Z <=> X * Y * Z
299 (X / Y) / Z <=> X / Y / Z
306 (X * Y) / Z <=> X * Y / Z
313 (X / Y) * Z <=> X / Y * Z
315 // ---------------------------------------------------------------------------
316 // Relational isomorphisms
317 // ---------------------------------------------------------------------------
331 // ---------------------------------------------------------------------------
332 // Increment isomorphisms
333 // ---------------------------------------------------------------------------
335 // equivalences between i++, +=1, etc.
336 // note: there is an addition in this SP.
341 i++; <=> ++i; <=> i+=1; <=> i=i+1;
343 // I would like to avoid the following rule, but we cant transform a ++i
344 // in i++ everywhere. We can do it only when the instruction is alone,
345 // such as when there is not stuff around it (not as in x = i++) That's why in
346 // the previous iso, we have explicitely force the i++ do be alone with
347 // the ';'. But unfortunately in the last expression of the for there is
348 // no ';' so the previous rule cannot be applied, hence this special
357 for(X;Y;i++) S <=> for(X;Y;++i) S
359 // ****************************************************************************
360 // gcc specific isomorphisms
361 // ****************************************************************************
363 // likely and unlikely are used to give hints to gcc to improve performance.
370 unlikely(E) <=> likely(E) => E
372 // ---------------------------------------------------------------------------
373 // Parenthesis isomorphisms
374 // ---------------------------------------------------------------------------
376 //@@ expression E; @@
380 // todo: isomorphism avec les () around ? cf sizeof 3.
381 // (E) => E with some conditions.
390 // ---------------------------------------------------------------------------
391 // Statement isomorphisms
392 // ---------------------------------------------------------------------------
394 // ---------------------------------------------------------------------------
395 // Value isomorphisms
396 // ---------------------------------------------------------------------------
398 // There is also equal_c_int in cocci_vs_c to dealing with other
399 // integer decimal/hexadecimal isomorphisms.
400 // an argexpression applies only at top level, in the argument of a
401 // function call, or on the right-hand side of an assignment
403 @ zero_multiple_format @
411 // ****************************************************************************
412 // if structure isomorphisms
413 // ****************************************************************************
415 // these are after the above so that the introduced negation will distribute
416 // properly over the argument to likely/unlikely
423 if (X) S1 else S2 => if (!X) S2 else S1
430 if (E1 != E2) S1 else S2 => if (E1 == E2) S2 else S1
439 if (E) S1 else S2 => if (E) S1
443 expression E1, E2, E3;
446 E1 ? E2 : E3 => !E1 ? E3 : E2
449 // if (X) Y else Z <=> X ? Y : Z sometimes.
455 // ---------------------------------------------------------------------------
456 // Optional initializers
457 // ---------------------------------------------------------------------------
458 // this is not safe when the declaration is replaced
459 // attempt to indicate that by requiring that Z is context
460 // no optional static/extern for isos
464 context identifier Z;
479 context identifier Z;
481 extern T Z; => extern T Z = ...;
484 @ const_extern_decl_init @
489 extern T Z; => extern T Z = C;
494 context identifier Z;
496 static T Z; => static T Z = ...;
499 @ const_static_decl_init @
504 static T Z; => static T Z = C;
506 // ---------------------------------------------------------------------------
507 // Branch (or compound) isomorphisms
508 // ---------------------------------------------------------------------------
509 // maybe a cocci patch should require something that looks like what is on
510 // the left above to occur in a if or while
512 // could worry that this has to be a simple statement, but this should work
513 // better as it allows + code on S
541 return ...; => return;
544 // ---------------------------------------------------------------------------
545 // Declaration isomorphisms
546 // ---------------------------------------------------------------------------
547 // They are handled in engine (TODO)
549 // int i,j,k; <=> int i; int j; int k;
552 // ---------------------------------------------------------------------------
553 // Affectation/initialisation isomorphism
554 // ---------------------------------------------------------------------------
555 // They are handled in engine.
556 // 'X = Y' should also match 'type X = Y';
558 // ---------------------------------------------------------------------------
559 // Pointer/Array isomorphisms
560 // ---------------------------------------------------------------------------
562 // pointer arithmetic equivalences
565 // ---------------------------------------------------------------------------
566 // Pointer/Field isomorphisms
567 // ---------------------------------------------------------------------------
571 expression E1, E2; // was pure, not sure why that's needed, not good for rule27
575 E1->fld => E1[E2].fld
588 E.fld = E1; => T I = { .fld = E1, };
590 // ---------------------------------------------------------------------------
591 // more pointer field iso
592 // ---------------------------------------------------------------------------
594 // pure means that either the whole field reference expression is dropped,
595 // or E is context code and has no attached + code
596 // not really... pure means matches a unitary unplussed metavariable
597 // but this rule doesn't work anyway
610 // ---------------------------------------------------------------------------
611 // sizeof isomorphisms
612 // ---------------------------------------------------------------------------
614 // The following is made redundant by the paren isomorphism
620 // sizeof(E) => sizeof E
625 pure type T; // pure because we drop a metavar
629 sizeof(T) => sizeof(E)
633 // expression list ES;
637 // E.fld(ES) <=> (*E.fld)(ES)
640 // ****************************************************************************
641 // Linux specific isomorphisms
642 // ****************************************************************************
644 // Examples: many functions are equivalent/related, and one SP modifying
645 // such a function should also modify the equivalent/related one.
648 // ---------------------------------------------------------------------------
649 // in rule18, needed ?
650 // ---------------------------------------------------------------------------
652 // - test_and_set_bit(ev, &bcs->event);
654 // - set_bit(ev, &bcs->event);
656 // - bcs->event |= 1 << ev; // the only case that is used
659 // ****************************************************************************
660 // Everything that is required to be in last position, for ugly reasons ...
661 // ****************************************************************************