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
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
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
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
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
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
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
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
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
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
Problems & Our Solutions 8
Problem 1 9
Pointer → Integer Casting? (int)p 10
Pointer → Integer Casting? (p,0x100) (int)p 10
Pointer → Integer Casting? (p,0x100) (int)p 10
Pointer → Integer Casting? (p,0x100) (int)p (p,0x100) 1. Carry Provenance 10
Pointer → Integer Casting? (p,0x100) (int)p (p,0x100) 0x100 2. Drop 1. Carry Provenance Provenance 10
Pointer → Integer Casting? (p,0x100) (int)p (p,0x100) 0x100 2. Drop 1. Carry Provenance Provenance 10
Pointer → Integer Casting? (p,0x100) (int)p (p,0x100) 0x100 1. Carry 2. Drop Provenance Provenance 10
Carry Provenance: Integer Optimization Problem 1. Carry Provenance k = (i==j ? i : j) k = j 11
Carry Provenance: Integer Optimization Problem 1. Carry Provenance k = (i==j ? i : j) k = j true 11
Carry Provenance: Integer Optimization Problem 1. Carry Provenance k = (i==j ? i : j) k = j true i 11
Carry Provenance: Integer Optimization Problem 1. Carry Provenance k = (i==j ? i : j) k = j true j 11
Carry Provenance: Integer Optimization Problem 1. Carry Provenance k = (i==j ? i : j) k = j false 11
Carry Provenance: Integer Optimization Problem 1. Carry Provenance k = (i==j ? i : j) k = j false j 11
Carry Provenance: Integer Optimization Problem 1. Carry Provenance k = (i==j ? i : j) k = j j 11
Carry Provenance: Integer Optimization Problem 1. Carry Provenance (p,0x100) k = (i==j ? i : j) k = j 11
Carry Provenance: Integer Optimization Problem 1. Carry Provenance (p,0x100) k = (i==j ? i : j) k = j (q,0x100) 11
Carry Provenance: Integer Optimization Problem 1. Carry Provenance (p,0x100) k = (i==j ? i : j) k = j true (q,0x100) 11
Carry Provenance: Integer Optimization Problem 1. Carry Provenance (p,0x100) k = (i==j ? i : j) k = j true (q,0x100) 11
Carry Provenance: Integer Optimization Problem 1. Carry Provenance (p,0x100) k = (i==j ? i : j) k = j true (q,0x100) (q,0x100) 11
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
Carry Provenance: Integer Optimization Problem 2. Drop Provenance (p,0x100) k = (i==j ? i : j) k = j true (q,0x100) (q,0x100) 12
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
Problem 2 13
Integer → Pointer Casting? char p[1] Memory: 0x100 (int*)0x100 14
Integer → Pointer Casting? char p[1] Memory: 0x100 (int*)0x100 ( Ø ,0x100) 1. Always Empty 14
Integer → Pointer Casting? char p[1] Memory: 0x100 (int*)0x100 ( Ø ,0x100) 2. Depending on 1. Always Empty the Memory Layout 14
Integer → Pointer Casting? Memory: 0x100 (int*)0x100 ( Ø ,0x100) ( Ø ,0x100) 2. Depending on 1. Always Empty the Memory Layout 14
Integer → Pointer Casting? char p[1] Memory: 0x100 (int*)0x100 ( Ø ,0x100) (p,0x100) 2. Depending on 1. Always Empty the Memory Layout 14
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
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
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
Empty Provenance: Pointer – Integer Round Trip 1. Always Empty char p[1] Memory: 0x100 i = (int)p p2 = (char*)i *p2 = 10 15
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Problem 3 20
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
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
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
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
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