Presentation is loading. Please wait.

Presentation is loading. Please wait.

Finding bugs: Analysis Techniques & Tools Comparison of Program Analysis Techniques CS161 Computer Security Cho, Chia Yuan.

Similar presentations


Presentation on theme: "Finding bugs: Analysis Techniques & Tools Comparison of Program Analysis Techniques CS161 Computer Security Cho, Chia Yuan."— Presentation transcript:

1 Finding bugs: Analysis Techniques & Tools Comparison of Program Analysis Techniques CS161 Computer Security Cho, Chia Yuan

2 CompleteIncomplete Sound Unsound Reports all errors Reports no false alarms Reports all errors May report false alarms UndecidableDecidable May not report all errors May report false alarms Decidable May not report all errors Reports no false alarms Testing Dynamic Analysis Static Analysis Manual Program Verification Symbolic Execution Abstract Interpretation Dynamic Symbolic Execution

3 int issafe(char c) { return ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') || (c == '_'); } 1: int sanitize(char s[], size_t n) { 2: size_t i = 0, j = 0; 3: while (j < n) { 4: if (issafe(s[j])) { 5: s[i] = s[j]; 6: i++; j++; 7: } 8: else { 9: j++; 10: } 11: } 12: return i; 13: } Q: Is this code Memory Safe? Manual Program Verification Symbolic Execution Abstract Interpretation Dynamic Symbolic Execution

4 int issafe(char c) { return ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') || (c == '_'); } 1: int sanitize(char s[], size_t n) { 2: size_t i = 0, j = 0; 3: while (j < n) { 4: if (issafe(s[j])) { 5: s[i] = s[j]; 6: i++; j++; 7: } 8: else { 9: j++; 10: } 11: } 12: return i; 13: } Q: Is this code Memory Safe? Q1. What assertions need to be valid for memory safety? - Where should they be inserted? Q2. What are the inputs (free variables) to the program?

5 int issafe(char c) { return ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') || (c == '_'); } 1: int sanitize(char s[], size_t n) { 2: size_t i = 0, j = 0; 3: while (j < n) { 4: if (issafe(s[j])) { 5: s[i] = s[j]; 6: i++; j++; 7: } 8: else { 9: j++; 10: } 11: } 12: return i; 13: } Q: Is this code Memory Safe? Q1. What assertions need to be valid for memory safety? - Where should they be inserted? Q2. What are the inputs (free variables) to the program? Ans: s, n, s[0.. n-1] assert(0 <= j < n); assert(0 <= i < n); Objective: (1) prove assertions valid or (2) produce an input that violates an assertion

6 int issafe(char c) { return ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') || (c == '_'); } Manual Program Analysis 1: int sanitize(char s[], size_t n) { 2: size_t i = 0, j = 0; 3: while (j < n) { 4: if (issafe(s[j])) { 5: s[i] = s[j]; 6: i++; j++; 7: } 8: else { 9: j++; 10: } 11: } 12: return i; 13: } Q: What’s the: Precondition at line 1? Loop invariant (i.e., invariant at line 4) Postconditions at lines 6, 9, 10? Postconditions at lines 3 & 4?

7 int issafe(char c) { return ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') || (c == '_'); } 1: int sanitize(char s[], size_t n) { 2: size_t i = 0, j = 0; 3: while (j < n) { 4: if (issafe(s[j])) { 5: s[i] = s[j]; 6: i++; j++; 7: } 8: else { 9: j++; 10: } 11: } 12: return i; 13: } Abstract Interpretation Let’s assume: Abstract domain: Value Set Intervals (i.e., [x, y] ) n == 2 Q: What’s the value set intervals of i and j after: Lines 2, 6, 9, 10, over iterations 1, 2 & 3? Q: What if n is 1000?

8 int issafe(char c) { return ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') || (c == '_'); } 1: int sanitize(char s[], size_t n) { 2: size_t i = 0, j = 0; 3: while (j < n) { 4: if (issafe(s[j])) { 5: s[i] = s[j]; 6: i++; j++; 7: } 8: else { 9: j++; 10: } 11: } 12: return i; 13: } Dynamic Symbolic Execution Let’s assume: n == 2, s != NULL, sizeof(s) >= 2 Q: How many paths are there in a full exploration? Q: Start exploring from an initial test case s = “??”. For each path, write down the obtained formula to solve to get a new input down a new path Q: What if n is 1000?

9 int issafe(char c) { return ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') || (c == '_'); } 1: int sanitize(char s[], size_t n) { 2: size_t i = 0, j = 0; 3: while (j < n) { 4: if (issafe(s[j])) { 5: s[i] = s[j]; 6: i++; j++; 7: } 8: else { 9: j++; 10: } 11: } 12: return i; 13: } Symbolic Execution Let’s assume: n == 2 Q: Transform the program (with assertions) into a single formula Q: What if n == 1000?

10 int issafe(char c) { return ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') || (c == '_'); } 1: int sanitize(char s[], size_t n) { 2: size_t i = 0, j = 0; 3: while (j < n) { 4: if (issafe(s[j])) { 5: s[i] = s[j]; 6: i++; j++; 7: } 8: else { 9: j++; 10: } 11: } 12: return i; 13: } Q: Is this code Memory Safe?

11 Answers

12 int issafe(char c) { return ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') || (c == '_'); } Manual Program Analysis 1: int sanitize(char s[], size_t n) { 2: size_t i = 0, j = 0; 3: while (j < n) { 4: if (issafe(s[j])) { 5: s[i] = s[j]; 6: i++; j++; 7: } 8: else { 9: j++; 10: } 11: } 12: return i; 13: } Q: What’s the: Precondition at line 1? Loop invariant (i.e., invariant at line 4)? Postconditions at lines 6, 9, 10? Postconditions at lines 3 & 4?

13 int issafe(char c) { return ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') || (c == '_'); } 1: int sanitize(char s[], size_t n) { 2: size_t i = 0, j = 0; 3: while (j < n) { 4: if (issafe(s[j])) { 5: s[i] = s[j]; 6: i++; j++; 7: } 8: else { 9: j++; 10: } 11: } 12: return i; 13: } Q: Is this code Memory Safe? assert(0 <= j < n); assert(0 <= i < n);

14 Manual Program Analysis 1: int sanitize(char s[], size_t n) { 2: size_t i = 0, j = 0; 3: while (j < n) { 4: if (issafe(s[j])) { 5: s[i] = s[j]; 6: i++; j++; 7: } 8: else { 9: j++; 10: } 11: } 12: return i; 13: } int issafe(char c) { return ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') || (c == '_'); } Requires: s != NULL && 0 <= n <= sizeof(s) s != NULL && 0 <= n <= sizeof(s) && 0 < i <= n && 0 < j <= n s != NULL && 0 <= n <= sizeof(s) && 0 <= i < n && 0 < j <= n s != NULL && 0 <= n <= sizeof(s) && 0 <= i <= n && 0 < j <= n assert(0 <= j < n); assert(0 <= i < n); s != NULL && 0 <= n <= sizeof(s) && 0 <= i < n && 0 <= j < n

15 int issafe(char c) { return ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') || (c == '_'); } 1: int sanitize(char s[], size_t n) { 2: size_t i = 0, j = 0; 3: while (j < n) { 4: if (issafe(s[j])) { 5: s[i] = s[j]; 6: i++; j++; 7: } 8: else { 9: j++; 10: } 11: } 12: return i; 13: } Abstract Interpretation Let’s assume: Abstract domain: Value Set Intervals (i.e., [x, y] ) n == 2 Q: What’s the value set intervals of i and j after: Lines 2, 6, 9, 10, over iterations 1, 2 & 3? Q: What if n is 1000?

16 1: int sanitize(char s[], size_t n) { 2: size_t i = 0, j = 0; 3: while (j < n) { 4: if (issafe(s[j])) { 5: s[i] = s[j]; 6: i++; j++; 7: } 8: else { 9: j++; 10: } 11: } 12: return i; 13: } Abstract Interpretation int issafe(char c) { return ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') || (c == '_'); } i: [0, 0] j: [0, 0] First pass … i: [1, 1] j: [1, 1] i: [0, 0] j: [1, 1] i: [0, 1] j: [1, 1]

17 1: int sanitize(char s[], size_t n) { 2: size_t i = 0, j = 0; 3: while (j < n) { 4: if (issafe(s[j])) { 5: s[i] = s[j]; 6: i++; j++; 7: } 8: else { 9: j++; 10: } 11: } 12: return i; 13: } Abstract Interpretation int issafe(char c) { return ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') || (c == '_'); } i: [0, 1] j: [0, 1] Second pass … i: [1, 2] j: [1, 2] i: [0, 1] j: [1, 2] i: [0, 2] j: [1, 2] Third pass? What if n == 1000?

18 int issafe(char c) { return ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') || (c == '_'); } 1: int sanitize(char s[], size_t n) { 2: size_t i = 0, j = 0; 3: while (j < n) { 4: if (issafe(s[j])) { 5: s[i] = s[j]; 6: i++; j++; 7: } 8: else { 9: j++; 10: } 11: } 12: return i; 13: } Dynamic Symbolic Execution Let’s assume: n == 2, s != NULL, sizeof(s) >= 2 Q: How many paths are there in a full exploration? Q: Start exploring from an initial test case s = “??”. For each path, write down the obtained formula to solve to get a new input down a new path Q: What if n is 1000?

19 1: int sanitize(char s[], size_t n) { 2: size_t i = 0, j = 0; 3: while (j < n) { 4: if (issafe(s[j])) { 5: s[i] = s[j]; 6: i++; j++; 7: } 8: else { 9: j++; 10: } 11: } 12: return i; 13: } Dynamic Symbolic Execution int issafe(char c) { return ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') || (c == '_'); } Q: How many paths are there in a full exploration? Ans: 4 paths! 1.Input : S0 == “??” Get Formula1: i1 == 0 && j1 == 0 && issafe(S0[j1]) Get Formula2: i1 == 0 && j1 == 0 && !issafe(S0[j1]) && j2 == j1 + 1 && issafe(S0[j2]) 2. Solve Formula1. Get Input: e.g., S0 == “a?” Get Formula3: i1 == 0 && j1 == 0 && issafe(S0[j1]) && S1 == S0 WITH S0[i1] == S0[j1] && i2 == i1 + 1 && j2 == j1 + 1 && issafe(S1[j2]) 3. Solve Formula2. Get Input: e.g., S0 == “?a” 4. Solve Formula3. Get Input: e.g., S0 == “aa” What if n == 1000?

20 int issafe(char c) { return ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') || (c == '_'); } 1: int sanitize(char s[], size_t n) { 2: size_t i = 0, j = 0; 3: while (j < n) { 4: if (issafe(s[j])) { 5: s[i] = s[j]; 6: i++; j++; 7: } 8: else { 9: j++; 10: } 11: } 12: return i; 13: } Symbolic Execution Let’s assume: n == 2 Q: Transform the program (with assertions) into a single formula Q: What if n == 1000?

21 int issafe(char c) { return ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') || (c == '_'); } 1: int sanitize(char s[], size_t n) { 2: size_t i = 0, j = 0; 3: while (j < n) { 4: if (issafe(s[j])) { 5: s[i] = s[j]; 6: i++; j++; 7: } 8: else { 9: j++; 10: } 11: } 12: return i; 13: } Symbolic Execution i1 == 0 && j1 == 0 && branchcond1 == issafe(S0[j1]) && S1 == S0 WITH S0[i1] == S0[j1] && i2 == i1 + 1 && j2 == j1 + 1 && j3 == j1 + 1 && S2 == branchcond1 ? S1 : S0 && i3 == branchcond1 ? i2 : i1 && j4 == branchcond1 ? j2: j3 && ( !(0 <= i1 < 2) || !(0 <= j1 < 2) !(0 <= i3 < 2) || !(0 <= j4 < 2) ) What if n == 1000?

22 int issafe(char c) { return ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') || (c == '_'); } 1: int sanitize(char s[], size_t n) { 2: size_t i = 0, j = 0; 3: while (j < n) { 4: if (issafe(s[j])) { 5: s[i] = s[j]; 6: i++; j++; 7: } 8: else { 9: j++; 10: } 11: } 12: return i; 13: } Q: Is this code Memory Safe? Manual Program Verification Symbolic Execution Abstract Interpretation Dynamic Symbolic Execution

23 int issafe(char c) { return ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') || (c == '_'); } 1: int sanitize(char s[], size_t n) { 2: size_t i = 0, j = 0; 3: while (j < n) { 4: if (issafe(s[j])) { 5: s[i] = s[j]; 6: i++; j++; 7: } 8: else { 9: j++; 10: } 11: } 12: return i; 13: } Q: Is this code Memory Safe? Q1. What assertions need to be valid for memory safety? - Where should they be inserted? Q2. What are the inputs (free variables) to the program? Ans: s, n, s[0.. n-1] assert(0 <= j < n); assert(0 <= i < n); Objective: (1) prove assertions valid or (2) produce an input that violates an assertion


Download ppt "Finding bugs: Analysis Techniques & Tools Comparison of Program Analysis Techniques CS161 Computer Security Cho, Chia Yuan."

Similar presentations


Ads by Google