reconciling high level optimizations and
play

Reconciling High-Level Optimizations and Low-Level Code in LLVM - PowerPoint PPT Presentation

OOPSLA 18 Boston Reconciling High-Level Optimizations and Low-Level Code in LLVM Juneyoung Lee Seoul National Univ. Chung-Kil Hur MPI-SWS Ralf Jung Zhengyang Liu University of Utah John Regehr Nuno P. Lopes Microsoft Research


  1. Miscompilation with Int-Ptr Casting int. eq. char p[1],q[1]={0}; char p[1],q[1]={0}; prop. int ip = (int)(p+1); int ip = (int)(p+1); int iq = (int)q; int iq = (int)q; if (iq == ip) { if (iq == ip) { *(char*)(int)(p+1)=10; *(char*)iq = 10; print(q[0]); print(q[0]); } } char p[1],q[1] = {0}; char p[1],q[1] = {0}; int ip = (int)(p+1); int ip = (int)(p+1); int iq = (int)q; int iq = (int)q; if (iq == ip) { if (iq == ip) { *(p+1) = 10; *(p+1) = 10; print(q[0]); print(0); } } 7

  2. Miscompilation with Int-Ptr Casting int. eq. char p[1],q[1]={0}; char p[1],q[1]={0}; prop. int ip = (int)(p+1); int ip = (int)(p+1); int iq = (int)q; int iq = (int)q; if (iq == ip) { if (iq == ip) { *(char*)(int)(p+1)=10; *(char*)iq = 10; print(q[0]); print(q[0]); } } char p[1],q[1] = {0}; char p[1],q[1] = {0}; int ip = (int)(p+1); int ip = (int)(p+1); int iq = (int)q; int iq = (int)q; if (iq == ip) { if (iq == ip) { *(p+1) = 10; *(p+1) = 10; print(q[0]); print(0); } } 7

  3. Miscompilation with Int-Ptr Casting int. eq. char p[1],q[1]={0}; char p[1],q[1]={0}; prop. int ip = (int)(p+1); int ip = (int)(p+1); int iq = (int)q; int iq = (int)q; if (iq == ip) { if (iq == ip) { *(char*)(int)(p+1)=10; *(char*)iq = 10; print(q[0]); print(q[0]); } } char p[1],q[1] = {0}; char p[1],q[1] = {0}; int ip = (int)(p+1); int ip = (int)(p+1); int iq = (int)q; int iq = (int)q; if (iq == ip) { if (iq == ip) { *(p+1) = 10; *(p+1) = 10; print(q[0]); print(0); } } 7

  4. Miscompilation with Int-Ptr Casting char p[1],q[1]={0}; char p[1],q[1]={0}; int ip = (int)(p+1); int ip = (int)(p+1); int iq = (int)q; int iq = (int)q; if (iq == ip) { if (iq == ip) { *(char*)(int)(p+1)=10; *(char*)iq = 10; print(q[0]); print(q[0]); } } cast elim. char p[1],q[1] = {0}; char p[1],q[1] = {0}; int ip = (int)(p+1); int ip = (int)(p+1); int iq = (int)q; int iq = (int)q; if (iq == ip) { if (iq == ip) { *(p+1) = 10; *(p+1) = 10; print(q[0]); print(0); } } 7

  5. Miscompilation with Int-Ptr Casting char p[1],q[1]={0}; char p[1],q[1]={0}; int ip = (int)(p+1); int ip = (int)(p+1); int iq = (int)q; int iq = (int)q; if (iq == ip) { if (iq == ip) { *(char*)(int)(p+1)=10; *(char*)iq = 10; print(q[0]); print(q[0]); } } char p[1],q[1] = {0}; char p[1],q[1] = {0}; int ip = (int)(p+1); int ip = (int)(p+1); int iq = (int)q; int iq = (int)q; if (iq == ip) { if (iq == ip) { *(p+1) = 10; *(p+1) = 10; constant print(q[0]); print(0); } prop. } 7

  6. Miscompilation with Int-Ptr Casting char p[1],q[1]={0}; char p[1],q[1]={0}; int ip = (int)(p+1); int ip = (int)(p+1); int iq = (int)q; int iq = (int)q; if (iq == ip) { if (iq == ip) { *(char*)(int)(p+1)=10; *(char*)iq = 10; print(q[0]); print(q[0]); 10 } } char p[1],q[1] = {0}; char p[1],q[1] = {0}; int ip = (int)(p+1); int ip = (int)(p+1); int iq = (int)q; int iq = (int)q; if (iq == ip) { if (iq == ip) { *(p+1) = 10; *(p+1) = 10; print(q[0]); print(0); } } 7

  7. Miscompilation with Int-Ptr Casting char p[1],q[1]={0}; char p[1],q[1]={0}; int ip = (int)(p+1); int ip = (int)(p+1); int iq = (int)q; int iq = (int)q; if (iq == ip) { if (iq == ip) { *(char*)(int)(p+1)=10; *(char*)iq = 10; print(q[0]); print(q[0]); 10 } } char p[1],q[1] = {0}; char p[1],q[1] = {0}; int ip = (int)(p+1); int ip = (int)(p+1); int iq = (int)q; int iq = (int)q; if (iq == ip) { if (iq == ip) { *(p+1) = 10; *(p+1) = 10; print(q[0]); print(0); } } 7

  8. Miscompilation with Int-Ptr Casting char p[1],q[1]={0}; char p[1],q[1]={0}; int ip = (int)(p+1); int ip = (int)(p+1); int iq = (int)q; int iq = (int)q; if (iq == ip) { if (iq == ip) { *(char*)(int)(p+1)=10; *(char*)iq = 10; print(q[0]); print(q[0]); 10 } } char p[1],q[1] = {0}; char p[1],q[1] = {0}; int ip = (int)(p+1); int ip = (int)(p+1); int iq = (int)q; int iq = (int)q; if (iq == ip) { if (iq == ip) { *(p+1) = 10; *(p+1) = 10; print(q[0]); print(0); } } 7

  9. Miscompilation with Int-Ptr Casting char p[1],q[1]={0}; char p[1],q[1]={0}; We found this miscompilation bug int ip = (int)(p+1); int ip = (int)(p+1); int iq = (int)q; int iq = (int)q; in both LLVM & GCC if (iq == ip) { if (iq == ip) { *(char*)(int)(p+1)=10; *(char*)iq = 10; print(q[0]); print(q[0]); 10 } } char p[1],q[1] = {0}; char p[1],q[1] = {0}; int ip = (int)(p+1); int ip = (int)(p+1); int iq = (int)q; int iq = (int)q; if (iq == ip) { if (iq == ip) { *(p+1) = 10; *(p+1) = 10; print(q[0]); print(0); } } 7

  10. Miscompilation with Int-Ptr Casting char p[1],q[1]={0}; char p[1],q[1]={0}; We found this miscompilation bug int ip = (int)(p+1); int ip = (int)(p+1); int iq = (int)q; int iq = (int)q; in both LLVM & GCC if (iq == ip) { if (iq == ip) { *(char*)(int)(p+1)=10; *(char*)iq = 10; print(q[0]); print(q[0]); Goal of this paper 10 } } Finding a good memory model for char p[1],q[1] = {0}; char p[1],q[1] = {0}; pointer ↔ integer casting int ip = (int)(p+1); int ip = (int)(p+1); int iq = (int)q; int iq = (int)q; if (iq == ip) { if (iq == ip) { *(p+1) = 10; *(p+1) = 10; print(q[0]); print(0); } } 7

  11. Problems & Our Solutions 8

  12. Problem 1 9

  13. Pointer → Integer Casting? (int)p 10

  14. Pointer → Integer Casting? (p,0x100) (int)p 10

  15. Pointer → Integer Casting? (p,0x100) (int)p 10

  16. Pointer → Integer Casting? (p,0x100) (int)p (p,0x100) 1. Carry Provenance 10

  17. Pointer → Integer Casting? (p,0x100) (int)p (p,0x100) 0x100 2. Drop 1. Carry Provenance Provenance 10

  18. Pointer → Integer Casting? (p,0x100) (int)p (p,0x100) 0x100 2. Drop 1. Carry Provenance Provenance 10

  19. Pointer → Integer Casting? (p,0x100) (int)p (p,0x100) 0x100 1. Carry 2. Drop Provenance Provenance 10

  20. Carry Provenance: Integer Optimization Problem 1. Carry Provenance k = (i==j ? i : j) k = j 11

  21. Carry Provenance: Integer Optimization Problem 1. Carry Provenance k = (i==j ? i : j) k = j true 11

  22. Carry Provenance: Integer Optimization Problem 1. Carry Provenance k = (i==j ? i : j) k = j true i 11

  23. Carry Provenance: Integer Optimization Problem 1. Carry Provenance k = (i==j ? i : j) k = j true j 11

  24. Carry Provenance: Integer Optimization Problem 1. Carry Provenance k = (i==j ? i : j) k = j false 11

  25. Carry Provenance: Integer Optimization Problem 1. Carry Provenance k = (i==j ? i : j) k = j false j 11

  26. Carry Provenance: Integer Optimization Problem 1. Carry Provenance k = (i==j ? i : j) k = j j 11

  27. Carry Provenance: Integer Optimization Problem 1. Carry Provenance (p,0x100) k = (i==j ? i : j) k = j 11

  28. Carry Provenance: Integer Optimization Problem 1. Carry Provenance (p,0x100) k = (i==j ? i : j) k = j (q,0x100) 11

  29. Carry Provenance: Integer Optimization Problem 1. Carry Provenance (p,0x100) k = (i==j ? i : j) k = j true (q,0x100) 11

  30. Carry Provenance: Integer Optimization Problem 1. Carry Provenance (p,0x100) k = (i==j ? i : j) k = j true (q,0x100) 11

  31. Carry Provenance: Integer Optimization Problem 1. Carry Provenance (p,0x100) k = (i==j ? i : j) k = j true (q,0x100) (q,0x100) 11

  32. Carry Provenance: Integer Optimization Problem Problem 1. Carry Provenance Integer optimizations may change provenance (p,0x100) k = (i==j ? i : j) k = j true (q,0x100) (q,0x100) 11

  33. Carry Provenance: Integer Optimization Problem 2. Drop Provenance (p,0x100) k = (i==j ? i : j) k = j true (q,0x100) (q,0x100) 12

  34. Carry Provenance: Integer Optimization Problem 2. Drop Provenance (p,0x100) 0x100 k = (i==j ? i : j) k = j true (q,0x100) 0x100 (q,0x100) 0x100 12

  35. Problem 2 13

  36. Integer → Pointer Casting? char p[1] Memory: 0x100 (int*)0x100 14

  37. Integer → Pointer Casting? char p[1] Memory: 0x100 (int*)0x100 ( Ø ,0x100) 1. Always Empty 14

  38. Integer → Pointer Casting? char p[1] Memory: 0x100 (int*)0x100 ( Ø ,0x100) 2. Depending on 1. Always Empty the Memory Layout 14

  39. Integer → Pointer Casting? Memory: 0x100 (int*)0x100 ( Ø ,0x100) ( Ø ,0x100) 2. Depending on 1. Always Empty the Memory Layout 14

  40. Integer → Pointer Casting? char p[1] Memory: 0x100 (int*)0x100 ( Ø ,0x100) (p,0x100) 2. Depending on 1. Always Empty the Memory Layout 14

  41. Integer → Pointer Casting? char p[1] Memory: 0x100 (int*)0x100 ( Ø ,0x100) ( ∗ ,0x100) (p,0x100) 2. Depending on 1. Always Empty 3. Always Full the Memory Layout 14

  42. Integer → Pointer Casting? char p[1] Memory: 0x100 (int*)0x100 ( Ø ,0x100) ( ∗ ,0x100) (p,0x100) 2. Depending on 1. Always Empty 3. Always Full the Memory Layout 14

  43. Integer → Pointer Casting? char p[1] Memory: 0x100 (int*)0x100 ( Ø ,0x100) ( ∗ ,0x100) (p,0x100) 2. Depending on 1. Always Empty 3. Always Full the Memory Layout 14

  44. Empty Provenance: Pointer – Integer Round Trip 1. Always Empty char p[1] Memory: 0x100 i = (int)p p2 = (char*)i *p2 = 10 15

  45. Empty Provenance: Pointer – Integer Round Trip 1. Always Empty char p[1] Memory: 0x100 (p,0x100) i = (int)p p2 = (char*)i *p2 = 10 15

  46. Empty Provenance: Pointer – Integer Round Trip 1. Always Empty char p[1] Memory: 0x100 0x100 (p,0x100) i = (int)p p2 = (char*)i *p2 = 10 15

  47. Empty Provenance: Pointer – Integer Round Trip 1. Always Empty char p[1] Memory: 0x100 0x100 (p,0x100) i = (int)p p2 = (char*)i ( ∅ ,0x100) *p2 = 10 15

  48. Empty Provenance: Pointer – Integer Round Trip 1. Always Empty char p[1] Memory: 0x100 0x100 (p,0x100) i = (int)p p2 = (char*)i ( ∅ ,0x100) *p2 = 10 UB 15

  49. Empty Provenance: Pointer – Integer Round Trip Problem 1. Always Empty Common program patterns raise UB char p[1] Memory: 0x100 0x100 (p,0x100) i = (int)p p2 = (char*)i ( ∅ ,0x100) *p2 = 10 UB 15

  50. Empty Provenance: Pointer – Integer Round Trip 3. Always Full char p[1] Memory: 0x100 0x100 (p,0x100) i = (int)p p2 = (char*)i ( ∅ ,0x100) *p2 = 10 UB 16

  51. Empty Provenance: Pointer – Integer Round Trip 3. Always Full char p[1] Memory: 0x100 0x100 (p,0x100) i = (int)p p2 = (char*)i ( ∅ ,0x100) ( ∗ ,0x100) *p2 = 10 UB 16

  52. Empty Provenance: Pointer – Integer Round Trip 3. Always Full char p[1] 10 Memory: 0x100 0x100 (p,0x100) i = (int)p p2 = (char*)i ( ∅ ,0x100) ( ∗ ,0x100) *p2 = 10 16

  53. Integer → Pointer Casting? char p[1] Memory: 0x100 (int*)0x100 ( Ø ,0x100) ( ∗ ,0x100) (p,0x100) (p,0x100) 2. Depending on 1. Always Empty 3. Always Full the Memory Layout 17

  54. Integer → Pointer Casting? char p[1] Memory: 0x100 (int*)0x100 ( Ø ,0x100) ( ∗ ,0x100) (p,0x100) (p,0x100) 2. Depending on 1. Always Empty 3. Always Full the Memory Layout 17

  55. Depending on the Memory Layout: Reordering 2. Depending on the Memory Layout char p[1] Memory: 0x100 q = (int*)0x100 char *p = malloc(1) char *p = malloc(1) q = (int*)0x100 18

  56. Depending on the Memory Layout: Reordering 2. Depending on the Memory Layout char p[1] Memory: 0x100 q = (int*)0x100 char *p = malloc(1) char *p = malloc(1) q = (int*)0x100 18

  57. Depending on the Memory Layout: Reordering 2. Depending on the Memory Layout char p[1] Memory: 0x100 q = (int*)0x100 char *p = malloc(1) char *p = malloc(1) q = (int*)0x100 (p,0x100) 18

  58. Depending on the Memory Layout: Reordering 2. Depending on the Memory Layout Memory: 0x100 q = (int*)0x100 char *p = malloc(1) char *p = malloc(1) q = (int*)0x100 (p,0x100) 18

  59. Depending on the Memory Layout: Reordering 2. Depending on the Memory Layout Memory: 0x100 ( Ø ,0x100) q = (int*)0x100 char *p = malloc(1) char *p = malloc(1) q = (int*)0x100 (p,0x100) 18

  60. Depending on the Memory Layout: Reordering 2. Depending on the Memory Layout Memory: Problem 0x100 ( Ø ,0x100) Movement of casts, or functions including them, is restricted q = (int*)0x100 char *p = malloc(1) char *p = malloc(1) q = (int*)0x100 (p,0x100) 18

  61. Depending on the Memory Layout: Reordering 3. Always Full char p[1] Memory: 0x100 ( Ø ,0x100) q = (int*)0x100 char *p = malloc(1) char *p = malloc(1) q = (int*)0x100 (p,0x100) 19

  62. Depending on the Memory Layout: Reordering 3. Always Full char p[1] Memory: 0x100 ( Ø ,0x100) ( ∗ ,0x100) q = (int*)0x100 char *p = malloc(1) char *p = malloc(1) q = (int*)0x100 ( ∗ ,0x100) (p,0x100) 19

  63. Problem 3 20

  64. Problems with Full Provenance Anyone can modify other’s local variables by 1. Guessing their addresses & 2. Acquiring full provenance via casting char p[1] = {0}; f(); print(p[0]); 21

  65. Problems with Full Provenance Anyone can modify other’s local variables by 1. Guessing their addresses & 2. Acquiring full provenance via casting char p[1] = {0}; char p[1] = {0}; f(); f(); print(p[0]); print(0); constant prop. 21

  66. Problems with Full Provenance Anyone can modify other’s local variables by 1. Guessing their addresses & 2. Acquiring full provenance via casting (p,0x100) char p[1] = {0}; char p[1] = {0}; f(); f(); print(p[0]); print(0); constant prop. 21

  67. Problems with Full Provenance Anyone can modify other’s local variables by 1. Guessing their addresses & 2. Acquiring full provenance via casting (p,0x100) char p[1] = {0}; char p[1] = {0}; f(); f(); *(char*)(0x100)=1; print(p[0]); print(0); constant prop. 21

  68. Problems with Full Provenance Anyone can modify other’s local variables by 1. Guessing their addresses & 2. Acquiring full provenance via casting (p,0x100) ( ∗ ,0x100) char p[1] = {0}; char p[1] = {0}; f(); f(); *(char*)(0x100)=1; print(p[0]); print(0); constant Full Provenance prop. 21

Recommend


More recommend