comparison src/iflow.sml @ 1214:648e6b087dfb

Change query_policy to sendClient; all arguments passed to SQL predicates are variables
author Adam Chlipala <adamc@hcoop.net>
date Thu, 08 Apr 2010 09:57:37 -0400
parents e791d93d4616
children 360f1ed0a969
comparison
equal deleted inserted replaced
1213:e791d93d4616 1214:648e6b087dfb
410 type t 410 type t
411 val empty : t 411 val empty : t
412 val assert : t * exp * exp -> t 412 val assert : t * exp * exp -> t
413 val query : t * exp * exp -> bool 413 val query : t * exp * exp -> bool
414 val allPeers : t * exp -> exp list 414 val allPeers : t * exp -> exp list
415 val p_t : t Print.printer
415 end = struct 416 end = struct
416 417
417 fun eq (e1, e2) = eeq (simplify e1, simplify e2) 418 fun eq (e1, e2) = eeq (simplify e1, simplify e2)
418 419
419 type t = (exp * exp) list 420 type t = (exp * exp) list
438 else 439 else
439 NONE 440 NONE
440 end) t 441 end) t
441 end 442 end
442 443
444 open Print
445
446 val p_t = p_list (fn (e1, e2) => box [p_exp (simplify e1),
447 space,
448 PD.string "->",
449 space,
450 p_exp (simplify e2)])
451
452 fun query (t, e1, e2) =
453 let
454 fun doUn e =
455 case e of
456 Func (f, [e1]) =>
457 if String.isPrefix "un" f then
458 let
459 val s = String.extract (f, 2, NONE)
460 in
461 case ListUtil.search (fn e =>
462 case e of
463 Func (f', [e']) =>
464 if f' = s then
465 SOME e'
466 else
467 NONE
468 | _ => NONE) (allPeers (t, e1)) of
469 NONE => e
470 | SOME e => doUn e
471 end
472 else
473 e
474 | _ => e
475
476 val e1' = doUn (lookup (t, doUn (simplify e1)))
477 val e2' = doUn (lookup (t, doUn (simplify e2)))
478 in
479 (*prefaces "CC query" [("e1", p_exp (simplify e1)),
480 ("e2", p_exp (simplify e2)),
481 ("e1'", p_exp (simplify e1')),
482 ("e2'", p_exp (simplify e2')),
483 ("t", p_t t)];*)
484 eq (e1', e2')
485 end
486
443 fun assert (t, e1, e2) = 487 fun assert (t, e1, e2) =
444 let 488 let
445 val r1 = lookup (t, e1) 489 val r1 = lookup (t, e1)
446 val r2 = lookup (t, e2) 490 val r2 = lookup (t, e2)
447
448 fun doUn k (t', e1, e2) =
449 case e2 of
450 Func (f, [e]) =>
451 if String.isPrefix "un" f then
452 let
453 val f' = String.extract (f, 2, NONE)
454 in
455 foldl (fn (e', t') =>
456 case e' of
457 Func (f'', [e'']) =>
458 if f'' = f' then
459 (lookup (t', e1), k e'') :: t'
460 else
461 t'
462 | _ => t') t' (allPeers (t, e))
463 end
464 else
465 t'
466 | Proj (e2, f) => doUn (fn e' => k (Proj (e', f))) (t', e1, e2)
467 | _ => t'
468 in 491 in
469 if eq (r1, r2) then 492 if eq (r1, r2) then
470 t 493 t
471 else 494 else
472 doUn (fn x => x) (doUn (fn x => x) ((r1, r2) :: t, e1, e2), e2, e1) 495 let
496 fun doUn (t, e1, e2) =
497 case e1 of
498 Func (f, [e]) => if String.isPrefix "un" f then
499 let
500 val s = String.extract (f, 2, NONE)
501 in
502 foldl (fn (e', t) =>
503 case e' of
504 Func (f', [e']) =>
505 if f' = s then
506 assert (assert (t, e', e1), e', e2)
507 else
508 t
509 | _ => t) t (allPeers (t, e))
510 end
511 else
512 t
513 | _ => t
514
515 fun doProj (t, e1, e2) =
516 foldl (fn ((e1', e2'), t) =>
517 let
518 fun doOne (e, t) =
519 case e of
520 Proj (e', f) =>
521 if query (t, e1, e') then
522 assert (t, e, Proj (e2, f))
523 else
524 t
525 | _ => t
526 in
527 doOne (e1', doOne (e2', t))
528 end) t t
529
530 val t = (r1, r2) :: t
531 val t = doUn (t, r1, r2)
532 val t = doUn (t, r2, r1)
533 val t = doProj (t, r1, r2)
534 val t = doProj (t, r2, r1)
535 in
536 t
537 end
473 end 538 end
474
475 open Print
476
477 fun query (t, e1, e2) =
478 ((*prefaces "CC query" [("e1", p_exp (simplify e1)),
479 ("e2", p_exp (simplify e2)),
480 ("t", p_list (fn (e1, e2) => box [p_exp (simplify e1),
481 space,
482 PD.string "->",
483 space,
484 p_exp (simplify e2)]) t)];*)
485 eq (lookup (t, e1), lookup (t, e2)))
486 539
487 end 540 end
488 541
489 fun rimp cc ((r1, es1), (r2, es2)) = 542 fun rimp cc ((r1, es1), (r2, es2)) =
490 case (r1, r2) of 543 case (r1, r2) of
491 (Sql r1', Sql r2') => 544 (Sql r1', Sql r2') =>
492 r1' = r2' andalso 545 r1' = r2' andalso
493 (case (es1, es2) of 546 (case (es1, es2) of
494 ([Recd xes1], [Recd xes2]) => 547 ([e1], [e2]) => eq (e1, e2)
495 let
496 val saved = save ()
497 in
498 if List.all (fn (f, e2) =>
499 case ListUtil.search (fn (f', e1) => if f' = f then SOME e1 else NONE) xes1 of
500 NONE => true
501 | SOME e1 => eq (e1, e2)) xes2 then
502 true
503 else
504 (restore saved;
505 false)
506 end
507 | _ => false) 548 | _ => false)
508 | (Eq, Eq) => 549 | (Eq, Eq) =>
509 (case (es1, es2) of 550 (case (es1, es2) of
510 ([x1, y1], [x2, y2]) => 551 ([x1, y1], [x2, y2]) =>
511 let 552 let
531 Var v' => v' = v 572 Var v' => v' = v
532 | Proj (e, _) => matches e 573 | Proj (e, _) => matches e
533 | Func (f, [e]) => String.isPrefix "un" f andalso matches e 574 | Func (f, [e]) => String.isPrefix "un" f andalso matches e
534 | _ => false 575 | _ => false
535 in 576 in
577 (*Print.prefaces "Checking peers" [("e2", p_exp e2),
578 ("peers", Print.p_list p_exp (Cc.allPeers (cc, e2))),
579 ("db", Cc.p_t cc)];*)
536 List.exists matches (Cc.allPeers (cc, e2)) 580 List.exists matches (Cc.allPeers (cc, e2))
537 end 581 end
538 | _ => false) 582 | _ => false)
539 | _ => false 583 | _ => false
540 584
560 (false, (Known, _)) => gls goals onFail 604 (false, (Known, _)) => gls goals onFail
561 | _ => 605 | _ =>
562 let 606 let
563 fun hps hyps = 607 fun hps hyps =
564 case hyps of 608 case hyps of
565 [] => ((*Print.preface ("Fail", p_prop (Reln g));*) 609 [] => ((*Print.prefaces "Fail" [("g", p_prop (Reln g)),
610 ("db", Cc.p_t cc)];*)
566 onFail ()) 611 onFail ())
567 | ACond _ :: hyps => hps hyps 612 | ACond _ :: hyps => hps hyps
568 | AReln h :: hyps => 613 | AReln h :: hyps =>
569 let 614 let
570 val saved = save () 615 val saved = save ()
923 968
924 datatype queryMode = 969 datatype queryMode =
925 SomeCol of exp 970 SomeCol of exp
926 | AllCols of exp 971 | AllCols of exp
927 972
928 fun queryProp env rv oe e = 973 fun queryProp env rvN rv oe e =
929 case parse query e of 974 case parse query e of
930 NONE => (print ("Warning: Information flow checker can't parse SQL query at " 975 NONE => (print ("Warning: Information flow checker can't parse SQL query at "
931 ^ ErrorMsg.spanToString (#2 e) ^ "\n"); 976 ^ ErrorMsg.spanToString (#2 e) ^ "\n");
932 (Unknown, [])) 977 (rvN, Var 0, Unknown, []))
933 | SOME r => 978 | SOME r =>
934 let 979 let
980 val (rvN, count) = rv rvN
981
982 val (rvs, rvN) = ListUtil.foldlMap (fn ((_, v), rvN) =>
983 let
984 val (rvN, e) = rv rvN
985 in
986 ((v, e), rvN)
987 end) rvN (#From r)
988
989 fun rvOf v =
990 case List.find (fn (v', _) => v' = v) rvs of
991 NONE => raise Fail "Iflow.queryProp: Bad table variable"
992 | SOME (_, e) => e
993
935 fun usedFields e = 994 fun usedFields e =
936 case e of 995 case e of
937 SqConst _ => [] 996 SqConst _ => []
938 | Field (v, f) => [(v, f)] 997 | Field (v, f) => [(v, f)]
939 | Binop (_, e1, e2) => removeDups (usedFields e1 @ usedFields e2) 998 | Binop (_, e1, e2) => removeDups (usedFields e1 @ usedFields e2)
940 | SqKnown _ => [] 999 | SqKnown _ => []
941 | Inj _ => [] 1000 | Inj _ => []
942 | SqFunc (_, e) => usedFields e 1001 | SqFunc (_, e) => usedFields e
943 | Count => [] 1002 | Count => []
944 1003
945 val allUsed = removeDups (List.mapPartial (fn SqField x => SOME x | _ => NONE) (#Select r)
946 @ (case #Where r of
947 NONE => []
948 | SOME e => usedFields e))
949
950 val p = 1004 val p =
951 foldl (fn ((t, v), p) => 1005 foldl (fn ((t, v), p) => And (p, Reln (Sql t, [rvOf v]))) True (#From r)
952 And (p,
953 Reln (Sql t,
954 [Recd (foldl (fn ((v', f), fs) =>
955 if v' = v then
956 (f, Proj (Proj (rv, v), f)) :: fs
957 else
958 fs) [] allUsed)])))
959 True (#From r)
960 1006
961 fun expIn e = 1007 fun expIn e =
962 case e of 1008 case e of
963 SqConst p => inl (Const p) 1009 SqConst p => inl (Const p)
964 | Field (v, f) => inl (Proj (Proj (rv, v), f)) 1010 | Field (v, f) => inl (Proj (rvOf v, f))
965 | Binop (bo, e1, e2) => 1011 | Binop (bo, e1, e2) =>
966 inr (case (bo, expIn e1, expIn e2) of 1012 inr (case (bo, expIn e1, expIn e2) of
967 (Exps f, inl e1, inl e2) => f (e1, e2) 1013 (Exps f, inl e1, inl e2) => f (e1, e2)
968 | (Props f, inr p1, inr p2) => f (p1, p2) 1014 | (Props f, inr p1, inr p2) => f (p1, p2)
969 | _ => Unknown) 1015 | _ => Unknown)
983 end 1029 end
984 | SqFunc (f, e) => 1030 | SqFunc (f, e) =>
985 inl (case expIn e of 1031 inl (case expIn e of
986 inl e => Func (f, [e]) 1032 inl e => Func (f, [e])
987 | _ => raise Fail ("Iflow: non-expresion passed to function " ^ f)) 1033 | _ => raise Fail ("Iflow: non-expresion passed to function " ^ f))
988 | Count => inl (Proj (rv, "$COUNT")) 1034 | Count => inl count
989 1035
990 val p = case #Where r of 1036 val p = case #Where r of
991 NONE => p 1037 NONE => p
992 | SOME e => 1038 | SOME e =>
993 case expIn e of 1039 case expIn e of
994 inr p' => And (p, p') 1040 inr p' => And (p, p')
995 | _ => p 1041 | _ => p
996 in 1042 in
997 (And (p, case oe of 1043 (rvN,
1044 count,
1045 And (p, case oe of
998 SomeCol oe => 1046 SomeCol oe =>
999 foldl (fn (si, p) => 1047 foldl (fn (si, p) =>
1000 let 1048 let
1001 val p' = case si of 1049 val p' = case si of
1002 SqField (v, f) => Reln (Eq, [oe, Proj (Proj (rv, v), f)]) 1050 SqField (v, f) => Reln (Eq, [oe, Proj (rvOf v, f)])
1003 | SqExp (e, f) => 1051 | SqExp (e, f) =>
1004 case expIn e of 1052 case expIn e of
1005 inr _ => Unknown 1053 inr _ => Unknown
1006 | inl e => Reln (Eq, [oe, e]) 1054 | inl e => Reln (Eq, [oe, e])
1007 in 1055 in
1011 | AllCols oe => 1059 | AllCols oe =>
1012 foldl (fn (si, p) => 1060 foldl (fn (si, p) =>
1013 let 1061 let
1014 val p' = case si of 1062 val p' = case si of
1015 SqField (v, f) => Reln (Eq, [Proj (Proj (oe, v), f), 1063 SqField (v, f) => Reln (Eq, [Proj (Proj (oe, v), f),
1016 Proj (Proj (rv, v), f)]) 1064 Proj (rvOf v, f)])
1017 | SqExp (e, f) => 1065 | SqExp (e, f) =>
1018 case expIn e of 1066 case expIn e of
1019 inr p => Cond (Proj (oe, f), p) 1067 inr p => Cond (Proj (oe, f), p)
1020 | inl e => Reln (Eq, [Proj (oe, f), e]) 1068 | inl e => Reln (Eq, [Proj (oe, f), e])
1021 in 1069 in
1023 end) 1071 end)
1024 True (#Select r)), 1072 True (#Select r)),
1025 1073
1026 case #Where r of 1074 case #Where r of
1027 NONE => [] 1075 NONE => []
1028 | SOME e => map (fn (v, f) => Proj (Proj (rv, v), f)) (usedFields e)) 1076 | SOME e => map (fn (v, f) => Proj (rvOf v, f)) (usedFields e))
1029 end 1077 end
1030 1078
1031 fun evalPat env e (pt, _) = 1079 fun evalPat env e (pt, _) =
1032 case pt of 1080 case pt of
1033 PWild => (env, True) 1081 PWild => (env, True)
1116 | EFfiApp (m, s, es) => 1164 | EFfiApp (m, s, es) =>
1117 if m = "Basis" andalso SS.member (writers, s) then 1165 if m = "Basis" andalso SS.member (writers, s) then
1118 let 1166 let
1119 val (es, st) = ListUtil.foldlMap (evalExp env) st es 1167 val (es, st) = ListUtil.foldlMap (evalExp env) st es
1120 in 1168 in
1121 (Func ("unit", []), (#1 st, p, foldl (fn (e, sent) => addSent (#2 st, e, sent)) sent es)) 1169 (Recd [], (#1 st, p, foldl (fn (e, sent) => addSent (#2 st, e, sent)) sent es))
1122 end 1170 end
1123 else if Settings.isEffectful (m, s) andalso not (Settings.isBenignEffectful (m, s)) then 1171 else if Settings.isEffectful (m, s) andalso not (Settings.isBenignEffectful (m, s)) then
1124 default () 1172 default ()
1125 else 1173 else
1126 let 1174 let
1211 end 1259 end
1212 | EWrite e => 1260 | EWrite e =>
1213 let 1261 let
1214 val (e, st) = evalExp env (e, st) 1262 val (e, st) = evalExp env (e, st)
1215 in 1263 in
1216 (Func ("unit", []), (#1 st, p, addSent (#2 st, e, sent))) 1264 (Recd [], (#1 st, p, addSent (#2 st, e, sent)))
1217 end 1265 end
1218 | ESeq (e1, e2) => 1266 | ESeq (e1, e2) =>
1219 let 1267 let
1220 val (_, st) = evalExp env (e1, st) 1268 val (_, st) = evalExp env (e1, st)
1221 in 1269 in
1238 let 1286 let
1239 val (_, st) = evalExp env (q, st) 1287 val (_, st) = evalExp env (q, st)
1240 val (i, st) = evalExp env (i, st) 1288 val (i, st) = evalExp env (i, st)
1241 1289
1242 val r = #1 st 1290 val r = #1 st
1243 val rv = #1 st + 1 1291 val acc = #1 st + 1
1244 val acc = #1 st + 2 1292 val st' = (#1 st + 2, #2 st, #3 st)
1245 val st' = (#1 st + 3, #2 st, #3 st)
1246 1293
1247 val (b, st') = evalExp (Var acc :: Var r :: env) (b, st') 1294 val (b, st') = evalExp (Var acc :: Var r :: env) (b, st')
1248 1295
1249 val (qp, used) = queryProp env (Var rv) (AllCols (Var r)) q 1296 val (rvN, count, qp, used) =
1297 queryProp env
1298 (#1 st') (fn rvN => (rvN + 1, Var rvN))
1299 (AllCols (Var r)) q
1250 1300
1251 val p' = And (qp, #2 st') 1301 val p' = And (qp, #2 st')
1252 1302
1253 val (nvs, p, res) = if varInP acc (#2 st') then 1303 val (nvs, p, res) = if varInP acc (#2 st') then
1254 (#1 st + 1, #2 st, Var r) 1304 (#1 st + 1, #2 st, Var r)
1255 else 1305 else
1256 let 1306 let
1257 val out = #1 st' 1307 val out = rvN
1258 1308
1259 val p = Or (Reln (Eq, [Var out, i]), 1309 val p = Or (Reln (Eq, [Var out, i]),
1260 And (Reln (Eq, [Var out, b]), 1310 And (Reln (Eq, [Var out, b]),
1261 And (Reln (Gt, [Proj (Var rv, "$COUNT"), 1311 And (Reln (Gt, [count,
1262 Const (Prim.Int 0)]), 1312 Const (Prim.Int 0)]),
1263 p'))) 1313 p')))
1264 in 1314 in
1265 (out + 1, p, Var out) 1315 (out + 1, p, Var out)
1266 end 1316 end
1321 val (e, (_, p, sent)) = evalExp env (e, (nv, p, [])) 1371 val (e, (_, p, sent)) = evalExp env (e, (nv, p, []))
1322 in 1372 in
1323 (sent @ vals, pols) 1373 (sent @ vals, pols)
1324 end 1374 end
1325 1375
1326 | DPolicy (PolQuery e) => (vals, #1 (queryProp [] (Lvar 0) (SomeCol (Var 0)) e) :: pols) 1376 | DPolicy (PolClient e) => (vals, #3 (queryProp [] 0 (fn rvN => (rvN + 1, Lvar rvN))
1327 1377 (SomeCol (Var 0)) e) :: pols)
1378
1328 | _ => (vals, pols) 1379 | _ => (vals, pols)
1329 1380
1330 val () = reset () 1381 val () = reset ()
1331 1382
1332 val (vals, pols) = foldl decl ([], []) file 1383 val (vals, pols) = foldl decl ([], []) file