Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Finding 1,500 bugs in the SMT Solvers Z3 and CVC5

Finding 1,500 bugs in the SMT Solvers Z3 and CVC5

Satisfiability Modulo Theory (SMT) solvers are essential tools for many advances in programming languages and formal methods. Examples include symbolic execution engines, software model checkers, and program verifiers. SMT solvers' robustness is crucial---Soundness bugs SMT solvers can invalidate client applications' results and lead to disasters in safety-critical or security-critical domains. We ran a large-scale testing campaign to put Z3 and CVC4/5's robustness to the test: As of today, We have found 1,500+ unique bugs in Z3 and CVC4--1,100+ have already been fixed by the developers and 400+ are critical soundness bugs. This talk covers the techniques used and lessons learned from this campaign. Specifically, we will discuss: (1) Semantic Fusion, a general, metamorphic testing methodology, (2) Type-Aware Mutation, a highly effective testing technique for testing SMT solvers, and (3) outline open challenges in making SMT solvers (and other formal methods tools) more correct and faster.

Dominik Winterer

June 24, 2022
Tweet

Other Decks in Research

Transcript

  1. Finding 1,500+ Bugs in the SMT Solver s Z3 and

    CVC5 Dominik Wintere r ETH Zurich
 
 Talk at Paderborn Universit y Jun 21st, 2022 @DominikWinterer wintered.github.io
  2. SMT Solvers: Important Software Foundations SMT Solver Formal veri fi

    cation Symbolic Execution Access Policy Analysis Security Safety … 10
  3. SMT Solver UNSAT Bug in an SMT Solver φ :

    x > 0 ∧ x < 1 13 x = 0.5
  4. SMT Solvers should be robust! SMT Solver Access Policy Analysis

    Symbolic Execution Formal Veri fi cation Security Security … 14
  5. SMT Solvers should be robust! SMT Solver Symbolic Execution Access

    Policy nalysis Security Safety … Formal Veri fi cation 15
  6. Ensuring the Robustness of SMT Solvers 16 Proo f Certi

    fi cates Formally veri fi e d SMT solver Automated
 Testing
  7. Ensuring the Robustness of SMT Solvers 17 Proo f Certi

    fi cates Formally veri fi e d SMT solver Automated
 Testing
  8. Project Yin-Yang for SMT Solver Testing [Summary: 1,560 (total) /

    1,061 ( fi xed)]
 
 [Z3 bugs: 1,147 (total) / 779 ( fi xed)]
 [CVC4 bugs: 413 (total) / 282 ( fi xed)]
 
 [Bugs in default mode (Z3): 680 (total) / 479 ( fi xed)]
 [Bugs in default mode (CVC4): 204 (total) / 147 ( fi xed)]
 
 [Soundness bugs (Z3): 375 (total) / 228 ( fi xed)]
 [Soundness bugs (CVC4): 71 (total) / 60 ( fi xed)]
 July 2019 -
  9. Roadmap 1. Introductio n 2. Testing Technique s a) Semantic

    Fusio n b) Type-aware Operator Mutatio n c) Generative Type-Aware Operator Mutation 3. Current and Future Directions 19
  10. SMT-LIB language • Standard format for modern SMT solver s

    • LISP-dialec t • Declarative: no re-assignments of variable s • SMT-LIB is quite expressive 20 Variable Declarations Constraints Solver Query
  11. SMT-LIB language φ : x > 0 ∧ x <

    1 (declare-fun x () Real ) (assert (and (> x 0)(< x 1)) ) (check-sat ) 22
  12. SMT-LIB language φ : x > 0 ∧ x <

    1 (declare-fun x () Real ) (assert (and (> x 0)(< x 1)) ) (check-sat ) 23
  13. SMT-LIB language φ : x > 0 ∧ x <

    1 (declare-fun x () Real ) (assert (and (> x 0)(< x 1)) ) (check-sat ) 24
  14. SMT-LIB language φ : x > 0 ∧ x <

    1 (declare-fun x () Real ) (assert (and (> x 0)(< x 1)) ) (check-sat ) 25
  15. Roadmap 1. Introductio n 2. Testing Technique s a) Semantic

    Fusio n b) Type-aware Operator Mutatio n c) Generative Type-Aware Operator Mutation 3. Open Problems 26
  16. Semantic Fusion φ1 = x > 0 ∧ x >

    1 φ2 = y < 0 ∧ y < 1 SAT SAT 30
  17. Semantic Fusion (x > 0 ∧ x > 1) ∧

    (y < 0 ∧ y < 1) φ1 φ2 31
  18. Semantic Fusion (x > 0 ∧ x > 1) ∧

    (y < 0 ∧ y < 1) φ1 φ2 φconcat = SAT 32
  19. Semantic Fusion (x > 0 ∧ x > 1) ∧

    (y < 0 ∧ y < 1) φ1 φ2 φconcat = SAT x = 2 y = − 2 33
  20. Semantic Fusion (x > 0 ∧ x > 1) ∧

    (y < 0 ∧ y < 1) φ1 φ2 φconcat = SAT z 34
  21. Semantic Fusion (x > 0 ∧ x > 1) ∧

    (y < 0 ∧ y < 1) φ1 φ2 φconcat = SAT z = x + y 35
  22. Semantic Fusion (x > 0 ∧ x > 1) ∧

    (y < 0 ∧ y < 1) φ1 φ2 φconcat = SAT z = x + y Fusion Function 36
  23. Semantic Fusion (x > 0 ∧ x > 1) ∧

    (y < 0 ∧ y < 1) φ1 φ2 φconcat = SAT z = x + y 37
  24. Semantic Fusion (x > 0 ∧ x > 1) ∧

    (y < 0 ∧ y < 1) φ1 φ2 φconcat = SAT z = x + y x = z − y y = z − x 38
  25. Semantic Fusion (x > 0 ∧ x > 1) ∧

    (y < 0 ∧ y < 1) φ1 φ2 φconcat = SAT z = x + y x = z − y y = z − x Inversion Functions 39
  26. Semantic Fusion (x > 0 ∧ x > 1) ∧

    (y < 0 ∧ y < 1) φ1 φ2 φconcat = SAT z = x + y x = z − y y = z − x 40
  27. Semantic Fusion (x > 0 ∧ x > 1) ∧

    (y < 0 ∧ y < 1) φ1 φ2 φconcat = SAT z = x + y x = z − y y = z − x 41
  28. Semantic Fusion (x > 0 ∧ (z − y) >

    1) ∧ ((z − x) < 0 ∧ y < 1) z = x + y x = z − y y = z − x φ1 φ2 φfused = 42
  29. Semantic Fusion (x > 0 ∧ (z − y) >

    1) ∧ ((z − x) < 0 ∧ y < 1) z = x + y x = z − y y = z − x φfused = SAT 43
  30. Semantic Fusion (x > 0 ∧ (z − y) >

    1) ∧ ((z − x) < 0 ∧ y < 1) z = x + y x = z − y y = z − x φfused = SAT (x > 0 ∧ x > 1) ∧ (y < 0 ∧ y < 1) φconcat = x = 2 y = − 2 44
  31. Semantic Fusion (x > 0 ∧ (z − y) >

    1) ∧ ((z − x) < 0 ∧ y < 1) z = x + y x = z − y y = z − x φfused = SAT (x > 0 ∧ x > 1) ∧ (y < 0 ∧ y < 1) φconcat = x = 2 y = − 2 z = x + y = 0 45
  32. Semantic Fusion: an Example (declare-fun x () Int ) (declare-fun

    w () Bool ) (assert (= x (- 1)) ) (assert (= w (= x (- 1))) ) (assert w) (declare-fun y () Int ) (declare-fun v () Bool ) (assert (= v (not (= y (- 1)))) ) (assert (ite v false (= y (- 1)))) SAT SAT 46
  33. Semantic Fusion: an Example (declare-fun x () Int ) (declare-fun

    w () Bool ) (assert (= x (- 1)) ) (assert (= w (= x (- 1))) ) (assert w) (declare-fun y () Int ) (declare-fun v () Bool ) (assert (= v (not (= y (- 1)))) ) (assert (ite v false (= y (- 1)))) 47
  34. Semantic Fusion: an Example (declare-fun x () Int ) (declare-fun

    w () Bool ) (declare-fun y () Int ) (declare-fun v () Bool ) (assert (= x (- 1)) ) (assert (= w (= x (- 1))) ) (assert w ) (assert (= v (not (= y (- 1)))) ) (assert (ite v false (= y (- 1)))) 48
  35. Semantic Fusion: an Example (declare-fun x () Int ) (declare-fun

    w () Bool ) (declare-fun y () Int ) (declare-fun v () Bool ) (assert (= x (- 1)) ) (assert (= w (= x (- 1))) ) (assert w ) (assert (= v (not (= y (- 1)))) ) (assert (ite v false (= y (- 1)))) 49
  36. Semantic Fusion: an Example (declare-fun x () Int ) (declare-fun

    w () Bool ) (declare-fun y () Int ) (declare-fun v () Bool ) (declare-fun z () Int ) (assert (= x (- 1)) ) (assert (= w (= x (- 1))) ) (assert w ) (assert (= v (not (= y (- 1)))) ) (assert (ite v false (= y (- 1)))) 50
  37. Semantic Fusion: an Example (declare-fun x () Int ) (declare-fun

    w () Bool ) (declare-fun y () Int ) (declare-fun v () Bool ) (declare-fun z () Int ) (assert (= x (- 1)) ) (assert (= w (= x (- 1))) ) (assert w ) (assert (= v (not (= y (- 1)))) ) (assert (ite v false (= y (- 1)))) z = x * y 51
  38. Semantic Fusion: an Example (declare-fun x () Int ) (declare-fun

    w () Bool ) (declare-fun y () Int ) (declare-fun v () Bool ) (declare-fun z () Int ) (assert (= (div z y) (- 1)) ) (assert (= w (= x (- 1))) ) (assert w ) (assert (= v (not (= y (- 1)))) ) (assert (ite v false (= (div z x) (- 1)))) z = x * y 52
  39. Semantic Fusion: an Example (declare-fun x () Int ) (declare-fun

    w () Bool ) (declare-fun y () Int ) (declare-fun v () Bool ) (declare-fun z () Int ) (assert (= (div z y) (- 1)) ) (assert (= w (= x (- 1))) ) (assert w ) (assert (= v (not (= y (- 1)))) ) (assert (ite v false (= (div z x) (- 1)))) SAT 53
  40. Semantic Fusion: an Example (declare-fun x () Int ) (declare-fun

    w () Bool ) (declare-fun y () Int ) (declare-fun v () Bool ) (declare-fun z () Int ) (assert (= (div z y) (- 1)) ) (assert (= w (= x (- 1))) ) (assert w ) (assert (= v (not (= y (- 1)))) ) (assert (ite v false (= (div z x) (- 1)))) SAT $ cvc4 example.smt 2 unsat 54
  41. Semantic Fusion: an Example (declare-fun x () Int ) (declare-fun

    w () Bool ) (declare-fun y () Int ) (declare-fun v () Bool ) (declare-fun z () Int ) (assert (= (div z y) (- 1)) ) (assert (= w (= x (- 1))) ) (assert w ) (assert (= v (not (= y (- 1)))) ) (assert (ite v false (= (div z x) (- 1)))) SAT https://github.com/CVC4/CVC4/issues/3413 $ cvc4 example.smt 2 unsat 55
  42. Semantic Fusion φ2 = y < 0 ∧ y >

    1 UNSAT UNSAT φ1 = x > 1 ∧ x < 0 56
  43. Semantic Fusion (x > 1 ∧ x < 0) ∨

    (y < 0 ∧ y > 1) φ1 φ2 57
  44. Semantic Fusion (x > 1 ∧ x < 0) ∨

    (y < 0 ∧ y > 1) φ1 φ2 φconcat = UNSAT 58
  45. Semantic Fusion (x > 1 ∧ x < 0) ∨

    (y < 0 ∧ y > 1) φ1 φ2 φconcat = z UNSAT 59
  46. Semantic Fusion φ1 φ2 φconcat = z = x +

    y UNSAT (x > 1 ∧ x < 0) ∨ (y < 0 ∧ y > 1) 60
  47. Semantic Fusion φ1 φ2 φconcat = z = x +

    y x = z − y y = z − x UNSAT (x > 1 ∧ x < 0) ∨ (y < 0 ∧ y > 1) 61
  48. Semantic Fusion (x > 1 ∧ (z − y) <

    0) ∨ ((z − x) < 0 ∧ y > 1) z = x + y x = z − y y = z − x φ1 φ2 φfused = 62
  49. Semantic Fusion φfused = SAT (x > 1 ∧ (z

    − y) < 0) ∨ ((z − x) < 0 ∧ y > 1) 63
  50. Semantic Fusion φfused = SAT x = 2 y =

    2 z = 0 (x > 1 ∧ (z − y) < 0) ∨ ((z − x) < 0 ∧ y > 1) 64
  51. Semantic Fusion φfused = ((x > 1 ∧ (z −

    y) < 0) ∨ ((z − x) < 0 ∧ y > 1)) ∧ z = x + y Fusion Constraint 65
  52. Semantic Fusion φfused = ((x > 1 ∧ (z −

    y) < 0) ∨ ((z − x) < 0 ∧ y > 1)) ∧ z = x + y UNSAT 66
  53. Semantic Fusion: an Example (declare-fun x () Real) (assert (not

    (= (+ (+ 1.0 x) 6.0) (+ 7.0 x)))) (declare-fun y () Real) (declare-fun w () Real) (declare-fun v () Real) (assert (and (< y v) (>= w v) (< (/ w v ) 0) (> y 0))) UNSAT UNSAT 67
  54. Semantic Fusion: an Example (declare-fun x () Real) (assert (not

    (= (+ (+ 1.0 x) 6.0) (+ 7.0 x)))) (declare-fun y () Real) (declare-fun w () Real) (declare-fun v () Real) (assert (and (< y v) (>= w v) (< (/ w v ) 0) (> y 0))) 68
  55. Semantic Fusion: an Example (declare-fun x () Real ) (declare-fun

    y () Real) (declare-fun w () Real) (declare-fun v () Real ) (assert (or (assert (not (= (+ (+ 1.0 x) 6.0) (+ 7.0 x))) ) (assert (and (< y v) (>= w v) (< (/ w v ) 0) (> y 0)))) 69
  56. (declare-fun x () Real ) (declare-fun y () Real) (declare-fun

    w () Real) (declare-fun v () Real ) (assert (or (assert (not (= (+ (+ 1.0 x) 6.0) (+ 7.0 x))) ) (assert (and (< y v) (>= w v) (< (/ w v ) 0) (> y 0)))) Semantic Fusion: an Example 70
  57. (declare-fun x () Real ) (declare-fun y () Real) (declare-fun

    w () Real) (declare-fun v () Real ) (declare-fun z () Real ) (assert (or (assert (not (= (+ (+ 1.0 x) 6.0) (+ 7.0 x))) ) (assert (and (< y v) (>= w v) (< (/ w v ) 0) (> y 0)))) Semantic Fusion: an Example 71
  58. Semantic Fusion: an Example z = x * y (declare-fun

    x () Real ) (declare-fun y () Real) (declare-fun w () Real) (declare-fun v () Real ) (declare-fun z () Real ) (assert (or (assert (not (= (+ (+ 1.0 x) 6.0) (+ 7.0 x))) ) (assert (and (< y v) (>= w v) (< (/ w v ) 0) (> y 0)))) 72
  59. Semantic Fusion: an Example z = x * y (declare-fun

    x () Real ) (declare-fun y () Real) (declare-fun w () Real) (declare-fun v () Real ) (declare-fun z () Real ) (assert (or (assert (not (= (+ (+ 1.0 (/ z y)) 6.0) (+ 7.0 x))) ) (assert (and (< (/ z x) v) (>= w v) (< (/ w v ) 0) (> (/ z x) 0)))) (assert (= z (* x y)) ) (assert (= x (/ z y)) ) (assert (= y (/ z x))) 73
  60. Semantic Fusion: an Example UNSAT (declare-fun x () Real )

    (declare-fun y () Real) (declare-fun w () Real) (declare-fun v () Real ) (declare-fun z () Real ) (assert (or (assert (not (= (+ (+ 1.0 (/ z y)) 6.0) (+ 7.0 x))) ) (assert (and (< (/ z x) v) (>= w v) (< (/ w v ) 0) (> (/ z x) 0))) ) (assert (= z (* x y)) ) (assert (= x (/ z y)) ) (assert (= y (/ z x))) 74
  61. Semantic Fusion: an Example UNSAT % z3 example.smt 2 sat

    (declare-fun x () Real ) (declare-fun y () Real) (declare-fun w () Real) (declare-fun v () Real ) (declare-fun z () Real ) (assert (or (assert (not (= (+ (+ 1.0 (/ z y)) 6.0) (+ 7.0 x))) ) (assert (and (< (/ z x) v) (>= w v) (< (/ w v ) 0) (> (/ z x) 0))) ) (assert (= z (* x y)) ) (assert (= x (/ z y)) ) (assert (= y (/ z x))) 75
  62. Semantic Fusion: an Example UNSAT https://github.com/Z3Prover/z3/issues/2391 % z3 example.smt 2

    sat (declare-fun x () Real ) (declare-fun y () Real) (declare-fun w () Real) (declare-fun v () Real ) (declare-fun z () Real ) (assert (or (assert (not (= (+ (+ 1.0 (/ z y)) 6.0) (+ 7.0 x))) ) (assert (and (< (/ z x) v) (>= w v) (< (/ w v ) 0) (> (/ z x) 0))) ) (assert (= z (* x y)) ) (assert (= x (/ z y)) ) (assert (= y (/ z x))) 76
  63. Empirical Evaluation • Tool YinYang, our realization of Semantic Fusion

    • Bug hunting with YinYang (July-October 2019) 79
  64. Empirical Evaluation • Tool YinYang, our realization of Semantic Fusion

    • Bug hunting with YinYang (July-October 2019) • Bug reduction with C-Reduce 80
  65. Empirical Evaluation • Tool YinYang, our realization of Semantic Fusion

    • Bug hunting with YinYang (July-October 2019) • Bug reduction with C-Reduce • Bug reports on issue trackers of Z3 and CVC4 81
  66. Is Semantic Fusion necessary? 𝜑 1 ConcatFuzz 𝜑 2 SAT

    SAT ∧ 𝜑 1 𝜑 2 ∨ UNSAT UNSAT 98
  67. Is Semantic Fusion necessary? 𝜑 1 ConcatFuzz can only retrigger

    5/50 bugs ConcatFuzz 𝜑 2 SAT SAT ∧ 𝜑 1 𝜑 2 ∨ UNSAT UNSAT 99
  68. Z3 #2376 % cat formula.smt2 (declare-fun a () Real) (declare-fun

    b () Real) (declare-fun c () Real) (declare-fun d () Real) (declare-fun j () Real) (declare-fun e () Real) (assert (not (exists ((f Real)) (=> (and (< (/ 0 0) c) (< (/ 0 (* 2.0 b)) d))(= (= 0.0 a) (not (=> (<= f a) (<= e j)))))))) (check-sat) % cvc4 formula.smt2 unsat %z3 formula.smt2 sat 105
  69. Z3 #2376 % cat formula.smt2 (declare-fun a () Real) (declare-fun

    b () Real) (declare-fun c () Real) (declare-fun d () Real) (declare-fun j () Real) (declare-fun e () Real) (assert (not (exists ((f Real)) (=> (and (< (/ 0 0) c) (< (/ 0 (* 2.0 b)) d))(= (= 0.0 a) (not (=> (<= f a) (<= e j)))))))) (check-sat) % cvc4 formula.smt2 unsat %z3 formula.smt2 sat 106
  70. CVC4 #3412 % cat formula.smt2 (declare-fun a () Int) (declare-fun

    b () Int) (assert (= (div a b) (- 1))) (check-sat) % z3 formula.smt2 sat % cvc4 formula.smt2 unsat 107
  71. CVC4 #3412 % cat formula.smt2 (declare-fun a () Int) (declare-fun

    b () Int) (assert (= (div a b) (- 1))) (check-sat) % z3 formula.smt2 sat % cvc4 formula.smt2 unsat 108
  72. CVC4 #3412 % cat formula.smt2 (declare-fun a () Int) (declare-fun

    b () Int) (assert (= (div a b) (- 1))) (check-sat) % z3 formula.smt2 sat % cvc4 formula.smt2 unsat 109
  73. Z3 #4153 % cat formula.smt2 (declare-fun a () String) (declare-fun

    b () String) (assert (= (str.++ (str.substr "1" 0 (str.len a)) "0") b)) (assert (< (str.to.int b) 0)) (check-sat ) % z3-4.8-7 formula.smt2 unsat % z3 formula.smt2 sa t 110
  74. Z3 #4153 % cat formula.smt2 (declare-fun a () String) (declare-fun

    b () String) (assert (= (str.++ (str.substr "1" 0 (str.len a)) "0") b)) (assert (< (str.to.int b) 0)) (check-sat ) % z3-4.8-7 formula.smt2 unsat % z3 formula.smt2 sa t 111
  75. CVC4 #3217 % cat formula.smt2 (declare-fun a () String) (declare-fun

    b () String) (declare-fun c () String) (declare-fun d () String) (assert (or (not (= (str.suffixof "B" (str.replace "A" b "B")) (= ( str.substr a 0 (str.len b)) "A"))) (not (= (not (= c "A")) (str.suffixof "A" (str.replace "A" c "B")))))) (assert (= a (str.++ (str.++ b "") d))) (check-sat) % z3 formula.smt2 unsat % cvc4 formula.smt2 sa t 112
  76. CVC4 #3217 % cat formula.smt2 (declare-fun a () String) (declare-fun

    b () String) (declare-fun c () String) (declare-fun d () String) (assert (or (not (= (str.suffixof "B" (str.replace "A" b "B")) (= ( str.substr a 0 (str.len b)) "A"))) (not (= (not (= c "A")) (str.suffixof "A" (str.replace "A" c "B")))))) (assert (= a (str.++ (str.++ b "") d))) (check-sat) % z3 formula.smt2 unsat % cvc4 formula.smt2 sa t 113
  77. Z3 #2618 & CVC4 #3357 % cat formula.smt2 (declare-fun a

    () String) (declare-fun b () String) (declare-fun c () String) (assert (str.in.re c (re.* (re.union (str.to.re "aa") (str.to.re ""))))) (assert (= 0 (str.to.int (str.replace a b (str.at a (str.len a)))))) (assert (= a (str.++ b c))) (check-sat) % cvc4 formula.smt2 unsat % z3 formula.smt2 sa t 114
  78. Z3 #2618 & CVC4 #3357 % z3 unreduced.smt2 sa t

    % cvc4 unreduced.smt2 sa t % cat formula.smt2 (declare-fun a () String) (declare-fun b () String) (declare-fun c () String) (assert (str.in.re c (re.* (re.union (str.to.re "aa") (str.to.re ""))))) (assert (= 0 (str.to.int (str.replace a b (str.at a (str.len a)))))) (assert (= a (str.++ b c))) (check-sat) % cvc4 formula.smt2 unsat % z3 formula.smt2 sa t Z3 and CVC4 are both unsound on the unreduced test! 115
  79. Roadmap 1. Introductio n 2. Testing Technique s a) Semantic

    Fusio n b) Type-aware Operator Mutatio n c) Generative Type-Aware Operator Mutation 3. Current and Future Directions 116
  80. Type-aware operator mutation $ cat > formula.smt 2 (assert (forall

    ((a Int) ) (exist ((b Int) ) (distinct (* 2 b) a))) ) (check-sat ) $ cvc4 formula.smt 2 sa t $ z3 formula.smt 2 sat 117
  81. Type-aware operator mutation $ cat > formula.smt 2 (assert (forall

    ((a Int) ) (exist ((b Int) ) (distinct (* 2 b) a))) ) (check-sat ) $ cvc4 formula.smt 2 sa t $ z3 formula.smt 2 sat 118
  82. Type-aware operator mutation (assert (forall ((a Int) ) (exist ((b

    Int) ) (= (* 2 b) a))) ) (check-sat ) $ cat > formula.smt 2 (assert (forall ((a Int) ) (exist ((b Int) ) (distinct (* 2 b) a))) ) (check-sat ) $ cvc4 formula.smt 2 sa t $ z3 formula.smt 2 sat 119
  83. Type-aware operator mutation (assert (forall ((a Int) ) (exist ((b

    Int) ) (= (* 2 b) a))) ) (check-sat ) $ cat > formula.smt 2 (assert (forall ((a Int) ) (exist ((b Int) ) (distinct (* 2 b) a))) ) (check-sat ) $ cvc4 formula.smt 2 sa t $ z3 formula.smt 2 sat Int Int Int Int 120
  84. (assert (forall ((a Int) ) (exist ((b Int) ) (=

    (* 2 b) a))) ) (check-sat ) $ cat > formula.smt 2 (assert (forall ((a Int) ) (exist ((b Int) ) (distinct (* 2 b) a))) ) (check-sat ) $ cvc4 formula.smt 2 sa t $ z3 formula.smt 2 sat Int Int Int Int = > < > = < = Type-aware operator mutation Operator candidates: 121 121
  85. (assert (forall ((a Int) ) (exist ((b Int) ) (=

    (* 2 b) a))) ) (check-sat ) $ cat > formula.smt 2 (assert (forall ((a Int) ) (exist ((b Int) ) (distinct (* 2 b) a))) ) (check-sat ) $ cvc4 formula.smt 2 sa t $ z3 formula.smt 2 sat Int Int Int Int Type-aware operator mutation Operator candidates: = > < > = < = 122
  86. Type-aware operator mutation (assert (forall ((a Int) ) (exist ((b

    Int) ) (= (* 2 b) a))) ) (check-sat ) $ cat > formula.smt 2 (assert (forall ((a Int) ) (exist ((b Int) ) (distinct (* 2 b) a))) ) (check-sat ) $ cvc4 formula.smt 2 sa t $ z3 formula.smt 2 sat 123
  87. Type-aware operator mutation (assert (forall ((a Int) ) (exist ((b

    Int) ) (= (* 2 b) a))) ) (check-sat ) $ cat > bug.smt2 $ cat > formula.smt 2 (assert (forall ((a Int) ) (exist ((b Int) ) (distinct (* 2 b) a))) ) (check-sat ) $ cvc4 formula.smt 2 sa t $ z3 formula.smt 2 sat $ cvc4 bug.smt 2 unsa t $ z3 bug.smt 2 sat 124
  88. Type-aware operator mutation (assert (forall ((a Int) ) (exist ((b

    Int) ) (= (* 2 b) a))) ) (check-sat ) $ cat > bug.smt2 $ cat > formula.smt 2 (assert (forall ((a Int) ) (exist ((b Int) ) (distinct (* 2 b) a))) ) (check-sat ) $ cvc4 formula.smt 2 sa t $ z3 formula.smt 2 sat $ cvc4 bug.smt 2 unsa t $ z3 bug.smt 2 sat ✘ ✔ 125
  89. Type-aware operator mutation (assert (forall ((a Int) ) (exist ((b

    Int) ) (= (* 2 b) a))) ) (check-sat ) $ cat > bug.smt2 $ cat > formula.smt 2 (assert (forall ((a Int) ) (exist ((b Int) ) (distinct (* 2 b) a))) ) (check-sat ) $ cvc4 formula.smt 2 sa t $ z3 formula.smt 2 sat $ cvc4 bug.smt 2 unsa t $ z3 bug.smt 2 sat https://github.com/Z3Prover/z3/issues/3973 ✔ ✘ 126
  90. Type-aware operator mutation chain (declare-fun a () Real ) (assert

    (> (/ (* 2 a) a) (* a a ) 1)) (check-sat) 128
  91. (declare-fun a () Real ) (assert (> (/ (* 2

    a) a) (* a a ) 1)) (check-sat) Type-aware operator mutation chain 129
  92. (declare-fun a () Real ) (assert (> (/ (* 2

    a) a) (* a a ) 1)) (check-sat) Type-aware operator mutation chain (declare-fun a () Real ) (assert (= (/ (* 2 a) a) (* a a ) 1)) (check-sat) 130
  93. (declare-fun a () Real ) (assert (> (/ (* 2

    a) a) (* a a ) 1)) (check-sat) Type-aware operator mutation chain (declare-fun a () Real ) (assert (= (/ (* 2 a) a) (* a a ) 1)) (check-sat) 131
  94. (declare-fun a () Real ) (assert (> (/ (* 2

    a) a) (* a a ) 1)) (check-sat) Type-aware operator mutation chain (declare-fun a () Real ) (assert (= (/ (* 2 a) a) (* a a ) 1)) (check-sat) (declare-fun a () Real ) (assert (= (/ (* 2 a) a) (/ a a ) 1)) (check-sat) 132
  95. (declare-fun a () Real ) (assert (> (/ (* 2

    a) a) (* a a ) 1)) (check-sat) Type-aware operator mutation chain (declare-fun a () Real ) (assert (= (/ (* 2 a) a) (* a a ) 1)) (check-sat) (declare-fun a () Real ) (assert (= (/ (* 2 a) a) (/ a a ) 1)) (check-sat) … 133
  96. (declare-fun a () Real ) (assert (= (/ (* 2

    a) a) (/ a a ) 1)) (check-sat) Type-aware operator mutation chain 134
  97. (declare-fun a () Real ) (assert (= (/ (* 2

    a) a) (/ a a ) 1)) (check-sat) Type-aware operator mutation chain $ cat > bug.smt2 $ cvc4 bug.smt 2 sa t $ z3 bug.smt 2 unsat 135
  98. (declare-fun a () Real ) (assert (= (/ (* 2

    a) a) (/ a a ) 1)) (check-sat) Type-aware operator mutation chain $ cat > bug.smt2 $ cvc4 bug.smt 2 sa t $ z3 bug.smt 2 unsat ✘ ✔ https://github.com/Z3Prover/z3/issues/2715 136
  99. (declare-fun a () Real ) (assert (= (/ (* 2

    a) a) (/ a a ) 1)) (check-sat) Type-aware operator mutation chain $ cat > bug.smt2 $ cvc4 bug.smt 2 sa t $ z3 bug.smt 2 unsat ✘ ✔ https://github.com/Z3Prover/z3/issues/2715 137
  100. Empirical Evaluation • Tool: OpFuzz • Bug hunting: Sep 2019

    - Oct 2020 • Testing targets: Z3 and CVC4 • Seeds: SMT-LIB benchmarks (300k+ formulas) 139
  101. Empirical Evaluation • Tool: OpFuzz • Bug hunting: Sep 2019

    - Oct 2020 • Testing targets: Z3 and CVC4 • Seeds: SMT-LIB benchmarks (300k+ formulas) 140
  102. Empirical Evaluation • Tool: OpFuzz • Bug hunting: Sep 2019

    - Oct 2020 • Testing targets: Z3 and CVC4 • Seeds: SMT-LIB benchmarks (300k+ formulas) 141
  103. Empirical Evaluation • Tool: OpFuzz • Bug hunting: Sep 2019

    - Oct 2020 • Testing targets: Z3 and CVC4 • Seeds: SMT-LIB benchmarks (300k+ formulas) 142
  104. Bug Findings Status Z3 CVC4 Total Reported 811 281 1,092

    Con fi rmed 578 241 819 Fixed 521 164 685 Duplicate 85 18 106 Bug status as of 30 Oct 2020 143
  105. Bug Findings Status Z3 CVC4 Total Reported 811 281 1,092

    Con fi rmed 578 241 819 Fixed 521 164 685 Duplicate 85 18 106 Bug status as of 30 Oct 2020 144
  106. Bug Findings Status Z3 CVC4 Total Reported 811 281 1,092

    Con fi rmed 578 241 819 Fixed 521 164 685 Duplicate 85 18 106 Bug status as of 30 Oct 2020 145
  107. Bug Findings Status Z3 CVC4 Total Reported 811 281 1,092

    Con fi rmed 578 241 819 Fixed 521 164 685 Duplicate 85 18 106 Bug status as of 30 Oct 2020 146
  108. Bug Findings Status Z3 CVC4 Total Soundness 157 27 184

    Invalid model 83 19 102 Crash 316 185 501 Others 22 10 32 Types of con fi rmed bugs 147
  109. Bug Findings Status Z3 CVC4 Total Soundness 157 27 184

    Invalid model 83 19 102 Crash 316 185 501 Others 22 10 32 Types of con fi rmed bugs 148
  110. Bug Findings Status Z3 CVC4 Total Soundness 157 27 184

    Invalid model 83 19 102 Crash 316 185 501 Others 22 10 32 Types of con fi rmed bugs 149
  111. Bug Findings Logic Z3 CVC4 Total Soundness 157 27 184

    Invalid model 83 19 102 Crash 316 185 501 Others 22 10 32 Types of con fi rmed bugs 150
  112. Bug Findings Number of options for triggering the bugs #Options

    Z3 CVC4 Total Default 388 101 489 1 109 67 176 2 45 31 76 >= 3 36 42 78 151
  113. Bug Findings Number of options for triggering the bugs #Options

    Z3 CVC4 Total Default 388 101 489 1 109 67 176 2 45 31 76 >= 3 36 42 78 152
  114. Bug Findings Number of options for triggering the bugs #Options

    Z3 CVC4 Total Default 388 101 489 1 109 67 176 2 45 31 76 >= 3 36 42 78 153
  115. Bugs in Z3 Bugs in CVC4 Approach soundness all soundness

    all StringFuzz 0 0 - - BanditFuzz 0 0 - - Bugariu et al. 1 3 0 0 YinYang 24 36 5 8 STORM 17 21 0 0 OpFuzz 114 316 11 185 Comparison to Previous Approaches Con fi rmed bugs in the default modes of the solvers 154
  116. Comparison to Previous Approaches Con fi rmed bugs in the

    default modes of the solvers Bugs in Z3 Bugs in CVC4 Approach soundness all soundness all StringFuzz 0 0 - - BanditFuzz 0 0 - - Bugariu et al. 1 3 0 0 YinYang 24 36 5 8 STORM 17 21 0 0 OpFuzz 114 316 11 185 155
  117. Comparison to Previous Approaches OpFuzz found many more soundness bugs

    in Z3 and CVC4’s default modes than all previous approaches Bugs in Z3 Bugs in CVC4 Approach soundness all soundness all StringFuzz 0 0 - - BanditFuzz 0 0 - - Bugariu et al. 1 3 0 0 YinYang 24 36 5 8 STORM 17 21 0 0 OpFuzz 114 316 11 185 156
  118. Z3 Soundness Bug #2832 $ cat bug.smt 2 (declare-const a

    (_ BitVec 8) ) (declare-const b (_ BitVec 8)) (declare-const c (_ BitVec 8)) (assert (= (bvxnor a b c ) (bvxnor (bvxnor a b) c))) (check-sat ) $ cvc4 bug.smt 2 sa t $ z3 bug.smt 2 unsat ✘ ✔ https://github.com/Z3Prover/z3/issues/2832 157
  119. Z3 Soundness Bug #2832 $ cat bug.smt 2 (declare-const a

    (_ BitVec 8) ) (declare-const b (_ BitVec 8)) (declare-const c (_ BitVec 8)) (assert (= (bvxnor a b c) (bvxnor (bvxnor a b) c))) (check-sat ) $ cvc4 bug.smt 2 sa t $ z3 bug.smt 2 unsat ✘ ✔ https://github.com/Z3Prover/z3/issues/2832 158
  120. Z3 Soundness Bug #2832 (bvxnor true true true) = (not

    (bvxor true true true) ) (bvnxor (bvnxor true true) true)) = (not (bvxor (bvxor true true) true))) (bvnxor true true) = (not (bvxor false true)) ) true false 
 ≠ (bvxnor a b c) (not (bvxor a b c)) ≠ 159
  121. Z3 Soundness Bug #2832 (bvxnor true true true) = (not

    (bvxor true true true) ) (bvnxor (bvnxor true true) true)) = (not (bvxor (bvxor true true) true))) (bvnxor true true) = (not (bvxor false true)) ) true false 
 ≠ (bvxnor a b c) (not (bvxor a b c)) ≠ 160
  122. Z3 Soundness Bug #2832 (bvxnor true true true) = (not

    (bvxor true true true) ) (bvnxor (bvnxor true true) true)) = (not (bvxor (bvxor true true) true)) (bvnxor true true) = (not (bvxor false true)) ) true false 
 ≠ (bvxnor a b c) (not (bvxor a b c)) ≠ 161
  123. Z3 Soundness Bug #2832 (bvxnor true true true) = (not

    (bvxor true true true) ) (bvnxor (bvnxor true true) true)) = (not (bvxor (bvxor true true) true)) (bvnxor true true) = (not (bvxor false true) ) true false 
 ≠ (bvxnor a b c) (not (bvxor a b c)) ≠ 162
  124. Z3 Soundness Bug #2832 (bvxnor true true true) = (not

    (bvxor true true true) ) (bvnxor (bvnxor true true) true)) = (not (bvxor (bvxor true true) true)) (bvnxor true true) = (not (bvxor false true) ) true false 
 ≠ (bvxnor a b c) (not (bvxor a b c)) ≠ 163
  125. Z3 Soundness Bug #2832 $ cat bug.smt 2 (declare-const a

    (_ BitVec 8) ) (declare-const b (_ BitVec 8)) (declare-const c (_ BitVec 8)) (assert (= (bvxnor a b c) (bvxnor (bvxnor a b) c))) (check-sat ) $ cvc4 bug.smt 2 sa t $ z3 bug.smt 2 unsat ✘ ✔ https://github.com/Z3Prover/z3/issues/2832 Root Cause: Unsound rewriter 164
  126. Z3 Soundness Bug #2830 $ cat bug.smt 2 (declare-fun a

    () Int ) (declare-fun b (Int) Bool ) (assert (b 0)) (push ) (assert (distinct true (= a 0) (not (b 0)))) (check-sat ) $ cvc4 bug.smt 2 unsa t $ z3 bug.smt 2 sat ✘ ✔ https://github.com/Z3Prover/z3/issues/2830 165
  127. Z3 Soundness Bug #2830 $ cat bug.smt 2 (declare-fun a

    () Int ) (declare-fun b (Int) Bool ) (assert (b 0)) (push ) (assert (distinct true (= a 0) (not (b 0)))) (check-sat ) $ cvc4 bug.smt 2 unsa t $ z3 bug.smt 2 sat ✘ ✔ https://github.com/Z3Prover/z3/issues/2830 Root Cause: Last argument omitted in distinct operator 166
  128. CVC4 Soundness Bug #3497 $ cat bug.smt 2 (declare-fun x

    () String) (declare-fun y () String) (assert (= (str.indexof x y 1) (str.len x))) (assert (str.contains x y)) (check-sat ) $ z3 bug.smt 2 sa t $ cvc4 bug.smt 2 unsat ✘ ✔ https://github.com/CVC4/CVC4/issues/3497 167
  129. CVC4 Soundness Bug #3497 $ cat bug.smt 2 (declare-fun x

    () String) (declare-fun y () String) (assert (= (str.indexof x y 1) (str.len x))) (assert (str.contains x y)) (check-sat ) $ z3 bug.smt 2 sa t $ cvc4 bug.smt 2 unsat ✘ ✔ https://github.com/CVC4/CVC4/issues/3497 168
  130. CVC4 Soundness Bug #3497 $ cat bug.smt 2 (declare-fun x

    () String) (declare-fun y () String) (assert (= (str.indexof x y 1) (str.len x))) (assert (str.contains x y)) (check-sat ) $ z3 bug.smt 2 sa t $ cvc4 bug.smt 2 unsat ✘ ✔ https://github.com/CVC4/CVC4/issues/3497 169
  131. CVC4 Soundness Bug #4469 $ cat bug.smt 2 (set-logic QF_AUFBVLIA

    ) (declare-fun a () Int) (declare-fun b (Int) Int) (assert (distinct (b a) (b (b a)))) (check-sat ) $ z3 bug.smt 2 sa t $ cvc4 bug.smt 2 unsat ✘ ✔ https://github.com/CVC4/CVC4/issues/4469 170
  132. CVC4 Soundness Bug #4469 $ cat bug.smt 2 (set-logic QF_AUFBVLIA

    ) (declare-fun a () Int) (declare-fun b (Int) Int) (assert (distinct (b a) (b (b a)))) (check-sat ) $ z3 bug.smt 2 sa t $ cvc4 bug.smt 2 unsat ✘ ✔ https://github.com/CVC4/CVC4/issues/4469 171
  133. CVC4 Soundness Bug #3475 $ cat bug.smt 2 (set-logic ALL)


    (declare-fun x () Real ) (assert (< x 0) ) (assert (not (= (/ (sqrt x) (sqrt x)) x)) ) (check-sat ) $ z3 bug.smt 2 sa t $ cvc4 bug.smt 2 unsat
 https://github.com/CVC4/CVC4/issues/3475 ✘ ✔ 172
  134. Roadmap 1. Introductio n 2. Testing Technique s a) Semantic

    Fusio n b) Type-aware Operator Mutatio n c) Generative Type-Aware Operator Mutation 3. Current and Future Directions 173
  135. Generative Type-Aware Mutation • Idea: Extend OpFuzz • Expressions •

    Support Generation: Control the size of Formula • Formula can grow & shrink 174
  136. $ cat formula.smt 2 (declare-fun x () String) (assert (>

    (- (str.to_int (str.++ x x))) 0)) (check-sat) $ cvc4 formula.smt 2 sa t $ z3 formula.smt 2 sat Generative Type-Aware Mutation 175 Generative Type-Aware Mutation
  137. $ cat formula.smt 2 (declare-fun x () String) (assert (>

    (- (str.to_int (str.++ x x))) 0)) (check-sat) $ cvc4 formula.smt 2 sa t $ z3 formula.smt 2 sat Bool: (> (- (str.to_int (str.++ x x))) 0) ) Int : 0, (- (str.to_int (str.++ x x))) 0), … String : (str.++ x x), x 176 Generative Type-Aware Mutation
  138. $ cat formula.smt 2 (declare-fun x () String) (assert (>

    (- (str.to_int (str.++ x x))) 0)) (check-sat) $ cvc4 formula.smt 2 sa t $ z3 formula.smt 2 sat $ cat formula.smt 2 (declare-fun x () String) (assert (> (- (str.to_int (str.++ x))) 0)) (check-sat) $ cvc4 formula.smt 2 sa t $ z3 formula.smt 2 Sat 177 Generative Type-Aware Mutation
  139. $ cat formula.smt 2 (declare-fun x () String) (assert (>

    (- (str.to_int (str.++ x x))) 0)) (check-sat) $ cvc4 formula.smt 2 sa t $ z3 formula.smt 2 sat $ cat formula.smt 2 (declare-fun x () String) (assert (> (- (str.to_int (str.++ x))) 0)) (check-sat) $ cvc4 formula.smt 2 sa t $ z3 formula.smt 2 Sat String 178 Generative Type-Aware Mutation
  140. $ cat formula.smt 2 (declare-fun x () String) (assert (>

    (- (str.to_int (str.++ x x))) 0)) (check-sat) $ cvc4 formula.smt 2 sa t $ z3 formula.smt 2 sat $ cat formula.smt 2 (declare-fun x () String) (assert (> (- (str.to_int (str.++ x))) 0)) (check-sat) $ cvc4 formula.smt 2 sa t $ z3 formula.smt 2 Sat String Bool: (> (- (str.to_int (str.++ x x))) 0) ) Int : 0, (- (str.to_int (str.++ x x))) 0), … String : (str.++ x x), x 179 Generative Type-Aware Mutation
  141. $ cat formula.smt 2 (declare-fun x () String) (assert (>

    (- (str.to_int (str.++ x x))) 0)) (check-sat) $ cvc4 formula.smt 2 sa t $ z3 formula.smt 2 sat $ cat formula.smt 2 (declare-fun x () String) (assert (> (- (str.to_int (str.++ x))) 0)) (check-sat) $ cvc4 formula.smt 2 sa t $ z3 formula.smt 2 Sat String Bool: (> (- (str.to_int (str.++ x x))) 0) ) Int : 0, (- (str.to_int (str.++ x x))) 0), … String : (str.++ x x), x Operator candidates: str.from_int str.replace str.++ ... 180 Generative Type-Aware Mutation
  142. $ cat formula.smt 2 (declare-fun x () String) (assert (>

    (- (str.to_int (str.++ x x))) 0)) (check-sat) $ cvc4 formula.smt 2 sa t $ z3 formula.smt 2 sat $ cat formula.smt 2 (declare-fun x () String) (assert (> (- (str.to_int (str.++ str.from_int x))) 0)) (check-sat) $ cvc4 formula.smt 2 sa t $ z3 formula.smt 2 Sat String Bool: (> (- (str.to_int (str.++ x x))) 0) ) Int : 0,, (- (str.to_int (str.++ x x))) 0), … String : (str.++ x x), x (str.from_int Int String) String 181 Generative Type-Aware Mutation
  143. $ cat formula.smt 2 (declare-fun x () String) (assert (>

    (- (str.to_int (str.++ x x))) 0)) (check-sat) $ cvc4 formula.smt 2 sa t $ z3 formula.smt 2 sat $ cat mutant.smt 2 (declare-fun x () String) (assert (> (- (str.to_int (str.++ (str.from_int 0) x))) 0)) (check-sat) $ cvc4 formula.smt 2 sa t $ z3 formula.smt 2 Sat 182 Generative Type-Aware Mutation
  144. $ cat formula.smt 2 (declare-fun x () String) (assert (>

    (- (str.to_int (str.++ x x))) 0)) (check-sat) $ cvc4 formula.smt 2 sa t $ z3 formula.smt 2 sat $ cat mutant.smt 2 (declare-fun x () String) (assert (> (- (str.to_int (str.++ (str.from_int 0) x))) 0)) (check-sat) $ cvc4 formula.smt 2 sa t $ z3 formula.smt 2 unsat 183 Generative Type-Aware Mutation
  145. More Bugs Status Z3 CVC4 Total Reported 177 60 237

    Con fi rmed 135 54 189 Fixed 132 44 176 Duplicate 9 5 14 Bug status as of 30 Sep 2021 184
  146. Roadmap 1. Introductio n 2. Testing Technique s a) Semantic

    Fusio n b) Type-aware Operator Mutatio n c) Generative Type-Aware Operator Mutation 3. Current and Future Directions 185
  147. Current and Future Directions Yin-Yang [PLDI ’20] OpFuzz [OOPSLA ’20]

    TypeFuzz [OOPSLA ’21] Correctness Robust & Fast SMT Solvers Performance 186
  148. Current and Future Directions Yin-Yang [PLDI ’20] OpFuzz [OOPSLA ’20]

    TypeFuzz [OOPSLA ’21] Correctness Robust & Fast SMT Solvers Performance 187
  149. “Testing can only show the presence of errors, not their

    absence.” 
 - Edsger W. Dijkstra 188
  150. Current and Future Directions Yin-Yang [PLDI ’20] OpFuzz [OOPSLA ’20]

    TypeFuzz [OOPSLA ’21] Correctness Robust & Fast SMT Solvers Performance 190
  151. SMT Solver Flags Z3 has 300+ fl ags, all of

    which could in fl uence its performance 192
  152. Zhendong Su Prof@ETH Zurich Chengyu Zhang Postdoc@ETH Zurich Collaborators Jiwon

    Park Intern@ETH Zurich ➜ Ph.D. student@UC Berkeley 195
  153. CVC4 Soundness Bug #3475 $ cat bug.smt 2 (set-logic ALL)


    (declare-fun x () Real ) (assert (< x 0) ) (assert (not (= (/ (sqrt x) (sqrt x)) x)) ) (check-sat ) $ z3 bug.smt 2 sa t $ cvc4 bug.smt 2 unsat
 https://github.com/CVC4/CVC4/issues/3475 ✘ ✔ Formula is satisfiable negative x = -1 (/ sqrt(-1) sqrt(-1)) = 1 198
  154. CVC4 Soundness Bug #3475 Simplification: 
 (sqrt x) = choice

    real y s.t. x*x = y Problem: Inadmissible for negative y (since no real x exists) 200