comparison src/iflow.sml @ 1245:5c2555dfce8f

Take advantage of equalities between get_cookie calls
author Adam Chlipala <adamc@hcoop.net>
date Sun, 18 Apr 2010 13:56:47 -0400
parents 1eedc9086e6c
children fd4028a594a9
comparison
equal deleted inserted replaced
1244:1eedc9086e6c 1245:5c2555dfce8f
270 270
271 datatype node = Node of {Id : int, 271 datatype node = Node of {Id : int,
272 Rep : node ref option ref, 272 Rep : node ref option ref,
273 Cons : node ref SM.map ref, 273 Cons : node ref SM.map ref,
274 Variety : variety, 274 Variety : variety,
275 Known : bool ref} 275 Known : bool ref,
276 Ge : Int64.int option ref}
276 277
277 and variety = 278 and variety =
278 Dt0 of string 279 Dt0 of string
279 | Dt1 of string * node ref 280 | Dt1 of string * node ref
280 | Prim of Prim.t 281 | Prim of Prim.t
332 string "}", 333 string "}",
333 if b then 334 if b then
334 box [space, 335 box [space,
335 string "(complete)"] 336 string "(complete)"]
336 else 337 else
337 box []]] 338 box []],
339 if !(#Known (unNode n)) then
340 string " (known)"
341 else
342 box [],
343 case !(#Ge (unNode n)) of
344 NONE => box []
345 | SOME n => string (" (>= " ^ Int64.toString n ^ ")")]
338 346
339 fun p_database (db : database) = 347 fun p_database (db : database) =
340 box [string "Vars:", 348 box [string "Vars:",
341 newline, 349 newline,
342 p_list_sep newline (fn (i, n) => box [string ("x" ^ Int.toString i), 350 p_list_sep newline (fn (i, n) => box [string ("x" ^ Int.toString i),
343 space, 351 space,
344 string "=", 352 string "=",
345 space, 353 space,
346 p_rep n, 354 p_rep n]) (IM.listItemsi (!(#Vars db)))]
347 if !(#Known (unNode n)) then
348 box [space,
349 string "(known)"]
350 else
351 box []]) (IM.listItemsi (!(#Vars db)))]
352 355
353 fun repOf (n : representative) : representative = 356 fun repOf (n : representative) : representative =
354 case !(#Rep (unNode n)) of 357 case !(#Rep (unNode n)) of
355 NONE => n 358 NONE => n
356 | SOME r => 359 | SOME r =>
387 let 390 let
388 val r = ref (Node {Id = nodeId (), 391 val r = ref (Node {Id = nodeId (),
389 Rep = ref NONE, 392 Rep = ref NONE,
390 Cons = ref SM.empty, 393 Cons = ref SM.empty,
391 Variety = Prim p, 394 Variety = Prim p,
392 Known = ref true}) 395 Known = ref true,
396 Ge = ref (case p of
397 Prim.Int n => SOME n
398 | _ => NONE)})
393 in 399 in
394 #Consts db := CM.insert (!(#Consts db), p, r); 400 #Consts db := CM.insert (!(#Consts db), p, r);
395 r 401 r
396 end) 402 end)
397 | Var n => (case IM.find (!(#Vars db), n) of 403 | Var n => (case IM.find (!(#Vars db), n) of
400 let 406 let
401 val r = ref (Node {Id = nodeId (), 407 val r = ref (Node {Id = nodeId (),
402 Rep = ref NONE, 408 Rep = ref NONE,
403 Cons = ref SM.empty, 409 Cons = ref SM.empty,
404 Variety = Nothing, 410 Variety = Nothing,
405 Known = ref false}) 411 Known = ref false,
412 Ge = ref NONE})
406 in 413 in
407 #Vars db := IM.insert (!(#Vars db), n, r); 414 #Vars db := IM.insert (!(#Vars db), n, r);
408 r 415 r
409 end) 416 end)
410 | Lvar _ => raise Undetermined 417 | Lvar _ => raise Undetermined
414 let 421 let
415 val r = ref (Node {Id = nodeId (), 422 val r = ref (Node {Id = nodeId (),
416 Rep = ref NONE, 423 Rep = ref NONE,
417 Cons = ref SM.empty, 424 Cons = ref SM.empty,
418 Variety = Dt0 f, 425 Variety = Dt0 f,
419 Known = ref true}) 426 Known = ref true,
427 Ge = ref NONE})
420 in 428 in
421 #Con0s db := SM.insert (!(#Con0s db), f, r); 429 #Con0s db := SM.insert (!(#Con0s db), f, r);
422 r 430 r
423 end) 431 end)
424 | Func (DtCon0 _, _) => raise Fail "Iflow.rep: DtCon0" 432 | Func (DtCon0 _, _) => raise Fail "Iflow.rep: DtCon0"
432 let 440 let
433 val r' = ref (Node {Id = nodeId (), 441 val r' = ref (Node {Id = nodeId (),
434 Rep = ref NONE, 442 Rep = ref NONE,
435 Cons = ref SM.empty, 443 Cons = ref SM.empty,
436 Variety = Dt1 (f, r), 444 Variety = Dt1 (f, r),
437 Known = ref (!(#Known (unNode r)))}) 445 Known = ref (!(#Known (unNode r))),
446 Ge = ref NONE})
438 in 447 in
439 #Cons (unNode r) := SM.insert (!(#Cons (unNode r)), f, r'); 448 #Cons (unNode r) := SM.insert (!(#Cons (unNode r)), f, r');
440 r' 449 r'
441 end 450 end
442 end 451 end
455 val cons = ref SM.empty 464 val cons = ref SM.empty
456 val r' = ref (Node {Id = nodeId (), 465 val r' = ref (Node {Id = nodeId (),
457 Rep = ref NONE, 466 Rep = ref NONE,
458 Cons = cons, 467 Cons = cons,
459 Variety = Nothing, 468 Variety = Nothing,
460 Known = ref (!(#Known (unNode r)))}) 469 Known = ref (!(#Known (unNode r))),
470 Ge = ref NONE})
461 471
462 val r'' = ref (Node {Id = nodeId (), 472 val r'' = ref (Node {Id = nodeId (),
463 Rep = ref NONE, 473 Rep = ref NONE,
464 Cons = #Cons (unNode r), 474 Cons = #Cons (unNode r),
465 Variety = Dt1 (f, r'), 475 Variety = Dt1 (f, r'),
466 Known = #Known (unNode r)}) 476 Known = #Known (unNode r),
477 Ge = ref NONE})
467 in 478 in
468 cons := SM.insert (!cons, f, r''); 479 cons := SM.insert (!cons, f, r'');
469 #Rep (unNode r) := SOME r''; 480 #Rep (unNode r) := SOME r'';
470 r' 481 r'
471 end 482 end
481 let 492 let
482 val r = ref (Node {Id = nodeId (), 493 val r = ref (Node {Id = nodeId (),
483 Rep = ref NONE, 494 Rep = ref NONE,
484 Cons = ref SM.empty, 495 Cons = ref SM.empty,
485 Variety = Nothing, 496 Variety = Nothing,
486 Known = ref false}) 497 Known = ref false,
498 Ge = ref NONE})
487 in 499 in
488 #Funcs db := ((f, rs), r) :: (!(#Funcs db)); 500 #Funcs db := ((f, rs), r) :: (!(#Funcs db));
489 r 501 r
490 end 502 end
491 | SOME (_, r) => repOf r 503 | SOME (_, r) => repOf r
509 521
510 val r' = ref (Node {Id = nodeId (), 522 val r' = ref (Node {Id = nodeId (),
511 Rep = ref NONE, 523 Rep = ref NONE,
512 Cons = ref SM.empty, 524 Cons = ref SM.empty,
513 Variety = Recrd (ref xes, true), 525 Variety = Recrd (ref xes, true),
514 Known = ref false}) 526 Known = ref false,
527 Ge = ref NONE})
515 in 528 in
516 #Records db := (xes, r') :: (!(#Records db)); 529 #Records db := (xes, r') :: (!(#Records db));
517 r' 530 r'
518 end 531 end
519 end 532 end
528 | NONE => let 541 | NONE => let
529 val r = ref (Node {Id = nodeId (), 542 val r = ref (Node {Id = nodeId (),
530 Rep = ref NONE, 543 Rep = ref NONE,
531 Cons = ref SM.empty, 544 Cons = ref SM.empty,
532 Variety = Nothing, 545 Variety = Nothing,
533 Known = ref (!(#Known (unNode r)))}) 546 Known = ref (!(#Known (unNode r))),
547 Ge = ref NONE})
534 in 548 in
535 xes := SM.insert (!xes, f, r); 549 xes := SM.insert (!xes, f, r);
536 r 550 r
537 end) 551 end)
538 | Nothing => 552 | Nothing =>
539 let 553 let
540 val r' = ref (Node {Id = nodeId (), 554 val r' = ref (Node {Id = nodeId (),
541 Rep = ref NONE, 555 Rep = ref NONE,
542 Cons = ref SM.empty, 556 Cons = ref SM.empty,
543 Variety = Nothing, 557 Variety = Nothing,
544 Known = ref (!(#Known (unNode r)))}) 558 Known = ref (!(#Known (unNode r))),
559 Ge = ref NONE})
545 560
546 val r'' = ref (Node {Id = nodeId (), 561 val r'' = ref (Node {Id = nodeId (),
547 Rep = ref NONE, 562 Rep = ref NONE,
548 Cons = #Cons (unNode r), 563 Cons = #Cons (unNode r),
549 Variety = Recrd (ref (SM.insert (SM.empty, f, r')), false), 564 Variety = Recrd (ref (SM.insert (SM.empty, f, r')), false),
550 Known = #Known (unNode r)}) 565 Known = #Known (unNode r),
566 Ge = ref NONE})
551 in 567 in
552 #Rep (unNode r) := SOME r''; 568 #Rep (unNode r) := SOME r'';
553 r' 569 r'
554 end 570 end
555 | _ => raise Contradiction 571 | _ => raise Contradiction
607 if !(#Known (unNode r2)) then 623 if !(#Known (unNode r2)) then
608 markKnown r1 624 markKnown r1
609 else 625 else
610 (); 626 ();
611 #Cons (unNode r2) := SM.unionWith #1 (!(#Cons (unNode r2)), !(#Cons (unNode r1))); 627 #Cons (unNode r2) := SM.unionWith #1 (!(#Cons (unNode r2)), !(#Cons (unNode r1)));
628
629 case !(#Ge (unNode r1)) of
630 NONE => ()
631 | SOME n1 =>
632 case !(#Ge (unNode r2)) of
633 NONE => #Ge (unNode r2) := SOME n1
634 | SOME n2 => #Ge (unNode r2) := SOME (Int64.max (n1, n2));
612 635
613 compactFuncs ()) 636 compactFuncs ())
614 637
615 and compactFuncs () = 638 and compactFuncs () =
616 let 639 let
661 let 684 let
662 val r' = ref (Node {Id = nodeId (), 685 val r' = ref (Node {Id = nodeId (),
663 Rep = ref NONE, 686 Rep = ref NONE,
664 Cons = ref SM.empty, 687 Cons = ref SM.empty,
665 Variety = Dt0 f, 688 Variety = Dt0 f,
666 Known = ref false}) 689 Known = ref false,
690 Ge = ref NONE})
667 in 691 in
668 #Rep (unNode r) := SOME r'; 692 #Rep (unNode r) := SOME r';
669 #Con0s db := SM.insert (!(#Con0s db), f, r') 693 #Con0s db := SM.insert (!(#Con0s db), f, r')
670 end) 694 end)
671 | _ => raise Contradiction 695 | _ => raise Contradiction
683 let 707 let
684 val r'' = ref (Node {Id = nodeId (), 708 val r'' = ref (Node {Id = nodeId (),
685 Rep = ref NONE, 709 Rep = ref NONE,
686 Cons = ref SM.empty, 710 Cons = ref SM.empty,
687 Variety = Nothing, 711 Variety = Nothing,
688 Known = ref (!(#Known (unNode r)))}) 712 Known = ref (!(#Known (unNode r))),
713 Ge = ref NONE})
689 714
690 val r' = ref (Node {Id = nodeId (), 715 val r' = ref (Node {Id = nodeId (),
691 Rep = ref NONE, 716 Rep = ref NONE,
692 Cons = ref SM.empty, 717 Cons = ref SM.empty,
693 Variety = Dt1 (f, r''), 718 Variety = Dt1 (f, r''),
694 Known = #Known (unNode r)}) 719 Known = #Known (unNode r),
720 Ge = ref NONE})
695 in 721 in
696 #Rep (unNode r) := SOME r' 722 #Rep (unNode r) := SOME r'
697 end 723 end
698 | _ => raise Contradiction 724 | _ => raise Contradiction
699 end 725 end
700 | (Eq, [e1, e2]) => 726 | (Eq, [e1, e2]) =>
701 markEq (representative (db, e1), representative (db, e2)) 727 markEq (representative (db, e1), representative (db, e2))
728 | (Ge, [e1, e2]) =>
729 let
730 val r1 = representative (db, e1)
731 val r2 = representative (db, e2)
732 in
733 case !(#Ge (unNode (repOf r2))) of
734 NONE => ()
735 | SOME n2 =>
736 case !(#Ge (unNode (repOf r1))) of
737 NONE => #Ge (unNode (repOf r1)) := SOME n2
738 | SOME n1 => #Ge (unNode (repOf r1)) := SOME (Int64.max (n1, n2))
739 end
702 | _ => () 740 | _ => ()
703 end 741 end
704 742
705 fun check (db, a) = 743 fun check (db, a) =
706 case a of 744 case a of
737 val r1 = representative (db, e1) 775 val r1 = representative (db, e1)
738 val r2 = representative (db, e2) 776 val r2 = representative (db, e2)
739 in 777 in
740 repOf r1 = repOf r2 778 repOf r1 = repOf r2
741 end 779 end
780 | (Ge, [e1, e2]) =>
781 let
782 val r1 = representative (db, e1)
783 val r2 = representative (db, e2)
784 in
785 case (!(#Ge (unNode (repOf r1))), #Variety (unNode (repOf r2))) of
786 (SOME n1, Prim (Prim.Int n2)) => Int64.>= (n1, n2)
787 | _ => false
788 end
742 | _ => false 789 | _ => false
743 790
744 fun builtFrom (db, {UseKnown = uk, Base = bs, Derived = d}) = 791 fun builtFrom (db, {UseKnown = uk, Base = bs, Derived = d}) =
745 let 792 let
746 val bs = map (fn b => representative (db, b)) bs 793 val bs = map (fn b => representative (db, b)) bs
929 | Computed of string 976 | Computed of string
930 | Binop of Rel * sqexp * sqexp 977 | Binop of Rel * sqexp * sqexp
931 | SqKnown of sqexp 978 | SqKnown of sqexp
932 | Inj of Mono.exp 979 | Inj of Mono.exp
933 | SqFunc of string * sqexp 980 | SqFunc of string * sqexp
934 | Count 981 | Unmodeled
935 982
936 fun cmp s r = wrap (const s) (fn () => Exps (fn (e1, e2) => Reln (r, [e1, e2]))) 983 fun cmp s r = wrap (const s) (fn () => Exps (fn (e1, e2) => Reln (r, [e1, e2])))
937 984
938 val sqbrel = altL [cmp "=" Eq, 985 val sqbrel = altL [cmp "=" Eq,
939 cmp "<>" Ne, 986 cmp "<>" Ne,
1009 constK "MIN", 1056 constK "MIN",
1010 constK "MAX", 1057 constK "MAX",
1011 constK "SUM", 1058 constK "SUM",
1012 constK "AVG"] 1059 constK "AVG"]
1013 1060
1061 val unmodeled = altL [const "COUNT(*)",
1062 const "CURRENT_TIMESTAMP"]
1063
1014 fun sqexp chs = 1064 fun sqexp chs =
1015 log "sqexp" 1065 log "sqexp"
1016 (altL [wrap prim SqConst, 1066 (altL [wrap prim SqConst,
1017 wrap (const "TRUE") (fn () => SqTrue), 1067 wrap (const "TRUE") (fn () => SqTrue),
1018 wrap (const "FALSE") (fn () => SqFalse), 1068 wrap (const "FALSE") (fn () => SqFalse),
1019 wrap field Field, 1069 wrap field Field,
1020 wrap uw_ident Computed, 1070 wrap uw_ident Computed,
1021 wrap known SqKnown, 1071 wrap known SqKnown,
1022 wrap func SqFunc, 1072 wrap func SqFunc,
1023 wrap (const "COUNT(*)") (fn () => Count), 1073 wrap unmodeled (fn () => Unmodeled),
1024 wrap sqlify Inj, 1074 wrap sqlify Inj,
1025 wrap (follow (const "COALESCE(") (follow sqexp (follow (const ",") 1075 wrap (follow (const "COALESCE(") (follow sqexp (follow (const ",")
1026 (follow (keep (fn ch => ch <> #")")) (const ")"))))) 1076 (follow (keep (fn ch => ch <> #")")) (const ")")))))
1027 (fn ((), (e, _)) => e), 1077 (fn ((), (e, _)) => e),
1028 wrap (follow (ws (const "(")) 1078 wrap (follow (ws (const "("))
1172 1222
1173 val allowUpdate : atom list -> unit 1223 val allowUpdate : atom list -> unit
1174 val update : ErrorMsg.span -> unit 1224 val update : ErrorMsg.span -> unit
1175 1225
1176 val havocReln : reln -> unit 1226 val havocReln : reln -> unit
1227 val havocCookie : string -> unit
1177 1228
1178 val debug : unit -> unit 1229 val debug : unit -> unit
1179 end = struct 1230 end = struct
1180 1231
1181 val hnames = ref 1 1232 val hnames = ref 1
1327 in 1378 in
1328 tryAll unifs hyps 1379 tryAll unifs hyps
1329 end 1380 end
1330 | (g as AReln (r, es)) :: goals => 1381 | (g as AReln (r, es)) :: goals =>
1331 (complete (); 1382 (complete ();
1332 Cc.check (db, AReln (r, map (simplify unifs) es)) 1383 (if Cc.check (db, AReln (r, map (simplify unifs) es)) then
1384 true
1385 else
1386 ((*Print.preface ("Fail", p_atom (AReln (r, map (simplify unifs) es)));*)
1387 false))
1333 andalso checkGoals goals unifs) 1388 andalso checkGoals goals unifs)
1334 | ACond _ :: _ => false 1389 | ACond _ :: _ => false
1335 in 1390 in
1336 checkGoals goals IM.empty 1391 checkGoals goals IM.empty
1337 end 1392 end
1353 else 1408 else
1354 let 1409 let
1355 val (_, hs, _) = !hyps 1410 val (_, hs, _) = !hyps
1356 in 1411 in
1357 ErrorMsg.errorAt loc "The information flow policy may be violated here."; 1412 ErrorMsg.errorAt loc "The information flow policy may be violated here.";
1358 Print.prefaces "Situation" [("Hypotheses", Print.p_list p_atom hs), 1413 Print.prefaces "Situation" [("User learns", p_exp e),
1359 ("User learns", p_exp e)(*, 1414 ("Hypotheses", Print.p_list p_atom hs)(*,
1360 ("E-graph", Cc.p_database db)*)] 1415 ("E-graph", Cc.p_database db)*)]
1361 end 1416 end
1362 end 1417 end
1363 1418
1364 fun checkPaths () = 1419 fun checkPaths () =
1406 else 1461 else
1407 let 1462 let
1408 val (_, hs, _) = !hyps 1463 val (_, hs, _) = !hyps
1409 in 1464 in
1410 ErrorMsg.errorAt loc "The database update policy may be violated here."; 1465 ErrorMsg.errorAt loc "The database update policy may be violated here.";
1411 Print.preface ("Hypotheses", Print.p_list p_atom hs) 1466 Print.prefaces "Situation" [("Hypotheses", Print.p_list p_atom hs)(*,
1467 ("E-graph", Cc.p_database db)*)]
1412 end 1468 end
1413 end 1469 end
1414 1470
1415 val insertable = ref ([] : atom list list) 1471 val insertable = ref ([] : atom list list)
1416 fun allowInsert v = insertable := v :: !insertable 1472 fun allowInsert v = insertable := v :: !insertable
1438 val n = !hnames 1494 val n = !hnames
1439 val (_, hs, _) = !hyps 1495 val (_, hs, _) = !hyps
1440 in 1496 in
1441 hnames := n + 1; 1497 hnames := n + 1;
1442 hyps := (n, List.filter (fn AReln (r', _) => r' <> r | _ => true) hs, ref false) 1498 hyps := (n, List.filter (fn AReln (r', _) => r' <> r | _ => true) hs, ref false)
1499 end
1500
1501 fun havocCookie cname =
1502 let
1503 val cname = "cookie/" ^ cname
1504 val n = !hnames
1505 val (_, hs, _) = !hyps
1506 in
1507 hnames := n + 1;
1508 hyps := (n, List.filter (fn AReln (Eq, [_, Func (Other f, [])]) => f <> cname | _ => true) hs, ref false)
1443 end 1509 end
1444 1510
1445 fun debug () = 1511 fun debug () =
1446 let 1512 let
1447 val (_, hs, _) = !hyps 1513 val (_, hs, _) = !hyps
1515 | SqFunc (f, e) => 1581 | SqFunc (f, e) =>
1516 (case expIn e of 1582 (case expIn e of
1517 inl e => inl (Func (Other f, [e])) 1583 inl e => inl (Func (Other f, [e]))
1518 | _ => default ()) 1584 | _ => default ())
1519 1585
1520 | Count => default () 1586 | Unmodeled => default ()
1521 end 1587 end
1522 in 1588 in
1523 expIn 1589 expIn
1524 end 1590 end
1525 1591
1608 (case deinj (#Env arg) e of 1674 (case deinj (#Env arg) e of
1609 NONE => (ErrorMsg.errorAt loc "Expression injected into SQL is too complicated"; 1675 NONE => (ErrorMsg.errorAt loc "Expression injected into SQL is too complicated";
1610 []) 1676 [])
1611 | SOME e => [(true, e)]) 1677 | SOME e => [(true, e)])
1612 | SqFunc (_, e) => usedFields e 1678 | SqFunc (_, e) => usedFields e
1613 | Count => [] 1679 | Unmodeled => []
1614 1680
1615 fun doUsed () = case #Where r of 1681 fun doUsed () = case #Where r of
1616 NONE => () 1682 NONE => ()
1617 | SOME e => 1683 | SOME e =>
1618 app (#UsedExp arg) (usedFields e) 1684 app (#UsedExp arg) (usedFields e)
1749 fun doFfi (m, s, es) = 1815 fun doFfi (m, s, es) =
1750 if m = "Basis" andalso SS.member (writers, s) then 1816 if m = "Basis" andalso SS.member (writers, s) then
1751 let 1817 let
1752 fun doArgs es = 1818 fun doArgs es =
1753 case es of 1819 case es of
1754 [] => k (Recd []) 1820 [] =>
1821 (if s = "set_cookie" then
1822 case es of
1823 [_, cname, _, _, _] =>
1824 (case #1 cname of
1825 EPrim (Prim.String cname) =>
1826 St.havocCookie cname
1827 | _ => ())
1828 | _ => ()
1829 else
1830 ();
1831 k (Recd []))
1755 | e :: es => 1832 | e :: es =>
1756 evalExp env e (fn e => (St.send true (e, loc); doArgs es)) 1833 evalExp env e (fn e => (St.send true (e, loc); doArgs es))
1757 in 1834 in
1758 doArgs es 1835 doArgs es
1759 end 1836 end
1994 | ESetval _ => default () 2071 | ESetval _ => default ()
1995 2072
1996 | EUnurlify ((EFfiApp ("Basis", "get_cookie", [(EPrim (Prim.String cname), _)]), _), _, _) => 2073 | EUnurlify ((EFfiApp ("Basis", "get_cookie", [(EPrim (Prim.String cname), _)]), _), _, _) =>
1997 let 2074 let
1998 val e = Var (St.nextVar ()) 2075 val e = Var (St.nextVar ())
2076 val e' = Func (Other ("cookie/" ^ cname), [])
1999 in 2077 in
2000 St.assert [AReln (Known, [e])]; 2078 St.assert [AReln (Known, [e]), AReln (Eq, [e, e'])];
2001 k e 2079 k e
2002 end 2080 end
2003 2081
2004 | EUnurlify _ => default () 2082 | EUnurlify _ => default ()
2005 | EJavaScript _ => default () 2083 | EJavaScript _ => default ()