TrustInSoft / tis-interpreter

An interpreter for finding subtle bugs in programs written in standard C
565 stars 28 forks source link

Wrong results: printf treats all enums as ints #111

Closed ch3root closed 8 years ago

ch3root commented 8 years ago

Source code:

#include <stdio.h>

int main()
{
  enum { e = 5000000000 } x = e;

  printf("%%d: %d\n", x);
  printf("%%ld: %ld\n", x);
}

tis-interpreter (31be1ffdb350ea940095be4757d0d5779c38f10b) output:

[value] Analyzing a complete application starting at main
[value] Computing initial state
[value] Initial state computed

%d: 5000000000

test.c:8:[value] warning: argument x has type enum __anonenum_x_1 but format indicates long
test.c:8:[value] warning: assert(match format and arguments)
                 stack: printf :: test.c:8 <- main
[value] done for function main

gcc (GCC) 7.0.0 20160616 (experimental):

$ gcc -std=c11 -pedantic -Wall -Wextra -O3 -fsanitize=undefined test.c && ./a.out
test.c: In function ‘main’:
test.c:5:14: warning: ISO C restricts enumerator values to range of ‘int’ [-Wpedantic]
   enum { e = 5000000000 } x = e;
              ^~~~~~~~~~
test.c:7:17: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long unsigned int’ [-Wformat=]
   printf("%%d: %d\n", x);
                 ^
%d: 705032704
%ld: 5000000000

clang version 3.9.0 (trunk 271312):

$ clang -std=c11 -Weverything -O3 -fsanitize=undefined test.c && ./a.out
test.c:5:10: warning: ISO C restricts enumerator values to range of 'int' (5000000000 is too large) [-Wpedantic]
  enum { e = 5000000000 } x = e;
         ^   ~~~~~~~~~~
test.c:7:23: warning: format specifies type 'int' but the argument has underlying type 'unsigned long' [-Wformat]
  printf("%%d: %d\n", x);
               ~~     ^
               %lu
2 warnings generated.
%d: 705032704
%ld: 5000000000
pascal-cuoq commented 8 years ago

enum treatment is a real mess. GCC rejects the following program (by @Aaylor), although it was not even trying to type the enum as int. Crazy!

enum { a = 0x7ffffffe, b, c } e;

int main(void) {
  return a;
}