comparison src/iflow.sml @ 2216:70ec9bb337be

Progress towards invalidation based on equalities of fields.
author Ziv Scully <ziv@mit.edu>
date Mon, 10 Nov 2014 22:04:40 -0500
parents 4d64af730e35
children 278e10629ba1
comparison
equal deleted inserted replaced
2215:639e62ca2530 2216:70ec9bb337be
14 * 14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
113 p_list p_exp es, 113 p_list p_exp es,
114 string ")"] 114 string ")"]
115 | PCon1 s => box [string (s ^ "("), 115 | PCon1 s => box [string (s ^ "("),
116 p_list p_exp es, 116 p_list p_exp es,
117 string ")"] 117 string ")"]
118 | Eq => p_bop "=" es 118 | Cmp Eq => p_bop "=" es
119 | Ne => p_bop "<>" es 119 | Cmp Ne => p_bop "<>" es
120 | Lt => p_bop "<" es 120 | Cmp Lt => p_bop "<" es
121 | Le => p_bop "<=" es 121 | Cmp Le => p_bop "<=" es
122 | Gt => p_bop ">" es 122 | Cmp Gt => p_bop ">" es
123 | Ge => p_bop ">=" es 123 | Cmp Ge => p_bop ">=" es
124 124
125 fun p_prop p = 125 fun p_prop p =
126 case p of 126 case p of
127 True => string "True" 127 True => string "True"
128 | False => string "False" 128 | False => string "False"
129 | Unknown => string "??" 129 | Unknown => string "??"
130 | And (p1, p2) => box [string "(", 130 | Lop (And, p1, p2) => box [string "(",
131 p_prop p1, 131 p_prop p1,
132 string ")", 132 string ")",
133 space, 133 space,
134 string "&&", 134 string "&&",
135 space, 135 space,
136 string "(", 136 string "(",
137 p_prop p2, 137 p_prop p2,
138 string ")"] 138 string ")"]
139 | Or (p1, p2) => box [string "(", 139 | Lop (Or, p1, p2) => box [string "(",
140 p_prop p1, 140 p_prop p1,
141 string ")", 141 string ")",
142 space, 142 space,
143 string "||", 143 string "||",
144 space, 144 space,
145 string "(", 145 string "(",
146 p_prop p2, 146 p_prop p2,
147 string ")"] 147 string ")"]
148 | Reln (r, es) => p_reln r es 148 | Reln (r, es) => p_reln r es
149 | Cond (e, p) => box [string "(", 149 | Cond (e, p) => box [string "(",
150 p_exp e, 150 p_exp e,
151 space, 151 space,
152 string "==", 152 string "==",
516 Rep = ref NONE, 516 Rep = ref NONE,
517 Cons = ref SM.empty, 517 Cons = ref SM.empty,
518 Variety = Nothing, 518 Variety = Nothing,
519 Known = ref (!(#Known (unNode r))), 519 Known = ref (!(#Known (unNode r))),
520 Ge = ref NONE}) 520 Ge = ref NONE})
521 521
522 val r'' = ref (Node {Id = nodeId (), 522 val r'' = ref (Node {Id = nodeId (),
523 Rep = ref NONE, 523 Rep = ref NONE,
524 Cons = #Cons (unNode r), 524 Cons = #Cons (unNode r),
525 Variety = Recrd (ref (SM.insert (SM.empty, f, r')), false), 525 Variety = Recrd (ref (SM.insert (SM.empty, f, r')), false),
526 Known = #Known (unNode r), 526 Known = #Known (unNode r),
527 Ge = ref NONE}) 527 Ge = ref NONE})
528 in 528 in
529 #Rep (unNode r) := SOME r''; 529 #Rep (unNode r) := SOME r'';
530 r' 530 r'
531 end 531 end
532 | _ => raise Contradiction 532 | _ => raise Contradiction
533 end 533 end
534 in 534 in
535 rep e 535 rep e
536 end 536 end
537 537
685 cons := SM.insert (!cons, f, r'); 685 cons := SM.insert (!cons, f, r');
686 #Rep (unNode r) := SOME r' 686 #Rep (unNode r) := SOME r'
687 end 687 end
688 | _ => raise Contradiction 688 | _ => raise Contradiction
689 end 689 end
690 | (Eq, [e1, e2]) => 690 | (Cmp Eq, [e1, e2]) =>
691 markEq (representative (db, e1), representative (db, e2)) 691 markEq (representative (db, e1), representative (db, e2))
692 | (Ge, [e1, e2]) => 692 | (Cmp Ge, [e1, e2]) =>
693 let 693 let
694 val r1 = representative (db, e1) 694 val r1 = representative (db, e1)
695 val r2 = representative (db, e2) 695 val r2 = representative (db, e2)
696 in 696 in
697 case !(#Ge (unNode (repOf r2))) of 697 case !(#Ge (unNode (repOf r2))) of
732 | _ => false) 732 | _ => false)
733 | (PCon1 f, [e]) => 733 | (PCon1 f, [e]) =>
734 (case #Variety (unNode (representative (db, e))) of 734 (case #Variety (unNode (representative (db, e))) of
735 Dt1 (f', _) => f' = f 735 Dt1 (f', _) => f' = f
736 | _ => false) 736 | _ => false)
737 | (Eq, [e1, e2]) => 737 | (Cmp Eq, [e1, e2]) =>
738 let 738 let
739 val r1 = representative (db, e1) 739 val r1 = representative (db, e1)
740 val r2 = representative (db, e2) 740 val r2 = representative (db, e2)
741 in 741 in
742 repOf r1 = repOf r2 742 repOf r1 = repOf r2
743 end 743 end
744 | (Ge, [e1, e2]) => 744 | (Cmp Ge, [e1, e2]) =>
745 let 745 let
746 val r1 = representative (db, e1) 746 val r1 = representative (db, e1)
747 val r2 = representative (db, e2) 747 val r2 = representative (db, e2)
748 in 748 in
749 case (!(#Ge (unNode (repOf r1))), #Variety (unNode (repOf r2))) of 749 case (!(#Ge (unNode (repOf r1))), #Variety (unNode (repOf r2))) of
846 () 846 ()
847 else 847 else
848 (hyps := (n', hs, ref false); 848 (hyps := (n', hs, ref false);
849 Cc.clear db; 849 Cc.clear db;
850 app (fn a => Cc.assert (db, a)) hs) 850 app (fn a => Cc.assert (db, a)) hs)
851 end 851 end
852 852
853 fun useKeys () = 853 fun useKeys () =
854 let 854 let
855 val changed = ref false 855 val changed = ref false
856 856
870 if tab' = tab andalso 870 if tab' = tab andalso
871 List.exists (List.all (fn f => 871 List.exists (List.all (fn f =>
872 let 872 let
873 val r = 873 val r =
874 Cc.check (db, 874 Cc.check (db,
875 AReln (Eq, [Proj (r1, f), 875 AReln (Cmp Eq, [Proj (r1, f),
876 Proj (r2, f)])) 876 Proj (r2, f)]))
877 in 877 in
878 (*Print.prefaces "Fs" 878 (*Print.prefaces "Fs"
879 [("tab", 879 [("tab",
880 Print.PD.string tab), 880 Print.PD.string tab),
886 Print.PD.string 886 Print.PD.string
887 (Bool.toString r))];*) 887 (Bool.toString r))];*)
888 r 888 r
889 end)) ks then 889 end)) ks then
890 (changed := true; 890 (changed := true;
891 Cc.assert (db, AReln (Eq, [r1, r2])); 891 Cc.assert (db, AReln (Cmp Eq, [r1, r2]));
892 finder (hyps, acc)) 892 finder (hyps, acc))
893 else 893 else
894 finder (hyps, a :: acc) 894 finder (hyps, a :: acc)
895 | a :: hyps => finder (hyps, a :: acc) 895 | a :: hyps => finder (hyps, a :: acc)
896 896
1113 val cname = "cookie/" ^ cname 1113 val cname = "cookie/" ^ cname
1114 val n = !hnames 1114 val n = !hnames
1115 val (_, hs, _) = !hyps 1115 val (_, hs, _) = !hyps
1116 in 1116 in
1117 hnames := n + 1; 1117 hnames := n + 1;
1118 hyps := (n, List.filter (fn AReln (Eq, [_, Func (Other f, [])]) => f <> cname | _ => true) hs, ref false) 1118 hyps := (n, List.filter (fn AReln (Cmp Eq, [_, Func (Other f, [])]) => f <> cname | _ => true) hs, ref false)
1119 end 1119 end
1120 1120
1121 fun check a = Cc.check (db, a) 1121 fun check a = Cc.check (db, a)
1122 1122
1123 fun debug () = 1123 fun debug () =
1136 | x :: ls => 1136 | x :: ls =>
1137 let 1137 let
1138 val ls = removeDups ls 1138 val ls = removeDups ls
1139 in 1139 in
1140 if List.exists (fn x' => x' = x) ls then 1140 if List.exists (fn x' => x' = x) ls then
1141 ls 1141 ls
1142 else 1142 else
1143 x :: ls 1143 x :: ls
1144 end 1144 end
1145 1145
1146 fun deinj env e = 1146 fun deinj env e =
1169 | SqTrue => inl (Func (DtCon0 "Basis.bool.True", [])) 1169 | SqTrue => inl (Func (DtCon0 "Basis.bool.True", []))
1170 | SqFalse => inl (Func (DtCon0 "Basis.bool.False", [])) 1170 | SqFalse => inl (Func (DtCon0 "Basis.bool.False", []))
1171 | Null => inl (Func (DtCon0 "None", [])) 1171 | Null => inl (Func (DtCon0 "None", []))
1172 | SqNot e => 1172 | SqNot e =>
1173 inr (case expIn e of 1173 inr (case expIn e of
1174 inl e => Reln (Eq, [e, Func (DtCon0 "Basis.bool.False", [])]) 1174 inl e => Reln (Cmp Eq, [e, Func (DtCon0 "Basis.bool.False", [])])
1175 | inr _ => Unknown) 1175 | inr _ => Unknown)
1176 | Field (v, f) => inl (Proj (rvOf v, f)) 1176 | Field (v, f) => inl (Proj (rvOf v, f))
1177 | Computed _ => default () 1177 | Computed _ => default ()
1178 | Binop (bo, e1, e2) => 1178 | Binop (bo, e1, e2) =>
1179 let 1179 let
1180 val e1 = expIn e1 1180 val e1 = expIn e1
1181 val e2 = expIn e2 1181 val e2 = expIn e2
1182 in 1182 in
1183 inr (case (bo, e1, e2) of 1183 inr (case (bo, e1, e2) of
1184 (Exps f, inl e1, inl e2) => f (e1, e2) 1184 (RCmp c, inl e1, inl e2) => Reln (Cmp c, [e1, e2])
1185 | (Props f, v1, v2) => 1185 | (RLop l, v1, v2) =>
1186 let 1186 let
1187 fun pin v = 1187 fun pin v =
1188 case v of 1188 case v of
1189 inl e => Reln (Eq, [e, Func (DtCon0 "Basis.bool.True", [])]) 1189 inl e => Reln (Cmp Eq, [e, Func (DtCon0 "Basis.bool.True", [])])
1190 | inr p => p 1190 | inr p => p
1191 in 1191 in
1192 f (pin v1, pin v2) 1192 Lop (l, pin v1, pin v2)
1193 end 1193 end
1194 | _ => Unknown) 1194 | _ => Unknown)
1195 end 1195 end
1196 | SqKnown e => 1196 | SqKnown e =>
1197 (case expIn e of 1197 (case expIn e of
1203 | SOME e => e) 1203 | SOME e => e)
1204 | SqFunc (f, e) => 1204 | SqFunc (f, e) =>
1205 (case expIn e of 1205 (case expIn e of
1206 inl e => inl (Func (Other f, [e])) 1206 inl e => inl (Func (Other f, [e]))
1207 | _ => default ()) 1207 | _ => default ())
1208 1208
1209 | Unmodeled => inl (Func (Other "allow", [rv ()])) 1209 | Unmodeled => inl (Func (Other "allow", [rv ()]))
1210 end 1210 end
1211 in 1211 in
1212 expIn 1212 expIn
1213 end 1213 end
1217 fun go p k = 1217 fun go p k =
1218 case p of 1218 case p of
1219 True => (k () handle Cc.Contradiction => ()) 1219 True => (k () handle Cc.Contradiction => ())
1220 | False => () 1220 | False => ()
1221 | Unknown => () 1221 | Unknown => ()
1222 | And (p1, p2) => go p1 (fn () => go p2 k) 1222 | Lop (And, p1, p2) => go p1 (fn () => go p2 k)
1223 | Or (p1, p2) => 1223 | Lop (Or, p1, p2) =>
1224 let 1224 let
1225 val saved = save () 1225 val saved = save ()
1226 in 1226 in
1227 go p1 k; 1227 go p1 k;
1228 restore saved; 1228 restore saved;
1349 case #Where r of 1349 case #Where r of
1350 NONE => final () 1350 NONE => final ()
1351 | SOME e => 1351 | SOME e =>
1352 let 1352 let
1353 val p = case expIn e of 1353 val p = case expIn e of
1354 inl e => Reln (Eq, [e, Func (DtCon0 "Basis.bool.True", [])]) 1354 inl e => Reln (Cmp Eq, [e, Func (DtCon0 "Basis.bool.True", [])])
1355 | inr p => p 1355 | inr p => p
1356 1356
1357 val saved = #Save arg () 1357 val saved = #Save arg ()
1358 in 1358 in
1359 decomp {Save = #Save arg, Restore = #Restore arg, Add = #Add arg} 1359 decomp {Save = #Save arg, Restore = #Restore arg, Add = #Add arg}
1363 handle Cc.Contradiction => () 1363 handle Cc.Contradiction => ()
1364 1364
1365 fun normal () = doWhere normal' 1365 fun normal () = doWhere normal'
1366 in 1366 in
1367 (case #Select r of 1367 (case #Select r of
1368 [SqExp (Binop (Exps bo, Count, SqConst (Prim.Int 0)), f)] => 1368 [SqExp (Binop (RCmp bo, Count, SqConst (Prim.Int 0)), f)] =>
1369 (case bo (Const (Prim.Int 1), Const (Prim.Int 2)) of 1369 (case bo of
1370 Reln (Gt, [Const (Prim.Int 1), Const (Prim.Int 2)]) => 1370 Gt =>
1371 (case #Cont arg of 1371 (case #Cont arg of
1372 SomeCol _ => () 1372 SomeCol _ => ()
1373 | AllCols k => 1373 | AllCols k =>
1374 let 1374 let
1375 fun answer e = k (Recd [(f, e)]) 1375 fun answer e = k (Recd [(f, e)])
1467 [] => k (Func (Other (m ^ "." ^ s), rev acc)) 1467 [] => k (Func (Other (m ^ "." ^ s), rev acc))
1468 | (e, _) :: es => 1468 | (e, _) :: es =>
1469 evalExp env e (fn e => doArgs (es, e :: acc)) 1469 evalExp env e (fn e => doArgs (es, e :: acc))
1470 in 1470 in
1471 doArgs (es, []) 1471 doArgs (es, [])
1472 end 1472 end
1473 in 1473 in
1474 case #1 e of 1474 case #1 e of
1475 EPrim p => k (Const p) 1475 EPrim p => k (Const p)
1476 | ERel n => k (List.nth (env, n)) 1476 | ERel n => k (List.nth (env, n))
1477 | ENamed _ => default () 1477 | ENamed _ => default ()
1517 fun doArgs (args, modes, env') = 1517 fun doArgs (args, modes, env') =
1518 case (args, modes) of 1518 case (args, modes) of
1519 ([], []) => (evalExp env' (#body rf) (fn _ => ()); 1519 ([], []) => (evalExp env' (#body rf) (fn _ => ());
1520 St.reinstate saved; 1520 St.reinstate saved;
1521 default ()) 1521 default ())
1522 1522
1523 | (arg :: args, mode :: modes) => 1523 | (arg :: args, mode :: modes) =>
1524 evalExp env arg (fn arg => 1524 evalExp env arg (fn arg =>
1525 let 1525 let
1526 val v = case mode of 1526 val v = case mode of
1527 Arbitrary => Var (St.nextVar ()) 1527 Arbitrary => Var (St.nextVar ())
1661 NextVar = Var o St.nextVar, 1661 NextVar = Var o St.nextVar,
1662 Add = fn a => St.assert [a], 1662 Add = fn a => St.assert [a],
1663 Save = St.stash, 1663 Save = St.stash,
1664 Restore = St.reinstate, 1664 Restore = St.reinstate,
1665 Cont = AllCols (fn x => 1665 Cont = AllCols (fn x =>
1666 (St.assert [AReln (Eq, [r, x])]; 1666 (St.assert [AReln (Cmp Eq, [r, x])];
1667 evalExp (acc :: r :: env) b k))} q 1667 evalExp (acc :: r :: env) b k))} q
1668 end) 1668 end)
1669 | EDml (e, _) => 1669 | EDml (e, _) =>
1670 (case parse dml e of 1670 (case parse dml e of
1671 NONE => (print ("Warning: Information flow checker can't parse DML command at " 1671 NONE => (print ("Warning: Information flow checker can't parse DML command at "
1695 k (Recd []) 1695 k (Recd [])
1696 end 1696 end
1697 | Delete (tab, e) => 1697 | Delete (tab, e) =>
1698 let 1698 let
1699 val old = St.nextVar () 1699 val old = St.nextVar ()
1700 1700
1701 val expIn = expIn (Var o St.nextVar) env 1701 val expIn = expIn (Var o St.nextVar) env
1702 (fn "T" => Var old 1702 (fn "T" => Var old
1703 | _ => raise Fail "Iflow.evalExp: Bad field expression in DELETE") 1703 | _ => raise Fail "Iflow.evalExp: Bad field expression in DELETE")
1704 1704
1705 val p = case expIn e of 1705 val p = case expIn e of
1706 inl e => raise Fail "Iflow.evalExp: DELETE with non-boolean" 1706 inl e => raise Fail "Iflow.evalExp: DELETE with non-boolean"
1707 | inr p => p 1707 | inr p => p
1708 1708
1709 val saved = St.stash () 1709 val saved = St.stash ()
1710 in 1710 in
1711 St.assert [AReln (Sql (tab ^ "$Old"), [Var old]), 1711 St.assert [AReln (Sql (tab ^ "$Old"), [Var old]),
1712 AReln (Sql (tab), [Var old])]; 1712 AReln (Sql (tab), [Var old])];
1713 decomp {Save = St.stash, 1713 decomp {Save = St.stash,
1746 fs 1746 fs
1747 else 1747 else
1748 (f, Proj (Var old, f)) :: fs) fs fs' 1748 (f, Proj (Var old, f)) :: fs) fs fs'
1749 1749
1750 val p = case expIn e of 1750 val p = case expIn e of
1751 inl e => raise Fail "Iflow.evalExp: UPDATE with non-boolean" 1751 inl e => raise Fail "Iflow.evalExp: UPDATE with non-boolean"
1752 | inr p => p 1752 | inr p => p
1753 val saved = St.stash () 1753 val saved = St.stash ()
1754 in 1754 in
1755 St.assert [AReln (Sql (tab ^ "$New"), [Recd fs]), 1755 St.assert [AReln (Sql (tab ^ "$New"), [Recd fs]),
1756 AReln (Sql (tab ^ "$Old"), [Var old]), 1756 AReln (Sql (tab ^ "$Old"), [Var old]),
1762 St.reinstate saved; 1762 St.reinstate saved;
1763 St.havocReln (Sql tab); 1763 St.havocReln (Sql tab);
1764 k (Recd [])) 1764 k (Recd []))
1765 handle Cc.Contradiction => ()) 1765 handle Cc.Contradiction => ())
1766 end) 1766 end)
1767 1767
1768 | ENextval (EPrim (Prim.String (_, seq)), _) => 1768 | ENextval (EPrim (Prim.String (_, seq)), _) =>
1769 let 1769 let
1770 val nv = St.nextVar () 1770 val nv = St.nextVar ()
1771 in 1771 in
1772 St.assert [AReln (Sql (String.extract (seq, 3, NONE)), [Var nv])]; 1772 St.assert [AReln (Sql (String.extract (seq, 3, NONE)), [Var nv])];
1778 | EUnurlify ((EFfiApp ("Basis", "get_cookie", [((EPrim (Prim.String (_, cname)), _), _)]), _), _, _) => 1778 | EUnurlify ((EFfiApp ("Basis", "get_cookie", [((EPrim (Prim.String (_, cname)), _), _)]), _), _, _) =>
1779 let 1779 let
1780 val e = Var (St.nextVar ()) 1780 val e = Var (St.nextVar ())
1781 val e' = Func (Other ("cookie/" ^ cname), []) 1781 val e' = Func (Other ("cookie/" ^ cname), [])
1782 in 1782 in
1783 St.assert [AReln (Known, [e]), AReln (Eq, [e, e'])]; 1783 St.assert [AReln (Known, [e]), AReln (Cmp Eq, [e, e'])];
1784 k e 1784 k e
1785 end 1785 end
1786 1786
1787 | EUnurlify _ => default () 1787 | EUnurlify _ => default ()
1788 | EJavaScript _ => default () 1788 | EJavaScript _ => default ()
2157 in 2157 in
2158 St.allowSend ([p], outs) 2158 St.allowSend ([p], outs)
2159 end 2159 end
2160 | _ => ()) 2160 | _ => ())
2161 end 2161 end
2162 2162
2163 | _ => () 2163 | _ => ()
2164 in 2164 in
2165 app decl (#1 file) 2165 app decl (#1 file)
2166 end 2166 end
2167 2167