comparison src/iflow.sml @ 1238:d6938ab3b5ae

Get refurbished Iflow working with calendar
author Adam Chlipala <adamc@hcoop.net>
date Wed, 14 Apr 2010 09:18:16 -0400
parents a9c200f73f24
children 30f789d5e2ad
comparison
equal deleted inserted replaced
1237:a9c200f73f24 1238:d6938ab3b5ae
241 val assert : database * atom -> unit 241 val assert : database * atom -> unit
242 val check : database * atom -> bool 242 val check : database * atom -> bool
243 243
244 val p_database : database Print.printer 244 val p_database : database Print.printer
245 245
246 val builtFrom : database * {Base : exp list, Derived : exp} -> bool 246 val builtFrom : database * {UseKnown : bool, Base : exp list, Derived : exp} -> bool
247 247
248 val p_repOf : database -> exp Print.printer 248 val p_repOf : database -> exp Print.printer
249 end = struct 249 end = struct
250 250
251 exception Contradiction 251 exception Contradiction
708 in 708 in
709 repOf r1 = repOf r2 709 repOf r1 = repOf r2
710 end 710 end
711 | _ => false 711 | _ => false
712 712
713 fun builtFrom (db, {Base = bs, Derived = d}) = 713 fun builtFrom (db, {UseKnown = uk, Base = bs, Derived = d}) =
714 let 714 let
715 val bs = map (fn b => representative (db, b)) bs 715 val bs = map (fn b => representative (db, b)) bs
716 716
717 fun loop d = 717 fun loop d =
718 let 718 let
719 val d = repOf d 719 val d = repOf d
720 in 720 in
721 List.exists (fn b => repOf b = d) bs 721 (uk andalso !(#Known (unNode d)))
722 orelse List.exists (fn b => repOf b = d) bs
722 orelse case #Variety (unNode d) of 723 orelse case #Variety (unNode d) of
723 Dt0 _ => true 724 Dt0 _ => true
724 | Dt1 (_, d) => loop d 725 | Dt1 (_, d) => loop d
725 | Prim _ => true 726 | Prim _ => true
726 | Recrd (xes, _) => List.all loop (SM.listItems (!xes)) 727 | Recrd (xes, _) => List.all loop (SM.listItems (!xes))
727 | Nothing => false 728 | Nothing => false
728 end 729 end
730
731 fun decomp e =
732 case e of
733 Func (Other _, es) => List.all decomp es
734 | _ => loop (representative (db, e))
729 in 735 in
730 loop (representative (db, d)) 736 decomp d
731 end 737 end
732 738
733 end 739 end
734 740
735 val tabs = ref (SM.empty : (string list * string list list) SM.map) 741 val tabs = ref (SM.empty : (string list * string list list) SM.map)
1160 val assert : atom list -> unit 1166 val assert : atom list -> unit
1161 1167
1162 val addPath : check -> unit 1168 val addPath : check -> unit
1163 1169
1164 val allowSend : atom list * exp list -> unit 1170 val allowSend : atom list * exp list -> unit
1165 val send : check -> unit 1171 val send : bool -> check -> unit
1166 1172
1167 val allowInsert : atom list -> unit 1173 val allowInsert : atom list -> unit
1168 val insert : ErrorMsg.span -> unit 1174 val insert : ErrorMsg.span -> unit
1169 1175
1170 val allowDelete : atom list -> unit 1176 val allowDelete : atom list -> unit
1172 1178
1173 val allowUpdate : atom list -> unit 1179 val allowUpdate : atom list -> unit
1174 val update : ErrorMsg.span -> unit 1180 val update : ErrorMsg.span -> unit
1175 1181
1176 val havocReln : reln -> unit 1182 val havocReln : reln -> unit
1183
1184 val debug : unit -> unit
1177 end = struct 1185 end = struct
1178 1186
1179 val hnames = ref 1 1187 val hnames = ref 1
1180 1188
1181 type hyps = int * atom list 1189 type hyps = int * atom list
1182 1190
1183 val db = Cc.database () 1191 val db = Cc.database ()
1184 val path = ref ([] : (hyps * check) option ref list) 1192 val path = ref ([] : (hyps * check) option ref list)
1185 val hyps = ref (0, [] : atom list) 1193 val hyps = ref (0, [] : atom list)
1186 val nvar = ref 0 1194 val nvar = ref 0
1187
1188 fun reset () = (Cc.clear db;
1189 path := [];
1190 hyps := (0, []);
1191 nvar := 0)
1192 1195
1193 fun setHyps (h as (n', hs)) = 1196 fun setHyps (h as (n', hs)) =
1194 let 1197 let
1195 val (n, _) = !hyps 1198 val (n, _) = !hyps
1196 in 1199 in
1229 1232
1230 fun addPath c = path := ref (SOME (!hyps, c)) :: !path 1233 fun addPath c = path := ref (SOME (!hyps, c)) :: !path
1231 1234
1232 val sendable = ref ([] : (atom list * exp list) list) 1235 val sendable = ref ([] : (atom list * exp list) list)
1233 1236
1234 fun checkGoals goals unifs succ fail = 1237 fun checkGoals goals k =
1235 case goals of
1236 [] => succ (unifs, [])
1237 | AReln (Sql tab, [Lvar lv]) :: goals =>
1238 let
1239 val saved = stash ()
1240 val (_, hyps) = !hyps
1241
1242 fun tryAll unifs hyps =
1243 case hyps of
1244 [] => fail ()
1245 | AReln (Sql tab', [e]) :: hyps =>
1246 if tab' = tab then
1247 checkGoals goals (IM.insert (unifs, lv, e)) succ
1248 (fn () => tryAll unifs hyps)
1249 else
1250 tryAll unifs hyps
1251 | _ :: hyps => tryAll unifs hyps
1252 in
1253 tryAll unifs hyps
1254 end
1255 | AReln (r, es) :: goals => checkGoals goals unifs
1256 (fn (unifs, ls) => succ (unifs, AReln (r, map (simplify unifs) es) :: ls))
1257 fail
1258 | ACond _ :: _ => fail ()
1259
1260 fun buildable (e, loc) =
1261 let 1238 let
1262 fun doPols pols acc fail = 1239 fun checkGoals goals unifs =
1240 case goals of
1241 [] => k unifs
1242 | AReln (Sql tab, [Lvar lv]) :: goals =>
1243 let
1244 val saved = stash ()
1245 val (_, hyps) = !hyps
1246
1247 fun tryAll unifs hyps =
1248 case hyps of
1249 [] => false
1250 | AReln (Sql tab', [e]) :: hyps =>
1251 (tab' = tab andalso
1252 checkGoals goals (IM.insert (unifs, lv, e)))
1253 orelse tryAll unifs hyps
1254 | _ :: hyps => tryAll unifs hyps
1255 in
1256 tryAll unifs hyps
1257 end
1258 | AReln (r, es) :: goals =>
1259 Cc.check (db, AReln (r, map (simplify unifs) es))
1260 andalso checkGoals goals unifs
1261 | ACond _ :: _ => false
1262 in
1263 checkGoals goals IM.empty
1264 end
1265
1266 fun useKeys () =
1267 let
1268 fun findKeys hyps =
1269 case hyps of
1270 [] => ()
1271 | AReln (Sql tab, [r1]) :: hyps =>
1272 (case SM.find (!tabs, tab) of
1273 NONE => findKeys hyps
1274 | SOME (_, []) => findKeys hyps
1275 | SOME (_, ks) =>
1276 let
1277 fun finder hyps =
1278 case hyps of
1279 [] => ()
1280 | AReln (Sql tab', [r2]) :: hyps =>
1281 (if tab' = tab andalso
1282 List.exists (List.all (fn f =>
1283 let
1284 val r =
1285 Cc.check (db,
1286 AReln (Eq, [Proj (r1, f),
1287 Proj (r2, f)]))
1288 in
1289 (*Print.prefaces "Fs"
1290 [("tab",
1291 Print.PD.string tab),
1292 ("r1",
1293 p_exp (Proj (r1, f))),
1294 ("r2",
1295 p_exp (Proj (r2, f))),
1296 ("r",
1297 Print.PD.string
1298 (Bool.toString r))];*)
1299 r
1300 end)) ks then
1301 ((*Print.prefaces "Key match" [("tab", Print.PD.string tab),
1302 ("r1", p_exp r1),
1303 ("r2", p_exp r2),
1304 ("rp1", Cc.p_repOf cc r1),
1305 ("rp2", Cc.p_repOf cc r2)];*)
1306 Cc.assert (db, AReln (Eq, [r1, r2])))
1307 else
1308 ();
1309 finder hyps)
1310 | _ :: hyps => finder hyps
1311 in
1312 finder hyps;
1313 findKeys hyps
1314 end)
1315 | _ :: hyps => findKeys hyps
1316
1317 val (_, hs) = !hyps
1318 in
1319 (*print "findKeys\n";*)
1320 findKeys hs
1321 end
1322
1323 fun buildable uk (e, loc) =
1324 let
1325 fun doPols pols acc =
1263 case pols of 1326 case pols of
1264 [] => ((*Print.prefaces "buildable" [("Base", Print.p_list p_exp acc), 1327 [] => ((*Print.prefaces "buildable" [("Base", Print.p_list p_exp acc),
1265 ("Derived", p_exp e), 1328 ("Derived", p_exp e),
1266 ("Hyps", Print.p_list p_atom (#2 (!hyps)))];*) 1329 ("Hyps", Print.p_list p_atom (#2 (!hyps)))];*)
1267 if Cc.builtFrom (db, {Base = acc, Derived = e}) then 1330 Cc.builtFrom (db, {UseKnown = uk, Base = acc, Derived = e}))
1268 ()
1269 else
1270 fail ())
1271 | (goals, es) :: pols => 1331 | (goals, es) :: pols =>
1272 checkGoals goals IM.empty 1332 checkGoals goals (fn unifs => doPols pols (map (simplify unifs) es @ acc))
1273 (fn (unifs, goals) => 1333 orelse doPols pols acc
1274 if List.all (fn a => Cc.check (db, a)) goals then
1275 doPols pols (map (simplify unifs) es @ acc) fail
1276 else
1277 doPols pols acc fail)
1278 (fn () => doPols pols acc fail)
1279 in 1334 in
1280 doPols (!sendable) [] 1335 useKeys ();
1281 (fn () => let 1336 if doPols (!sendable) [] then
1282 val (_, hs) = !hyps 1337 ()
1283 in 1338 else
1284 ErrorMsg.errorAt loc "The information flow policy may be violated here."; 1339 let
1285 Print.prefaces "Situation" [("Hypotheses", Print.p_list p_atom hs), 1340 val (_, hs) = !hyps
1286 ("User learns", p_exp e)] 1341 in
1287 end) 1342 ErrorMsg.errorAt loc "The information flow policy may be violated here.";
1343 Print.prefaces "Situation" [("Hypotheses", Print.p_list p_atom hs),
1344 ("User learns", p_exp e)]
1345 end
1288 end 1346 end
1289 1347
1290 fun checkPaths () = 1348 fun checkPaths () =
1291 let 1349 let
1292 val hs = !hyps 1350 val hs = !hyps
1295 case !r of 1353 case !r of
1296 NONE => () 1354 NONE => ()
1297 | SOME (hs, e) => 1355 | SOME (hs, e) =>
1298 (r := NONE; 1356 (r := NONE;
1299 setHyps hs; 1357 setHyps hs;
1300 buildable e)) (!path); 1358 buildable true e)) (!path);
1301 setHyps hs 1359 setHyps hs
1302 end 1360 end
1303 1361
1304 fun allowSend v = sendable := v :: !sendable 1362 fun allowSend v = ((*Print.prefaces "Allow" [("goals", Print.p_list p_atom (#1 v)),
1305 1363 ("exps", Print.p_list p_exp (#2 v))];*)
1306 fun send (e, loc) = ((*Print.preface ("Send", p_exp e);*) 1364 sendable := v :: !sendable)
1307 checkPaths (); 1365
1308 if isKnown e then 1366 fun send uk (e, loc) = ((*Print.preface ("Send", p_exp e);*)
1309 () 1367 checkPaths ();
1310 else 1368 if isKnown e then
1311 buildable (e, loc)) 1369 ()
1370 else
1371 buildable uk (e, loc))
1312 1372
1313 fun doable pols (loc : ErrorMsg.span) = 1373 fun doable pols (loc : ErrorMsg.span) =
1314 let 1374 let
1315 val pols = !pols 1375 val pols = !pols
1316 in 1376 in
1317 if List.exists (fn goals => 1377 if List.exists (fn goals =>
1318 checkGoals goals IM.empty 1378 if checkGoals goals (fn _ => true) then
1319 (fn (_, goals) => List.all (fn a => Cc.check (db, a)) goals) 1379 ((*Print.prefaces "Match" [("goals", Print.p_list p_atom goals),
1320 (fn () => false)) pols then 1380 ("hyps", Print.p_list p_atom (#2 (!hyps)))];*)
1381 true)
1382 else
1383 ((*Print.prefaces "No match" [("goals", Print.p_list p_atom goals),
1384 ("hyps", Print.p_list p_atom (#2 (!hyps)))];*)
1385 false)) pols then
1321 () 1386 ()
1322 else 1387 else
1323 let 1388 let
1324 val (_, hs) = !hyps 1389 val (_, hs) = !hyps
1325 in 1390 in
1338 1403
1339 val deletable = ref ([] : atom list list) 1404 val deletable = ref ([] : atom list list)
1340 fun allowDelete v = deletable := v :: !deletable 1405 fun allowDelete v = deletable := v :: !deletable
1341 val delete = doable deletable 1406 val delete = doable deletable
1342 1407
1408 fun reset () = (Cc.clear db;
1409 path := [];
1410 hyps := (0, []);
1411 nvar := 0;
1412 sendable := [];
1413 insertable := [];
1414 updatable := [];
1415 deletable := [])
1416
1343 fun havocReln r = 1417 fun havocReln r =
1344 let 1418 let
1345 val n = !hnames 1419 val n = !hnames
1346 val (_, hs) = !hyps 1420 val (_, hs) = !hyps
1347 in 1421 in
1348 hnames := n + 1; 1422 hnames := n + 1;
1349 hyps := (n, List.filter (fn AReln (r', _) => r' <> r | _ => true) hs) 1423 hyps := (n, List.filter (fn AReln (r', _) => r' <> r | _ => true) hs)
1424 end
1425
1426 fun debug () =
1427 let
1428 val (_, hs) = !hyps
1429 in
1430 Print.preface ("Hyps", Print.p_list p_atom hs)
1350 end 1431 end
1351 1432
1352 end 1433 end
1353 1434
1354 1435
1411 1492
1412 fun decomp {Save = save, Restore = restore, Add = add} = 1493 fun decomp {Save = save, Restore = restore, Add = add} =
1413 let 1494 let
1414 fun go p k = 1495 fun go p k =
1415 case p of 1496 case p of
1416 True => k () 1497 True => (k () handle Cc.Contradiction => ())
1417 | False => () 1498 | False => ()
1418 | Unknown => () 1499 | Unknown => ()
1419 | And (p1, p2) => go p1 (fn () => go p2 k) 1500 | And (p1, p2) => go p1 (fn () => go p2 k)
1420 | Or (p1, p2) => 1501 | Or (p1, p2) =>
1421 let 1502 let
1430 in 1511 in
1431 go 1512 go
1432 end 1513 end
1433 1514
1434 datatype queryMode = 1515 datatype queryMode =
1435 SomeCol of exp list -> unit 1516 SomeCol of {New : (string * exp) option, Old : (string * exp) option, Outs : exp list} -> unit
1436 | AllCols of exp -> unit 1517 | AllCols of exp -> unit
1437 1518
1438 type 'a doQuery = { 1519 type 'a doQuery = {
1439 Env : exp list, 1520 Env : exp list,
1440 NextVar : unit -> exp, 1521 NextVar : unit -> exp,
1456 let 1537 let
1457 fun doQuery q = 1538 fun doQuery q =
1458 case q of 1539 case q of
1459 Query1 r => 1540 Query1 r =>
1460 let 1541 let
1461 val rvs = map (fn (_, v) => (v, #NextVar arg ())) (#From r) 1542 val new = ref NONE
1543 val old = ref NONE
1544
1545 val rvs = map (fn (tab, v) =>
1546 let
1547 val nv = #NextVar arg ()
1548 in
1549 case v of
1550 "New" => new := SOME (tab, nv)
1551 | "Old" => old := SOME (tab, nv)
1552 | _ => ();
1553 (v, nv)
1554 end) (#From r)
1462 1555
1463 fun rvOf v = 1556 fun rvOf v =
1464 case List.find (fn (v', _) => v' = v) rvs of 1557 case List.find (fn (v', _) => v' = v) rvs of
1465 NONE => raise Fail "Iflow.queryProp: Bad table variable" 1558 NONE => raise Fail "Iflow.queryProp: Bad table variable"
1466 | SOME (_, e) => e 1559 | SOME (_, e) => e
1498 | SqExp (e, f) => 1591 | SqExp (e, f) =>
1499 case expIn e of 1592 case expIn e of
1500 inr _ => #NextVar arg () 1593 inr _ => #NextVar arg ()
1501 | inl e => e) (#Select r) 1594 | inl e => e) (#Select r)
1502 in 1595 in
1503 k sis 1596 k {New = !new, Old = !old, Outs = sis}
1504 end 1597 end
1505 | AllCols k => 1598 | AllCols k =>
1506 let 1599 let
1507 val (ts, es) = 1600 val (ts, es) =
1508 foldl (fn (si, (ts, es)) => 1601 foldl (fn (si, (ts, es)) =>
1556 SomeCol _ => () 1649 SomeCol _ => ()
1557 | AllCols k => 1650 | AllCols k =>
1558 let 1651 let
1559 fun answer e = k (Recd [(f, e)]) 1652 fun answer e = k (Recd [(f, e)])
1560 1653
1561 val () = answer (Func (DtCon0 "Basis.bool.False", []))
1562 val saved = #Save arg () 1654 val saved = #Save arg ()
1655 val () = (answer (Func (DtCon0 "Basis.bool.False", [])))
1656 handle Cc.Contradiction => ()
1563 in 1657 in
1658 #Restore arg saved;
1659 (*print "True time!\n";*)
1564 doWhere (fn () => answer (Func (DtCon0 "Basis.bool.True", []))); 1660 doWhere (fn () => answer (Func (DtCon0 "Basis.bool.True", [])));
1565 #Restore arg saved 1661 #Restore arg saved
1566 end) 1662 end)
1567 | _ => normal ()) 1663 | _ => normal ())
1568 | _ => normal ()) 1664 | _ => normal ())
1606 env 1702 env
1607 end 1703 end
1608 1704
1609 fun evalExp env (e as (_, loc)) k = 1705 fun evalExp env (e as (_, loc)) k =
1610 let 1706 let
1707 (*val () = St.debug ()*)
1611 (*val () = Print.preface ("evalExp", MonoPrint.p_exp MonoEnv.empty e)*) 1708 (*val () = Print.preface ("evalExp", MonoPrint.p_exp MonoEnv.empty e)*)
1612 1709
1613 fun default () = k (Var (St.nextVar ())) 1710 fun default () = k (Var (St.nextVar ()))
1614 1711
1615 fun doFfi (m, s, es) = 1712 fun doFfi (m, s, es) =
1617 let 1714 let
1618 fun doArgs es = 1715 fun doArgs es =
1619 case es of 1716 case es of
1620 [] => k (Recd []) 1717 [] => k (Recd [])
1621 | e :: es => 1718 | e :: es =>
1622 evalExp env e (fn e => (St.send (e, loc); doArgs es)) 1719 evalExp env e (fn e => (St.send true (e, loc); doArgs es))
1623 in 1720 in
1624 doArgs es 1721 doArgs es
1625 end 1722 end
1626 else if Settings.isEffectful (m, s) andalso not (Settings.isBenignEffectful (m, s)) then 1723 else if Settings.isEffectful (m, s) andalso not (Settings.isBenignEffectful (m, s)) then
1627 default () 1724 default ()
1671 val () = St.addPath (e, loc) 1768 val () = St.addPath (e, loc)
1672 in 1769 in
1673 app (fn (p, pe) => 1770 app (fn (p, pe) =>
1674 let 1771 let
1675 val saved = St.stash () 1772 val saved = St.stash ()
1676
1677 val env = evalPat env e p
1678 in 1773 in
1679 evalExp env pe k; 1774 let
1680 St.reinstate saved 1775 val env = evalPat env e p
1776 in
1777 evalExp env pe k;
1778 St.reinstate saved
1779 end
1780 handle Cc.Contradiction => St.reinstate saved
1681 end) pes 1781 end) pes
1682 end handle Cc.Contradiction => ()) 1782 end)
1683 | EStrcat (e1, e2) => 1783 | EStrcat (e1, e2) =>
1684 evalExp env e1 (fn e1 => 1784 evalExp env e1 (fn e1 =>
1685 evalExp env e2 (fn e2 => 1785 evalExp env e2 (fn e2 =>
1686 k (Func (Other "cat", [e1, e2])))) 1786 k (Func (Other "cat", [e1, e2]))))
1687 | EError (e, _) => evalExp env e (fn e => St.send (e, loc)) 1787 | EError (e, _) => evalExp env e (fn e => St.send true (e, loc))
1688 | EReturnBlob {blob = b, mimeType = m, ...} => 1788 | EReturnBlob {blob = b, mimeType = m, ...} =>
1689 evalExp env b (fn b => 1789 evalExp env b (fn b =>
1690 (St.send (b, loc); 1790 (St.send true (b, loc);
1691 evalExp env m 1791 evalExp env m
1692 (fn m => St.send (m, loc)))) 1792 (fn m => St.send true (m, loc))))
1693 | ERedirect (e, _) => 1793 | ERedirect (e, _) =>
1694 evalExp env e (fn e => St.send (e, loc)) 1794 evalExp env e (fn e => St.send true (e, loc))
1695 | EWrite e => 1795 | EWrite e =>
1696 evalExp env e (fn e => (St.send (e, loc); 1796 evalExp env e (fn e => (St.send true (e, loc);
1697 k (Recd []))) 1797 k (Recd [])))
1698 | ESeq (e1, e2) => 1798 | ESeq (e1, e2) =>
1699 evalExp env e1 (fn _ => evalExp env e2 k) 1799 evalExp env e1 (fn _ => evalExp env e2 k)
1700 | ELet (_, _, e1, e2) => 1800 | ELet (_, _, e1, e2) =>
1701 evalExp env e1 (fn e1 => evalExp (e1 :: env) e2 k) 1801 evalExp env e1 (fn e1 => evalExp (e1 :: env) e2 k)
1709 in 1809 in
1710 doArgs (es, []) 1810 doArgs (es, [])
1711 end 1811 end
1712 1812
1713 | EQuery {query = q, body = b, initial = i, state = state, ...} => 1813 | EQuery {query = q, body = b, initial = i, state = state, ...} =>
1714 evalExp env q (fn _ => 1814 evalExp env i (fn i =>
1715 evalExp env i (fn i => 1815 let
1716 let 1816 val saved = St.stash ()
1717 val saved = St.stash () 1817
1718 1818 val () = (k i)
1719 val r = Var (St.nextVar ()) 1819 handle Cc.Contradiction => ()
1720 val acc = Var (St.nextVar ()) 1820 val () = St.reinstate saved
1721 in 1821
1722 if MonoUtil.Exp.existsB {typ = fn _ => false, 1822 val r = Var (St.nextVar ())
1723 exp = fn (n, e) => 1823 val acc = Var (St.nextVar ())
1724 case e of 1824 in
1725 ERel n' => n' = n 1825 if MonoUtil.Exp.existsB {typ = fn _ => false,
1726 | _ => false, 1826 exp = fn (n, e) =>
1727 bind = fn (n, b) => 1827 case e of
1728 case b of 1828 ERel n' => n' = n
1729 MonoUtil.Exp.RelE _ => n + 1 1829 | _ => false,
1730 | _ => n} 1830 bind = fn (n, b) =>
1731 0 b then 1831 case b of
1732 doQuery {Env = env, 1832 MonoUtil.Exp.RelE _ => n + 1
1733 NextVar = Var o St.nextVar, 1833 | _ => n}
1734 Add = fn a => St.assert [a], 1834 0 b then
1735 Save = St.stash, 1835 doQuery {Env = env,
1736 Restore = St.reinstate, 1836 NextVar = Var o St.nextVar,
1737 UsedExp = fn e => St.send (e, loc), 1837 Add = fn a => St.assert [a],
1738 Cont = AllCols (fn _ => (St.reinstate saved; 1838 Save = St.stash,
1739 evalExp 1839 Restore = St.reinstate,
1740 (acc :: r :: env) 1840 UsedExp = fn e => St.send false (e, loc),
1741 b (fn _ => default ())))} q 1841 Cont = AllCols (fn _ => evalExp
1742 else 1842 (acc :: r :: env)
1743 doQuery {Env = env, 1843 b (fn _ => default ()))} q
1744 NextVar = Var o St.nextVar, 1844 else
1745 Add = fn a => St.assert [a], 1845 doQuery {Env = env,
1746 Save = St.stash, 1846 NextVar = Var o St.nextVar,
1747 Restore = St.reinstate, 1847 Add = fn a => St.assert [a],
1748 UsedExp = fn e => St.send (e, loc), 1848 Save = St.stash,
1749 Cont = AllCols (fn x => 1849 Restore = St.reinstate,
1750 (St.assert [AReln (Eq, [r, x])]; 1850 UsedExp = fn e => St.send false (e, loc),
1751 evalExp (acc :: r :: env) b k))} q 1851 Cont = AllCols (fn x =>
1752 end)) 1852 (St.assert [AReln (Eq, [r, x])];
1853 evalExp (acc :: r :: env) b k))} q
1854 end)
1753 | EDml e => 1855 | EDml e =>
1754 (case parse dml e of 1856 (case parse dml e of
1755 NONE => (print ("Warning: Information flow checker can't parse DML command at " 1857 NONE => (print ("Warning: Information flow checker can't parse DML command at "
1756 ^ ErrorMsg.spanToString loc ^ "\n"); 1858 ^ ErrorMsg.spanToString loc ^ "\n");
1757 default ()) 1859 default ())
1789 inl e => raise Fail "Iflow.evalExp: DELETE with non-boolean" 1891 inl e => raise Fail "Iflow.evalExp: DELETE with non-boolean"
1790 | inr p => p 1892 | inr p => p
1791 1893
1792 val saved = St.stash () 1894 val saved = St.stash ()
1793 in 1895 in
1794 St.assert [AReln (Sql "$Old", [Var old]), 1896 St.assert [AReln (Sql (tab ^ "$Old"), [Var old])];
1795 AReln (Sql tab, [Var old])];
1796 decomp {Save = St.stash, 1897 decomp {Save = St.stash,
1797 Restore = St.reinstate, 1898 Restore = St.reinstate,
1798 Add = fn a => St.assert [a]} p 1899 Add = fn a => St.assert [a]} p
1799 (fn () => (St.delete loc; 1900 (fn () => (St.delete loc;
1800 St.reinstate saved; 1901 St.reinstate saved;
1834 inl e => raise Fail "Iflow.evalExp: UPDATE with non-boolean" 1935 inl e => raise Fail "Iflow.evalExp: UPDATE with non-boolean"
1835 | inr p => p 1936 | inr p => p
1836 val saved = St.stash () 1937 val saved = St.stash ()
1837 in 1938 in
1838 St.assert [AReln (Sql (tab ^ "$New"), [Recd fs]), 1939 St.assert [AReln (Sql (tab ^ "$New"), [Recd fs]),
1839 AReln (Sql "$Old", [Var old]), 1940 AReln (Sql (tab ^ "$Old"), [Var old])];
1840 AReln (Sql tab, [Var old])];
1841 decomp {Save = St.stash, 1941 decomp {Save = St.stash,
1842 Restore = St.reinstate, 1942 Restore = St.reinstate,
1843 Add = fn a => St.assert [a]} p 1943 Add = fn a => St.assert [a]} p
1844 (fn () => (St.update loc; 1944 (fn () => (St.update loc;
1845 St.reinstate saved; 1945 St.reinstate saved;
1856 k (Var nv) 1956 k (Var nv)
1857 end 1957 end
1858 | ENextval _ => default () 1958 | ENextval _ => default ()
1859 | ESetval _ => default () 1959 | ESetval _ => default ()
1860 1960
1861 | EUnurlify ((EFfiApp ("Basis", "get_cookie", _), _), _, _) => 1961 | EUnurlify ((EFfiApp ("Basis", "get_cookie", [(EPrim (Prim.String cname), _)]), _), _, _) =>
1862 let 1962 let
1863 val nv = St.nextVar () 1963 val e = Var (St.nextVar ())
1864 in 1964 in
1865 St.assert [AReln (Known, [Var nv])]; 1965 St.assert [AReln (Known, [e])];
1866 k (Var nv) 1966 k e
1867 end 1967 end
1868 1968
1869 | EUnurlify _ => default () 1969 | EUnurlify _ => default ()
1870 | EJavaScript _ => default () 1970 | EJavaScript _ => default ()
1871 | ESignalReturn _ => default () 1971 | ESignalReturn _ => default ()
1911 map (map (fn s => str (Char.toUpper (String.sub (s, 3))) 2011 map (map (fn s => str (Char.toUpper (String.sub (s, 3)))
1912 ^ String.extract (s, 4, NONE))) ks)) 2012 ^ String.extract (s, 4, NONE))) ks))
1913 else 2013 else
1914 raise Fail "Table name does not begin with uw_" 2014 raise Fail "Table name does not begin with uw_"
1915 end 2015 end
1916 | DVal (_, n, _, e, _) => 2016 | DVal (x, n, _, e, _) =>
1917 let 2017 let
2018 (*val () = print ("\n=== " ^ x ^ " ===\n\n");*)
2019
1918 val isExptd = IS.member (exptd, n) 2020 val isExptd = IS.member (exptd, n)
1919 2021
1920 val saved = St.stash () 2022 val saved = St.stash ()
1921 2023
1922 fun deAbs (e, env, ps) = 2024 fun deAbs (e, env, ps) =
1956 NextVar = rv, 2058 NextVar = rv,
1957 Add = fn a => atoms := a :: !atoms, 2059 Add = fn a => atoms := a :: !atoms,
1958 Save = fn () => !atoms, 2060 Save = fn () => !atoms,
1959 Restore = fn ls => atoms := ls, 2061 Restore = fn ls => atoms := ls,
1960 UsedExp = fn _ => (), 2062 UsedExp = fn _ => (),
1961 Cont = SomeCol (fn es => k (!atoms, es))} 2063 Cont = SomeCol (fn r => k (rev (!atoms), r))}
2064
2065 fun untab tab = List.filter (fn AReln (Sql tab', _) => tab' <> tab
2066 | _ => true)
1962 in 2067 in
1963 case pol of 2068 case pol of
1964 PolClient e => 2069 PolClient e =>
1965 doQ (fn (ats, es) => St.allowSend (ats, es)) e 2070 doQ (fn (ats, {Outs = es, ...}) => St.allowSend (ats, es)) e
1966 | PolInsert e => 2071 | PolInsert e =>
1967 doQ (fn (ats, _) => St.allowInsert ats) e 2072 doQ (fn (ats, {New = SOME (tab, new), ...}) =>
2073 St.allowInsert (AReln (Sql (tab ^ "$New"), [new]) :: untab tab ats)
2074 | _ => raise Fail "Iflow: No New in mayInsert policy") e
1968 | PolDelete e => 2075 | PolDelete e =>
1969 doQ (fn (ats, _) => St.allowDelete ats) e 2076 doQ (fn (ats, {Old = SOME (tab, old), ...}) =>
2077 St.allowDelete (AReln (Sql (tab ^ "$Old"), [old]) :: untab tab ats)
2078 | _ => raise Fail "Iflow: No Old in mayDelete policy") e
1970 | PolUpdate e => 2079 | PolUpdate e =>
1971 doQ (fn (ats, _) => St.allowUpdate ats) e 2080 doQ (fn (ats, {New = SOME (tab, new), Old = SOME (_, old), ...}) =>
2081 St.allowUpdate (AReln (Sql (tab ^ "$Old"), [old])
2082 :: AReln (Sql (tab ^ "$New"), [new])
2083 :: untab tab ats)
2084 | _ => raise Fail "Iflow: No New or Old in mayUpdate policy") e
1972 | PolSequence e => 2085 | PolSequence e =>
1973 (case #1 e of 2086 (case #1 e of
1974 EPrim (Prim.String seq) => 2087 EPrim (Prim.String seq) =>
1975 let 2088 let
1976 val p = AReln (Sql (String.extract (seq, 3, NONE)), [Lvar 0]) 2089 val p = AReln (Sql (String.extract (seq, 3, NONE)), [Lvar 0])