0

I am trying to analyze a C source code using Eva plugin of Frama-C.

In the following example, I found that Eva can calculate the value of a shift expression in which the right-hand-side value is big, but cannot calculate when the right-hand-side value is small.

extern unsigned char a;
int main() {
    int b, c, d;
    b = (a >> 15) & 1;

    c = (a >> 0) & 1;

    d = b + c;
}

In this example above, Eva can calculate the value of b but not c. Is (a >> 0) & 1 more complex than (a >> 15) & 1 to Eva?

Thuy Nguyen
  • 353
  • 2
  • 10
  • it's definitely not more complicated, shifting by 0 is the same as keeping the original value, maybe a bug in their implementation? – xception Jul 01 '19 at 06:23
  • 4
    Can you add examples for a, b, c, that show that it is not working? I.e., for some `a`, what are the values `b` and `c` and what would you expect instead? Also, what are the types of `a`, `b` and `c`? I have been using these sorts of shifts for many years in C and never hit a problem. – Daniel Junglas Jul 01 '19 at 06:28
  • 2
    I concur with @DanielJunglas' comment: without more context, especially the computed value of `a`, it is difficult to say anything meaningful. A possible explanation would be that `a` is in an interval that guarantees that all its most significant bits are `0`, so that the right shift will trivially evaluate to `0`. On the other hand, as soon as the set of values associated to `a` contains at least one odd and one even number, `c` will evaluate to either `0` or `1`. But again, this all depends on the interval computed for `a` in the first place, as well as the types of `a`, `b` and `c`. – Virgile Jul 01 '19 at 06:54
  • DanielJunglas, Virgile: You are right. I checked my source code again, the type of a is uint8. That why the bit 15 is obviously 0. – Thuy Nguyen Jul 02 '19 at 05:26
  • @ThuyNguyen if you fix the value of `a` to a singleton, like in the actual revision, then Eva will have no trouble evaluating `c` to `1` as well, except from the fact that `uint8` is not a standard C type. At best you can find `uint8_t` if you `#include ` and that the code fragment is still not parsable as it lacks the declarations for `b`, `c` and `d`. Please consider proposing a [mcve](https://stackoverflow.com/help/mcve). Currently, the question is quite confusing. – Virgile Jul 02 '19 at 16:48
  • @Virgile sorry for the confusion. I edit the question with a reproducible example. In which `a` is an `extern` variable and its value hasn't been initialized yet. – Thuy Nguyen Jul 05 '19 at 04:02
  • Thanks for the update. In your revised example, the situation is indeed as I described in my first comment. I'll expand that as an answer. – Virgile Jul 05 '19 at 06:50

1 Answers1

0

Eva is giving the most precise answer from the initial context where a, an external variable, is in the range [0..255], namely that b is equal to 0 and c may be either 0 or 1.

If you want to explore what is going on, the Values panel at the bottom of of the graphical user interface (launched with frama-c-gui -eva file.c) is the way to go. Its usage is documented in section 4.3 of the Eva user manual, but basically if you click on any (sub)-expression in the normalized code view (the left buffer), the abstract value computed by Eva for this expression at this point will be displayed in the panel.

In your example, we have the following intermediate values for the computation of b:

  • a -> [0..255]
  • (int)a -> [0..255] (implicit promotion of an arithmetic operand)
  • (int)a >> 15 -> {0} (only the first 8 bits might be non 0)
  • (int)a >> 15 & 1 -> {0} (first argument is 0, the bitwise and is also 0}

For c, the first two steps are identical, but then we have

  • (int)a >> 0 -> [0..255] (no-op, we have the same values as (int)a)
  • ((int)a >> 0) & 1 -> {0; 1} (in the interval [0..255], we have odd and even values, hence the result of the bitwise and can be either 0 or 1).
Virgile
  • 9,724
  • 18
  • 42