comparison src/iflow.sml @ 1210:c5bd970e77a5

Parsing more comparison operators
author Adam Chlipala <adamc@hcoop.net>
date Tue, 06 Apr 2010 12:04:08 -0400
parents 775357041e48
children 1d4d65245dd3
comparison
equal deleted inserted replaced
1209:775357041e48 1210:c5bd970e77a5
66 66
67 datatype reln = 67 datatype reln =
68 Known 68 Known
69 | Sql of string 69 | Sql of string
70 | Eq 70 | Eq
71 | Ne
72 | Lt
73 | Le
74 | Gt
75 | Ge
71 76
72 datatype prop = 77 datatype prop =
73 True 78 True
74 | False 79 | False
75 | Unknown 80 | Unknown
90 | Lvar n => string ("X" ^ Int.toString n) 95 | Lvar n => string ("X" ^ Int.toString n)
91 | Func (f, es) => box [string (f ^ "("), 96 | Func (f, es) => box [string (f ^ "("),
92 p_list p_exp es, 97 p_list p_exp es,
93 string ")"] 98 string ")"]
94 | Recd xes => box [string "{", 99 | Recd xes => box [string "{",
95 p_list (fn (x, e) => box [string "x", 100 p_list (fn (x, e) => box [string x,
96 space, 101 space,
97 string "=", 102 string "=",
98 space, 103 space,
99 p_exp e]) xes, 104 p_exp e]) xes,
100 string "}"] 105 string "}"]
101 | Proj (e, x) => box [p_exp e, 106 | Proj (e, x) => box [p_exp e,
102 string ("." ^ x)] 107 string ("." ^ x)]
103 | Finish => string "FINISH" 108 | Finish => string "FINISH"
109
110 fun p_bop s es =
111 case es of
112 [e1, e2] => box [p_exp e1,
113 space,
114 string s,
115 space,
116 p_exp e2]
117 | _ => raise Fail "Iflow.p_bop"
104 118
105 fun p_reln r es = 119 fun p_reln r es =
106 case r of 120 case r of
107 Known => 121 Known =>
108 (case es of 122 (case es of
111 string ")"] 125 string ")"]
112 | _ => raise Fail "Iflow.p_reln: Known") 126 | _ => raise Fail "Iflow.p_reln: Known")
113 | Sql s => box [string (s ^ "("), 127 | Sql s => box [string (s ^ "("),
114 p_list p_exp es, 128 p_list p_exp es,
115 string ")"] 129 string ")"]
116 | Eq => 130 | Eq => p_bop "=" es
117 (case es of 131 | Ne => p_bop "<>" es
118 [e1, e2] => box [p_exp e1, 132 | Lt => p_bop "<" es
119 space, 133 | Le => p_bop "<=" es
120 string "=", 134 | Gt => p_bop ">" es
121 space, 135 | Ge => p_bop ">=" es
122 p_exp e2]
123 | _ => raise Fail "Iflow.p_reln: Eq")
124 136
125 fun p_prop p = 137 fun p_prop p =
126 case p of 138 case p of
127 True => string "True" 139 True => string "True"
128 | False => string "False" 140 | False => string "False"
658 670
659 val t_ident = wrap ident (fn s => if String.isPrefix "T_" s then 671 val t_ident = wrap ident (fn s => if String.isPrefix "T_" s then
660 String.extract (s, 2, NONE) 672 String.extract (s, 2, NONE)
661 else 673 else
662 raise Fail "Iflow: Bad table variable") 674 raise Fail "Iflow: Bad table variable")
663 val uw_ident = wrap ident (fn s => if String.isPrefix "uw_" s then 675 val uw_ident = wrap ident (fn s => if String.isPrefix "uw_" s andalso size s >= 4 then
664 String.extract (s, 3, NONE) 676 str (Char.toUpper (String.sub (s, 3)))
677 ^ String.extract (s, 4, NONE)
665 else 678 else
666 raise Fail "Iflow: Bad uw_* variable") 679 raise Fail "Iflow: Bad uw_* variable")
667 680
668 val sitem = wrap (follow t_ident 681 val sitem = wrap (follow t_ident
669 (follow (const ".") 682 (follow (const ".")
679 | Field of string * string 692 | Field of string * string
680 | Binop of Rel * sqexp * sqexp 693 | Binop of Rel * sqexp * sqexp
681 | SqKnown of sqexp 694 | SqKnown of sqexp
682 | Inj of Mono.exp 695 | Inj of Mono.exp
683 696
684 val sqbrel = altL [wrap (const "=") (fn () => Exps (fn (e1, e2) => Reln (Eq, [e1, e2]))), 697 fun cmp s r = wrap (const s) (fn () => Exps (fn (e1, e2) => Reln (r, [e1, e2])))
698
699 val sqbrel = altL [cmp "=" Eq,
700 cmp "<>" Ne,
701 cmp "<=" Le,
702 cmp "<" Lt,
703 cmp ">=" Ge,
704 cmp ">" Gt,
685 wrap (const "AND") (fn () => Props And), 705 wrap (const "AND") (fn () => Props And),
686 wrap (const "OR") (fn () => Props Or)] 706 wrap (const "OR") (fn () => Props Or)]
687 707
688 datatype ('a, 'b) sum = inl of 'a | inr of 'b 708 datatype ('a, 'b) sum = inl of 'a | inr of 'b
689 709
786 806
787 fun queryProp env rv oe e = 807 fun queryProp env rv oe e =
788 case parse query e of 808 case parse query e of
789 NONE => (print ("Warning: Information flow checker can't parse SQL query at " 809 NONE => (print ("Warning: Information flow checker can't parse SQL query at "
790 ^ ErrorMsg.spanToString (#2 e) ^ "\n"); 810 ^ ErrorMsg.spanToString (#2 e) ^ "\n");
791 Unknown) 811 (Unknown, []))
792 | SOME r => 812 | SOME r =>
793 let 813 let
794 val p = 814 val p =
795 foldl (fn ((t, v), p) => 815 foldl (fn ((t, v), p) =>
796 And (p, 816 And (p,
824 | _ => raise Fail "Iflow: non-variable injected into query" 844 | _ => raise Fail "Iflow: non-variable injected into query"
825 in 845 in
826 inl (deinj e) 846 inl (deinj e)
827 end 847 end
828 848
849 fun usedFields e =
850 case e of
851 SqConst _ => []
852 | Field (v, f) => [Proj (Proj (Lvar rv, v), f)]
853 | Binop (_, e1, e2) => usedFields e1 @ usedFields e2
854 | SqKnown _ => []
855 | Inj _ => []
856
829 val p = case #Where r of 857 val p = case #Where r of
830 NONE => p 858 NONE => p
831 | SOME e => 859 | SOME e =>
832 case expIn e of 860 case expIn e of
833 inr p' => And (p, p') 861 inr p' => And (p, p')
834 | _ => p 862 | _ => p
835 in 863 in
836 case oe of 864 (case oe of
837 NONE => p 865 NONE => p
838 | SOME oe => 866 | SOME oe =>
839 And (p, foldl (fn ((v, f), p) => 867 And (p, foldl (fn ((v, f), p) =>
840 Or (p, 868 Or (p,
841 Reln (Eq, [oe, Proj (Proj (Lvar rv, v), f)]))) 869 Reln (Eq, [oe, Proj (Proj (Lvar rv, v), f)])))
842 False (#Select r)) 870 False (#Select r)),
871
872 case #Where r of
873 NONE => []
874 | SOME e => usedFields e)
843 end 875 end
844 876
845 fun evalExp env (e as (_, loc), st as (nv, p, sent)) = 877 fun evalExp env (e as (_, loc), st as (nv, p, sent)) =
846 let 878 let
847 fun default () = 879 fun default () =
977 1009
978 val (b, st') = evalExp (Var acc :: Var r :: env) (b, st') 1010 val (b, st') = evalExp (Var acc :: Var r :: env) (b, st')
979 1011
980 val r' = newLvar () 1012 val r' = newLvar ()
981 val acc' = newLvar () 1013 val acc' = newLvar ()
982 val qp = queryProp env r' NONE q 1014 val (qp, used) = queryProp env r' NONE q
983 1015
984 val doSubExp = subExp (r, r') o subExp (acc, acc') 1016 val doSubExp = subExp (r, r') o subExp (acc, acc')
985 val doSubProp = subProp (r, r') o subProp (acc, acc') 1017 val doSubProp = subProp (r, r') o subProp (acc, acc')
986 1018
987 val p = doSubProp (#2 st') 1019 val p = doSubProp (#2 st')
988 val p = And (p, qp) 1020 val p' = And (p, qp)
989 val p = Select (r, r', acc', p, doSubExp b) 1021 val p = Select (r, r', acc', p', doSubExp b)
990 in 1022
991 (Var r, (#1 st + 1, And (#2 st, p), map (fn (loc, e, p) => (loc, 1023 val sent = map (fn (loc, e, p) => (loc,
992 doSubExp e, 1024 doSubExp e,
993 And (qp, doSubProp p))) (#3 st'))) 1025 And (qp, doSubProp p))) (#3 st')
1026 val sent = map (fn e => (loc, e, p')) used @ sent
1027 in
1028 (Var r, (#1 st + 1, And (#2 st, p), sent))
994 end 1029 end
995 | EDml _ => default () 1030 | EDml _ => default ()
996 | ENextval _ => default () 1031 | ENextval _ => default ()
997 | ESetval _ => default () 1032 | ESetval _ => default ()
998 1033
1034 val (e, (_, p, sent)) = evalExp env (e, (nv, p, [])) 1069 val (e, (_, p, sent)) = evalExp env (e, (nv, p, []))
1035 in 1070 in
1036 (sent @ vals, pols) 1071 (sent @ vals, pols)
1037 end 1072 end
1038 1073
1039 | DPolicy (PolQuery e) => (vals, queryProp [] 0 (SOME (Var 0)) e :: pols) 1074 | DPolicy (PolQuery e) => (vals, #1 (queryProp [] 0 (SOME (Var 0)) e) :: pols)
1040 1075
1041 | _ => (vals, pols) 1076 | _ => (vals, pols)
1042 1077
1043 val () = reset () 1078 val () = reset ()
1044 1079