formal c semantics compcert and the c standard
play

Formal C semantics: CompCert and the C standard Robbert Krebbers 1 - PowerPoint PPT Presentation

Formal C semantics: CompCert and the C standard Robbert Krebbers 1 Xavier Leroy 2 Freek Wiedijk 1 1 ICIS, Radboud University Nijmegen, The Netherlands 2 Inria Paris-Rocquencourt, France July 17, 2014 @ ITP, Vienna, Austria 1 Underspecification


  1. Formal C semantics: CompCert and the C standard Robbert Krebbers 1 Xavier Leroy 2 Freek Wiedijk 1 1 ICIS, Radboud University Nijmegen, The Netherlands 2 Inria Paris-Rocquencourt, France July 17, 2014 @ ITP, Vienna, Austria 1

  2. Underspecification in C ◮ Unspecified behavior : two or more behaviors are allowed For example: order of evaluation in expressions ◮ Implementation defined behavior : like unspecified behavior, but the compiler has to document its choice For example: size and endianness of integers ◮ Undefined behavior: the standard imposes no requirements at all, the program is even allowed to crash For example: dereferencing a NULL or dangling pointer, signed integer overflow, . . . 2

  3. Underspecification in C ◮ Unspecified behavior : two or more behaviors are allowed For example: order of evaluation in expressions Non-determinism ◮ Implementation defined behavior : like unspecified behavior, but the compiler has to document its choice For example: size and endianness of integers Parametrization ◮ Undefined behavior: the standard imposes no requirements at all, the program is even allowed to crash For example: dereferencing a NULL or dangling pointer, signed integer overflow, . . . No semantics/crash state 2

  4. Pros and cons of underspecification Pros for optimizing compilers: ◮ More optimizations are possible ◮ High run-time efficiency ◮ Easy to support multiple architectures Cons for programmers/formal methods people: ◮ Portability and maintenance problems ◮ Hard to formally reason about 3

  5. Approaches to underspecification CompCert (Leroy et al. ) ◮ Main goal: verified optimizing compiler in ◮ Specific choices for unspecified/impl-defined behavior For example: 32-bits int s ◮ Describes some undefined behavior For example: dereferencing NULL, integer overflow defined ◮ Compiler correctness proof only for programs without undefined behavior Formalin (Krebbers & Wiedijk) ◮ Main goal: compiler independent separation logic in ◮ Describes some implementation-defined behavior For example: no legacy architectures with 0’s complement ◮ Aims to describe all unspecified and undefined behavior 4

  6. Defined behaviors in C11, Formalin and CompCert C CompCert C C11 Formalin integer overflow comparing subtle with end-of-array casts aliasing violations pointers subtle sequence point byte-wise type violations pointer copy punning use of dangling block scope pointers arithmetic on pointer bytes 5

  7. Defined behaviors in C11, Formalin and CompCert C CompCert C C11 Formalin integer overflow comparing subtle with end-of-array casts aliasing violations pointers subtle sequence point byte-wise type violations pointer copy punning use of dangling block scope pointers arithmetic on pointer bytes This talk: add to CompCert so we get Formalin ⊆ CompCert 5

  8. Comparing with end-of-array pointers (problem) Useful: void inc_array(int *p, int n) { int *end = p + n; while (p < end) (*p++)++; } 6

  9. Comparing with end-of-array pointers (problem) Useful: void inc_array(int *p, int n) { int *end = p + n; while (p < end) (*p++)++; } x 0 x 1 x n − 1 p end 6

  10. Comparing with end-of-array pointers (problem) Useful: void inc_array(int *p, int n) { int *end = p + n; while (p < end) (*p++)++; } x 1 x n − 1 x 0 + 1 p end 6

  11. Comparing with end-of-array pointers (problem) Useful: void inc_array(int *p, int n) { int *end = p + n; while (p < end) (*p++)++; } x n − 1 x 0 + 1 x 1 + 1 p end 6

  12. Comparing with end-of-array pointers (problem) Useful: void inc_array(int *p, int n) { int *end = p + n; while (p < end) (*p++)++; } x n − 1 x 0 + 1 x 1 + 1 p end 6

  13. Comparing with end-of-array pointers (problem) Useful: void inc_array(int *p, int n) { int *end = p + n; while (p < end) (*p++)++; } x n − 1 + 1 x 0 + 1 x 1 + 1 p end 6

  14. Comparing with end-of-array pointers (problem) Useful: void inc_array(int *p, int n) { int *end = p + n; while (p < end) (*p++)++; } x n − 1 + 1 x 0 + 1 x 1 + 1 p end Bizarre: int x, y; if (&x + 1 == &y) printf("x and y are adjacent\n"); 6

  15. Comparing with end-of-array pointers (problem) Useful: void inc_array(int *p, int n) { int *end = p + n; while (p < end) (*p++)++; } x n − 1 + 1 x 0 + 1 x 1 + 1 p end Bizarre: int x, y; if (&x + 1 == &y) printf("x and y are adjacent\n"); &x &y 6

  16. Comparing with end-of-array pointers (problem) Useful: void inc_array(int *p, int n) { int *end = p + n; while (p < end) (*p++)++; } x n − 1 + 1 x 0 + 1 x 1 + 1 p end Bizarre: int x, y; if (&x + 1 == &y) printf("x and y are adjacent\n"); &x &x + 1 &y 6

  17. Comparing with end-of-array pointers (problem) Useful: void inc_array(int *p, int n) { int *end = p + n; while (p < end) (*p++)++; } x n − 1 + 1 x 0 + 1 x 1 + 1 p end Bizarre: int x, y; if (&x + 1 == &y) printf("x and y are adjacent\n"); == ? &x &x + 1 &y 6

  18. Comparing with end-of-array pointers (problem) Useful: void inc_array(int *p, int n) { int *end = p + n; while (p < end) (*p++)++; } x n − 1 + 1 x 0 + 1 x 1 + 1 p end Bizarre: int x, y; if (&x + 1 == &y) printf("x and y are adjacent\n"); == ? &x &x + 1 &y Both undefined behavior in CompCert (1.12 and before) 6

  19. Comparing with end-of-array pointers (solution) Solution: Comparison of pointers is defined if: ◮ Same block: both should within block bounds � × 7

  20. Comparing with end-of-array pointers (solution) Solution: Comparison of pointers is defined if: ◮ Same block: both should within block bounds � × ◮ Different block: both should be strictly within block bounds × � 7

  21. Comparing with end-of-array pointers (solution) Solution: Comparison of pointers is defined if: ◮ Same block: both should within block bounds � × ◮ Different block: both should be strictly within block bounds × � Stable under compilation and gives a semantics to common programming practice with end-of-array pointers 7

  22. Byte-wise copying of objects (problem) struct { short x; short *r; } s1 = {10, &s.x}, s2; unsigned char *p = &s1, *q = &s2; unsigned char *end = p + size_of(s1); while (p < end) *p++ = *q++; 8

  23. Byte-wise copying of objects (problem) struct { short x; short *r; } s1 = {10, &s.x}, s2; unsigned char *p = &s1, *q = &s2; unsigned char *end = p + size_of(s1); while (p < end) *p++ = *q++; s1 : 0x0a 0x00 ( b s1 , 0) 0 ( b s1 , 0) 1 ( b s1 , 0) 2 ( b s1 , 0) 3 p end s2 : q 8

  24. Byte-wise copying of objects (problem) struct { short x; short *r; } s1 = {10, &s.x}, s2; unsigned char *p = &s1, *q = &s2; unsigned char *end = p + size_of(s1); while (p < end) *p++ = *q++; s1 : 0x0a 0x00 ( b s1 , 0) 0 ( b s1 , 0) 1 ( b s1 , 0) 2 ( b s1 , 0) 3 p end s2 : 0x0a q 8

  25. Byte-wise copying of objects (problem) struct { short x; short *r; } s1 = {10, &s.x}, s2; unsigned char *p = &s1, *q = &s2; unsigned char *end = p + size_of(s1); while (p < end) *p++ = *q++; s1 : 0x0a 0x00 ( b s1 , 0) 0 ( b s1 , 0) 1 ( b s1 , 0) 2 ( b s1 , 0) 3 p end s2 : 0x0a 0x00 q Previously undefined, need to allow copying indeterminate bytes 8

  26. Byte-wise copying of objects (problem) struct { short x; short *r; } s1 = {10, &s.x}, s2; unsigned char *p = &s1, *q = &s2; unsigned char *end = p + size_of(s1); while (p < end) *p++ = *q++; s1 : 0x0a 0x00 ( b s1 , 0) 0 ( b s1 , 0) 1 ( b s1 , 0) 2 ( b s1 , 0) 3 p end s2 : 0x0a 0x00 q Previously undefined, need to allow copying indeterminate bytes 8

  27. Byte-wise copying of objects (problem) struct { short x; short *r; } s1 = {10, &s.x}, s2; unsigned char *p = &s1, *q = &s2; unsigned char *end = p + size_of(s1); while (p < end) *p++ = *q++; s1 : 0x0a 0x00 ( b s1 , 0) 0 ( b s1 , 0) 1 ( b s1 , 0) 2 ( b s1 , 0) 3 p end s2 : 0x0a 0x00 q Previously undefined, need to allow copying symbolic pointer bytes 8

  28. Byte-wise copying of objects (problem) struct { short x; short *r; } s1 = {10, &s.x}, s2; unsigned char *p = &s1, *q = &s2; unsigned char *end = p + size_of(s1); while (p < end) *p++ = *q++; s1 : 0x0a 0x00 ( b s1 , 0) 0 ( b s1 , 0) 1 ( b s1 , 0) 2 ( b s1 , 0) 3 p end s2 : 0x0a 0x00 ( b s1 , 0) 0 q Previously undefined, need to allow copying symbolic pointer bytes 8

  29. Byte-wise copying of objects (problem) struct { short x; short *r; } s1 = {10, &s.x}, s2; unsigned char *p = &s1, *q = &s2; unsigned char *end = p + size_of(s1); while (p < end) *p++ = *q++; s1 : 0x0a 0x00 ( b s1 , 0) 0 ( b s1 , 0) 1 ( b s1 , 0) 2 ( b s1 , 0) 3 p end s2 : 0x0a 0x00 ( b s1 , 0) 0 ( b s1 , 0) 1 q Previously undefined, need to allow copying symbolic pointer bytes 8

  30. Byte-wise copying of objects (problem) struct { short x; short *r; } s1 = {10, &s.x}, s2; unsigned char *p = &s1, *q = &s2; unsigned char *end = p + size_of(s1); while (p < end) *p++ = *q++; s1 : 0x0a 0x00 ( b s1 , 0) 0 ( b s1 , 0) 1 ( b s1 , 0) 2 ( b s1 , 0) 3 p end s2 : 0x0a 0x00 ( b s1 , 0) 0 ( b s1 , 0) 1 ( b s1 , 0) 2 q Previously undefined, need to allow copying symbolic pointer bytes 8

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend