├── Makefile.in ├── Mutation.mli ├── README.md ├── VERSION ├── configure.ac ├── mut_options.ml ├── mut_register.ml └── tests ├── search ├── oracle │ ├── search.err.oracle │ └── search.res.oracle └── search.c └── test_config.in /Makefile.in: -------------------------------------------------------------------------------- 1 | ####################### 2 | # Frama-C Environment # 3 | ####################### 4 | 5 | ifndef FRAMAC_SHARE 6 | FRAMAC_SHARE := $(shell frama-c-config -print-share-path) 7 | endif 8 | 9 | ifndef FRAMAC_LIBDIR 10 | FRAMAC_LIBDIR := $(shell frama-c-config -print-libpath) 11 | endif 12 | 13 | ######################### 14 | # Plug-in configuration # 15 | ######################### 16 | 17 | PLUGIN_DIR ?=. 18 | PLUGIN_NAME := Mutation 19 | PLUGIN_CMO := local_config mut_options mut_register 20 | PLUGIN_GUI_CMO := 21 | PLUGIN_HAS_MLI:= yes 22 | PLUGIN_TESTS_DIRS:= search 23 | PLUGIN_GENERATED:= $(PLUGIN_DIR)/local_config.ml 24 | 25 | $(PLUGIN_DIR)/tests/test_config: $(PLUGIN_DIR)/tests/test_config.in 26 | $(PRINT_MAKING) $@ 27 | $(RM) $@ 28 | $(SED) -e "s|__PLUGIN_PATH__|`frama-c-config -print-plugin-path`|g" $^ > $@ 29 | $(CHMOD_RO) $@ 30 | 31 | tests:: $(PLUGIN_DIR)/tests/test_config 32 | 33 | ################ 34 | # Generic part # 35 | ################ 36 | 37 | include $(FRAMAC_SHARE)/Makefile.dynamic 38 | 39 | distclean: clean 40 | $(PRINT_RM) "any generated files" 41 | $(RM) -rf autom4te.cache 42 | $(RM) configure config.status config.log 43 | $(RM) -rf .frama-c 44 | $(RM) .depend 45 | 46 | clean:: 47 | $(RM) mutant_*.c 48 | 49 | ####################### 50 | # Local configuration # 51 | ####################### 52 | 53 | MUTATION_VERSION:=$(shell $(SED) -e 's/\\(.*\\)/\\1/' $(PLUGIN_DIR)/VERSION) 54 | 55 | $(PLUGIN_DIR)/local_config.ml: $(PLUGIN_DIR)/Makefile.in $(PLUGIN_DIR)/VERSION 56 | $(PRINT_MAKING) $@ 57 | $(RM) $@ 58 | $(ECHO) "(* This file was automatically generated from $<. Don't edit it. *)" >> $@ 59 | $(ECHO) "let version = \""$(MUTATION_VERSION)"\"" >> $@ 60 | $(CHMOD_RO) $@ 61 | 62 | ########## 63 | # Header # 64 | ########## 65 | 66 | headers:: 67 | @echo "Applying Headers..." 68 | headache -c licence/headache_config.txt -h licence/CEA_PROPRIETARY \ 69 | *.ml *.mli \ 70 | Makefile.in configure.ac 71 | 72 | ########## 73 | # Merlin # 74 | ######### 75 | 76 | .PHONY:merlin 77 | .merlin merlin: $(FRAMAC_SHARE)/Makefile.config 78 | #create Merlin file 79 | $(PRINT_MAKING) $@ 80 | echo "FLG -c $(FLAGS) $(FRAMAC_USER_MERLIN_FLAGS)" > .merlin 81 | for PKG in $(LIBRARY_NAMES); do echo PKG $$PKG >> .merlin; done 82 | for PKG in $(LIBRARY_NAMES_GUI); do echo PKG $$PKG >> .merlin; done 83 | for PKG in $(MERLIN_PACKAGES); do echo PKG $$PKG >> .merlin; done 84 | echo "B $(FRAMAC_LIBDIR)" >> .merlin 85 | echo "B $(FRAMAC_LIBDIR)/plugins" >> .merlin 86 | echo "B $(FRAMAC_LIBDIR)/plugins/gui" >> .merlin 87 | find . \( -name '.*' -o -name tests -o -name doc -o -name '*.cache' \) -prune \ 88 | -o \( -type d -exec printf "B %s\n" {} \; -exec printf "S %s\n" {} \; \) >> .merlin 89 | 90 | ##################################### 91 | # Regenerating the Makefile on need # 92 | ##################################### 93 | 94 | ifeq ("$(FRAMAC_INTERNAL)","yes") 95 | CONFIG_STATUS_DIR:=$(FRAMAC_SRC) 96 | CONFIG_STATUS_DIR_DEP:= 97 | else 98 | CONFIG_STATUS_DIR:=$(Mutation_DIR) 99 | CONFIG_STATUS_DIR_DEP:=$(CONFIG_STATUS_DIR)/config.status 100 | endif 101 | 102 | $(Mutation_DIR)/Makefile: $(Mutation_DIR)/Makefile.in $(CONFIG_STATUS_DIR_DEP) 103 | cd $(CONFIG_STATUS_DIR) && ./config.status --file $@ 104 | -------------------------------------------------------------------------------- /Mutation.mli: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Mutation plugin for Frama-C 3 | 4 | Generation of *mutant* programs. 5 | 6 | Mutant programs (*mutants* for short) are the result of a *mutation* : a 7 | syntactically modification on the source program (on its instructions or its 8 | specification). A given mutant may or may not be semantically equivalent to the 9 | source program. 10 | 11 | Here are the corresponding versions of Frama-C for each version of Mutation: 12 | 13 | | Frama-C | Mutation | 14 | | -------------- | ---------- | 15 | | v17 Chlorine | v0.3.x | 16 | | v16 Sulfur | v0.2.x | 17 | 18 | 19 | ## Building 20 | 21 | autoconf 22 | ./configure 23 | make 24 | make install 25 | 26 | 27 | # Using Mutation 28 | 29 | frama-c FILE -mut [-mut-code] [-mut-spec] [-mut-summary-file SUMMARY] 30 | 31 | where 'FILE' is the file the plugin is applied to, 'SUMMARY' is the file where 32 | the list of the produced mutants will be written. Use the options '-mut-code' 33 | and '-mut-spec' to apply code-only mutations or spec-only mutations. 34 | 35 | Here are some of the mutations applied by the Mutation plugin: 36 | * Replacement of a binary operator 37 | * Condition reversal 38 | * Loop invariant deletion 39 | * Postcondition deletion 40 | * Conjunction pruning 41 | * Replacement of numerical values 42 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 0.3.0 2 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | 2 | m4_define([plugin_file],Makefile.in) 3 | 4 | m4_define([FRAMAC_SHARE_ENV], 5 | [m4_normalize(m4_esyscmd([echo $FRAMAC_SHARE]))]) 6 | 7 | m4_define([FRAMAC_SHARE], 8 | [m4_ifval(FRAMAC_SHARE_ENV,[FRAMAC_SHARE_ENV], 9 | [m4_esyscmd(frama-c -print-path)])]) 10 | 11 | m4_ifndef([FRAMAC_M4_MACROS], [m4_include(FRAMAC_SHARE/configure.ac)]) 12 | 13 | check_plugin(mutation,PLUGIN_RELATIVE_PATH(plugin_file), 14 | [support for Mutation plug-in],yes,yes) 15 | 16 | 17 | # Check Frama-C version 18 | ####################### 19 | 20 | AC_MSG_CHECKING(for Frama-C version) 21 | AC_MSG_RESULT($FRAMAC_VERSION) 22 | 23 | VERSION_NUMBER=`echo $FRAMAC_VERSION | sed -n -e 's/[[a-zA-Z]]\+-\([[0-9]]\+\)-.*/\1/p'` 24 | EXTRA_VERSION_NUMBER=`echo $FRAMAC_VERSION | sed -n -e 's/[[a-zA-Z]]\+-[[0-9]]\+-\(.*\)/\1/p'` 25 | REQUIRED_NUMBER=20180502 26 | REQUIRED_NAME=Chlorine 27 | 28 | case $FRAMAC_VERSION in 29 | # $REQUIRED_NAME-$REQUIRED_NUMBER+dev*) 30 | # # at the time being, must use the Frama-C development version 31 | # ;; 32 | $REQUIRED_NAME-$REQUIRED_NUMBER*) 33 | if test -n "$EXTRA_VERSION_NUMBER"; then 34 | AC_MSG_WARN(no guarantee of compatibility with your Frama-C custom \ 35 | version of $REQUIRED_NAME) 36 | fi;; 37 | *) 38 | if test $VERSION_NUMBER -lt $REQUIRED_NUMBER; then 39 | AC_MSG_ERROR(Frama-C version must be at least \ 40 | $REQUIRED_NAME-$REQUIRED_NUMBER.) 41 | else 42 | AC_MSG_WARN(Frama-C version is more recent than $REQUIRED_NAME: \ 43 | use it at your own risk) 44 | fi;; 45 | esac 46 | 47 | # OCaml version 48 | ############### 49 | 50 | OCAMLVERSION=`ocamlc -v | sed -n -e 's|.*version *\(.*\)$|\1|p' ` 51 | 52 | MAY_RUN_TESTS=yes 53 | 54 | # C compiler and stdio.h 55 | ######################### 56 | 57 | AC_CHECK_HEADERS([stdio.h],[HAVE_STDIO_H=yes],) 58 | 59 | # not sure it can actually happens: 60 | # look like the configure stops on error if no C compiler detected 61 | if test -z $HAVE_STDIO_H; then 62 | MAY_RUN_TESTS=no 63 | AC_MSG_WARN([stdio.h missing: non-regression tests unavailable.]) 64 | fi 65 | 66 | 67 | ####################### 68 | # Generating Makefile # 69 | ####################### 70 | 71 | AC_SUBST(MAY_RUN_TESTS) 72 | AC_SUBST(OCAMLVERSION) 73 | 74 | write_plugin_config(Makefile) 75 | -------------------------------------------------------------------------------- /mut_options.ml: -------------------------------------------------------------------------------- 1 | module Self = Plugin.Register (struct 2 | let name = "Mutation" 3 | 4 | let shortname = "mut" 5 | 6 | let help = "" 7 | end) 8 | 9 | module Enabled = Self.False (struct 10 | let option_name = "-mut" 11 | 12 | let help = "" 13 | end) 14 | 15 | (* Customization *) 16 | 17 | module Mut_Code = Self.True (struct 18 | let option_name = "-mut-code" 19 | 20 | let help = "perform mutations on the C code" 21 | end) 22 | 23 | module Mut_Spec = Self.True (struct 24 | let option_name = "-mut-spec" 25 | 26 | let help = "perform mutations on the ACSL specification" 27 | end) 28 | 29 | module Only = Self.Int (struct 30 | let option_name = "-mut-only" 31 | 32 | let help = "only perform a given mutation (designated by its number)" 33 | 34 | let arg_name = "N" 35 | 36 | let default = -1 37 | end) 38 | 39 | module Summary_File = Self.String (struct 40 | let option_name = "-mut-summary-file" 41 | 42 | let help = "write the summary of generated mutations in a file" 43 | 44 | let arg_name = "F" 45 | 46 | let default = "summary.csv" 47 | end) 48 | 49 | (* Debug Keys *) 50 | 51 | let dkey_progress = Self.register_category "progress" 52 | 53 | let dkey_mutant = Self.register_category "mutant" 54 | -------------------------------------------------------------------------------- /mut_register.ml: -------------------------------------------------------------------------------- 1 | open Cil_types 2 | 3 | type mutation = 4 | (* mutations on code *) 5 | | Mut_BinOp of binop * binop * location 6 | | Mut_If of exp * (exp -> exp) * location 7 | (* mutations on spec *) 8 | | Mut_TBinOp of binop * binop * location 9 | | Mut_Prel of relation * relation * location 10 | | Mut_Pnot of predicate * location 11 | | Mut_LoopInv of predicate 12 | | Mut_Post of identified_predicate 13 | | Mut_Term of term * (term -> term) * location 14 | | Mut_Variant of term * (term -> term) * location 15 | | Mut_And of predicate * bool * location 16 | 17 | let pp_aux fmt f e1 e2 loc = 18 | Format.fprintf fmt "%a: `%a` --> `%a`" Printer.pp_location loc f e1 f e2 19 | 20 | let pp_mutation fmt = function 21 | | Mut_TBinOp (b1, b2, loc) | Mut_BinOp (b1, b2, loc) -> 22 | pp_aux fmt Printer.pp_binop b1 b2 loc 23 | | Mut_If (e1, f, loc) -> pp_aux fmt Printer.pp_exp e1 (f e1) loc 24 | | Mut_Prel (r1, r2, loc) -> pp_aux fmt Printer.pp_relation r1 r2 loc 25 | | Mut_Pnot (p, loc) -> 26 | Format.fprintf fmt "%a: ! (%a)" Printer.pp_location p.pred_loc 27 | Printer.pp_predicate p 28 | | Mut_LoopInv p -> 29 | Format.fprintf fmt "%a: - loop invariant %a" Printer.pp_location 30 | p.pred_loc Printer.pp_predicate p 31 | | Mut_Post p -> 32 | Format.fprintf fmt "%a: - ensures %a" Printer.pp_location 33 | p.ip_content.pred_loc Printer.pp_identified_predicate p 34 | | Mut_Term (t1, f, loc) -> pp_aux fmt Printer.pp_term t1 (f t1) loc 35 | | Mut_Variant (t1, f, loc) -> pp_aux fmt Printer.pp_term t1 (f t1) loc 36 | | Mut_And (p, b, loc) -> 37 | let side = if b then "left" else "right" in 38 | Format.fprintf fmt "%a: %a cut %s" Printer.pp_location loc 39 | Printer.pp_predicate p side 40 | 41 | let pp_mutation fmt m = 42 | let funcs = Format.pp_get_formatter_out_functions fmt () in 43 | let out_newline () = () in 44 | let out_spaces x = if x > 0 then funcs.out_string " " 0 1 else () in 45 | let funcs' = {funcs with out_newline; out_spaces; out_indent= out_spaces} in 46 | Format.pp_set_formatter_out_functions fmt funcs' ; 47 | pp_mutation fmt m ; 48 | Format.pp_set_formatter_out_functions fmt funcs 49 | 50 | let other_binops = function 51 | | PlusA -> [MinusA; Mult] 52 | | MinusA -> [PlusA; Mult] 53 | | Mult -> [PlusA; MinusA] 54 | | Div -> [Mult; PlusA; MinusA; Mod] 55 | | Mod -> [Mult; Div; PlusA; MinusA] 56 | | LAnd -> [LOr] 57 | | LOr -> [LAnd] 58 | | Lt -> [Le; Gt; Ge; Eq; Ne] 59 | | Gt -> [Ge; Lt; Le; Eq; Ne] 60 | | Le -> [Gt; Ge; Eq; Ne; Lt] 61 | | Ge -> [Lt; Le; Eq; Ne; Gt] 62 | | Eq -> [Ne] 63 | | Ne -> [Eq] 64 | | _ -> assert false 65 | 66 | let other_relations = function 67 | | Rlt -> [Rgt; Rle; Rge; Req; Rneq] 68 | | Rgt -> [Rlt; Rle; Rge; Req; Rneq] 69 | | Rle -> [Rlt; Rgt; Rge; Req; Rneq] 70 | | Rge -> [Rlt; Rgt; Rle; Req; Rneq] 71 | | Req -> [Rneq] 72 | | Rneq -> [Req] 73 | 74 | let loc_ok (loc, _) = 75 | Filename.basename loc.Lexing.pos_fname <> "__fc_builtin_for_normalization.i" 76 | 77 | let add_i i t = 78 | Logic_const.term (TBinOp (PlusA, t, Logic_const.tinteger i)) t.term_type 79 | 80 | class gatherer funcname = 81 | object (self) 82 | inherit Visitor.frama_c_inplace 83 | 84 | val mutable mutations = [] 85 | 86 | val mutable in_postcond = false 87 | 88 | val mutable in_invariant = false 89 | 90 | val mutable in_quantif = false 91 | 92 | method get_mutations () = mutations 93 | 94 | method private add m = mutations <- m :: mutations 95 | 96 | method! vbehavior bhv = 97 | let kf = Extlib.the self#current_kf in 98 | let add (_, p) = self#add (Mut_Post p) in 99 | if Kernel_function.get_name kf <> funcname then 100 | match bhv.b_post_cond with 101 | | (_, h) :: _ as l 102 | when Mut_options.Mut_Spec.get () && loc_ok h.ip_content.pred_loc -> 103 | in_postcond <- true ; 104 | List.iter add l ; 105 | Cil.DoChildrenPost 106 | (fun x -> 107 | in_postcond <- false ; 108 | x ) 109 | | _ -> Cil.DoChildren 110 | else 111 | (* for main function: only mutate postcondition predicates *) 112 | let f (_, h) = ignore (self#videntified_predicate h) in 113 | List.iter f bhv.b_post_cond ; 114 | Cil.SkipChildren 115 | 116 | method! vcode_annot ca = 117 | match ca.annot_content with 118 | | AInvariant (_, b, p) 119 | when Mut_options.Mut_Spec.get () && b && loc_ok p.pred_loc -> 120 | in_invariant <- true ; 121 | self#add (Mut_LoopInv p) ; 122 | Cil.DoChildrenPost 123 | (fun x -> 124 | in_invariant <- false ; 125 | x ) 126 | | AVariant (t, _) -> 127 | let neg t = Logic_const.term (TUnOp (Neg, t)) t.term_type in 128 | let add x t = Logic_const.term (TBinOp (PlusA, t, x)) t.term_type in 129 | let sub x t = Logic_const.term (TBinOp (MinusA, t, x)) t.term_type in 130 | let nadd x t = neg (add x t) and nsub x t = neg (sub x t) in 131 | (* v -> v +/- 1, 5, 10 *) 132 | self#add (Mut_Variant (t, add (Logic_const.tinteger 1), t.term_loc)) ; 133 | self#add (Mut_Variant (t, sub (Logic_const.tinteger 1), t.term_loc)) ; 134 | self#add (Mut_Variant (t, add (Logic_const.tinteger 5), t.term_loc)) ; 135 | self#add (Mut_Variant (t, sub (Logic_const.tinteger 5), t.term_loc)) ; 136 | self#add (Mut_Variant (t, add (Logic_const.tinteger 10), t.term_loc)) ; 137 | self#add (Mut_Variant (t, sub (Logic_const.tinteger 10), t.term_loc)) ; 138 | (* v -> -v *) 139 | self#add (Mut_Variant (t, neg, t.term_loc)) ; 140 | (* v -> - v +/- 1, 5, 10 *) 141 | self#add (Mut_Variant (t, nadd (Logic_const.tinteger 1), t.term_loc)) ; 142 | self#add (Mut_Variant (t, nsub (Logic_const.tinteger 1), t.term_loc)) ; 143 | self#add (Mut_Variant (t, nadd (Logic_const.tinteger 5), t.term_loc)) ; 144 | self#add (Mut_Variant (t, nsub (Logic_const.tinteger 5), t.term_loc)) ; 145 | self#add 146 | (Mut_Variant (t, nadd (Logic_const.tinteger 10), t.term_loc)) ; 147 | self#add 148 | (Mut_Variant (t, nsub (Logic_const.tinteger 10), t.term_loc)) ; 149 | Cil.DoChildren 150 | | _ -> Cil.DoChildren 151 | 152 | method! vpredicate p = 153 | match p.pred_content with 154 | | Pexists (_, {pred_content= Pand (_, y)}) 155 | |Pforall (_, {pred_content= Pimplies (_, y)}) -> 156 | in_quantif <- true ; 157 | ignore (self#vpredicate y) ; 158 | in_quantif <- false ; 159 | Cil.SkipChildren 160 | | Prel (r, t1, t2) when Mut_options.Mut_Spec.get () && loc_ok p.pred_loc 161 | -> 162 | let add o = self#add (Mut_Prel (r, o, p.pred_loc)) in 163 | List.iter add (other_relations r) ; 164 | ( if (in_postcond || in_invariant) && not in_quantif then 165 | let l = [1; 2; 3] in 166 | match r with 167 | | Rle | Rlt -> 168 | List.iter 169 | (fun i -> self#add (Mut_Term (t2, add_i i, p.pred_loc))) 170 | l 171 | | Rge | Rgt -> 172 | List.iter 173 | (fun i -> self#add (Mut_Term (t1, add_i i, p.pred_loc))) 174 | l 175 | | _ -> () ) ; 176 | Cil.DoChildren 177 | | Pnot _ when Mut_options.Mut_Spec.get () && loc_ok p.pred_loc -> 178 | self#add (Mut_Pnot (p, p.pred_loc)) ; 179 | Cil.DoChildren 180 | | Pand _ when Mut_options.Mut_Spec.get () && loc_ok p.pred_loc -> 181 | if in_invariant && not in_quantif then ( 182 | self#add (Mut_And (p, true, p.pred_loc)) ; 183 | self#add (Mut_And (p, false, p.pred_loc)) ) ; 184 | Cil.DoChildren 185 | | _ -> Cil.DoChildren 186 | 187 | method! vterm t = 188 | match t.term_node with 189 | | TBinOp 190 | ( ( ( PlusA | MinusA | Mult | Div | Mod | LAnd | LOr | Lt | Gt | Le 191 | | Ge | Eq | Ne ) as op ) 192 | , _ 193 | , _ ) 194 | when Mut_options.Mut_Spec.get () && loc_ok t.term_loc -> 195 | let add o = self#add (Mut_TBinOp (op, o, t.term_loc)) in 196 | List.iter add (other_binops op) ; 197 | Cil.DoChildren 198 | | _ -> Cil.DoChildren 199 | 200 | method! vexpr exp = 201 | match exp.enode with 202 | | BinOp 203 | ( ( ( PlusA | MinusA | Mult | Div | Mod | LAnd | LOr | Lt | Gt | Le 204 | | Ge | Eq | Ne ) as op ) 205 | , _ 206 | , _ 207 | , _ ) 208 | when Mut_options.Mut_Code.get () -> 209 | let add o = self#add (Mut_BinOp (op, o, exp.eloc)) in 210 | List.iter add (other_binops op) ; 211 | Cil.DoChildren 212 | | _ -> Cil.DoChildren 213 | 214 | method! vstmt_aux stmt = 215 | match stmt.skind with 216 | | If (exp, _, _, loc) when Mut_options.Mut_Code.get () -> 217 | let new_e exp = Cil.new_exp loc (UnOp (LNot, exp, Cil.intType)) in 218 | self#add (Mut_If (exp, new_e, loc)) ; 219 | Cil.DoChildren 220 | | _ -> Cil.DoChildren 221 | 222 | method! vglob_aux glob = 223 | match glob with 224 | | GType (_, l) when loc_ok l -> Cil.DoChildren 225 | | GType _ -> Cil.SkipChildren 226 | | GCompTag (_, l) when loc_ok l -> Cil.DoChildren 227 | | GCompTag _ -> Cil.SkipChildren 228 | | GCompTagDecl (_, l) when loc_ok l -> Cil.DoChildren 229 | | GCompTagDecl _ -> Cil.SkipChildren 230 | | GEnumTag (_, l) when loc_ok l -> Cil.DoChildren 231 | | GEnumTag _ -> Cil.SkipChildren 232 | | GEnumTagDecl (_, l) when loc_ok l -> Cil.DoChildren 233 | | GEnumTagDecl _ -> Cil.SkipChildren 234 | | GVarDecl (_, l) when loc_ok l -> Cil.DoChildren 235 | | GVarDecl _ -> Cil.SkipChildren 236 | | GFunDecl (_, _, l) when loc_ok l -> Cil.DoChildren 237 | | GFunDecl _ -> Cil.SkipChildren 238 | | GVar (_, _, l) when loc_ok l -> Cil.DoChildren 239 | | GVar _ -> Cil.SkipChildren 240 | | GFun (f, _) when f.svar.vname = funcname ^ "_precond" -> 241 | Cil.SkipChildren 242 | | GFun (_, l) when loc_ok l -> Cil.DoChildren 243 | | GFun _ -> Cil.SkipChildren 244 | | GAsm _ -> Cil.SkipChildren 245 | | GPragma _ -> Cil.SkipChildren 246 | | GText _ -> Cil.SkipChildren 247 | | GAnnot _ -> Cil.SkipChildren 248 | 249 | method! vassigns _ = Cil.SkipChildren 250 | end 251 | 252 | let same_locs l1 l2 = Cil_datatype.Location.compare l1 l2 = 0 253 | 254 | class mutation_visitor prj mut = 255 | object 256 | inherit Visitor.frama_c_copy prj 257 | 258 | method! vbehavior bhv = 259 | let f bhv = 260 | match mut with 261 | | Mut_Post m -> 262 | { bhv with 263 | b_post_cond= 264 | List.filter (fun (_, p) -> p.ip_id <> m.ip_id) bhv.b_post_cond 265 | } 266 | | _ -> bhv 267 | in 268 | Cil.ChangeDoChildrenPost (bhv, f) 269 | 270 | method! vcode_annot ca = 271 | let f ca = 272 | match (ca.annot_content, mut) with 273 | | AInvariant (_, linv, p), Mut_LoopInv m 274 | when linv && same_locs p.pred_loc m.pred_loc -> 275 | Logic_const.new_code_annotation 276 | (AInvariant ([], true, Logic_const.ptrue)) 277 | | AVariant (t, str), Mut_Variant (_, f, l) when same_locs t.term_loc l 278 | -> 279 | Logic_const.new_code_annotation (AVariant (f t, str)) 280 | | _ -> ca 281 | in 282 | Cil.ChangeDoChildrenPost (ca, f) 283 | 284 | method! vpredicate p = 285 | let f p = 286 | match (p.pred_content, mut) with 287 | | Prel (r, x, y), Mut_Prel (w, z, l) 288 | when same_locs p.pred_loc l && r = w -> 289 | Logic_const.prel (z, x, y) 290 | | Prel (r, x, y), Mut_Term (a, f, l) 291 | when same_locs p.pred_loc l && x.term_loc = a.term_loc -> 292 | Logic_const.prel (r, f x, y) 293 | | Prel (r, x, y), Mut_Term (a, f, l) 294 | when same_locs p.pred_loc l && y.term_loc = a.term_loc -> 295 | Logic_const.prel (r, x, f y) 296 | | Pnot p', Mut_Pnot (_, l) when same_locs p.pred_loc l -> p' 297 | | Pand (p1, p2), Mut_And (_, side, l) when same_locs p.pred_loc l -> 298 | if side then p2 else p1 299 | | _ -> p 300 | in 301 | Cil.ChangeDoChildrenPost (p, f) 302 | 303 | method! vterm term = 304 | let f term = 305 | match (term.term_node, mut) with 306 | | TBinOp (o, x, y), Mut_TBinOp (w, z, l) 307 | when same_locs term.term_loc l && o = w -> 308 | Logic_const.term (TBinOp (z, x, y)) term.term_type 309 | | _ -> term 310 | in 311 | Cil.ChangeDoChildrenPost (term, f) 312 | 313 | method! vexpr exp = 314 | let f exp = 315 | match (exp.enode, mut) with 316 | | BinOp (o1, x, y, t), Mut_BinOp (o2, z, l) 317 | when same_locs exp.eloc l && o1 = o2 -> 318 | Cil.new_exp exp.eloc (BinOp (z, x, y, t)) 319 | | _ -> exp 320 | in 321 | Cil.ChangeDoChildrenPost (exp, f) 322 | 323 | method! vstmt_aux stmt = 324 | let f stmt = 325 | match (stmt.skind, mut) with 326 | | If (e, x, y, loc), Mut_If (_, new_e, l) when same_locs loc l -> 327 | {stmt with skind= If (new_e e, x, y, loc)} 328 | | _ -> stmt 329 | in 330 | Cil.ChangeDoChildrenPost (stmt, f) 331 | end 332 | 333 | let rec mutate filename summary_file fct cpt = function 334 | | [] -> () 335 | | _ when Mut_options.Only.get () <> -1 && Mut_options.Only.get () < cpt -> () 336 | | _ :: t when Mut_options.Only.get () <> -1 && Mut_options.Only.get () > cpt 337 | -> 338 | mutate filename summary_file fct (cpt + 1) t 339 | | h :: t -> 340 | let file = filename ^ "_" ^ string_of_int cpt ^ ".c" in 341 | let dkey = Mut_options.dkey_progress in 342 | Mut_options.Self.feedback ~dkey "mutant %i %a" cpt pp_mutation h ; 343 | let str_mutation = Format.asprintf "%a" pp_mutation h in 344 | Printf.fprintf summary_file "%s,%s\n" file str_mutation ; 345 | let f p = new mutation_visitor p h in 346 | let project = File.create_project_from_visitor "__mut_tmp" f in 347 | Project.copy ~selection:(Parameter_state.get_selection ()) project ; 348 | let print_in_file () = 349 | Globals.set_entry_point fct false ; 350 | Kernel.Unicode.set false ; 351 | let buf = Buffer.create 512 in 352 | let fmt = Format.formatter_of_buffer buf in 353 | File.pretty_ast ~fmt () ; 354 | let out_file = open_out file in 355 | Mut_options.Self.feedback ~dkey:Mut_options.dkey_mutant "mutant %i:" 356 | cpt ; 357 | if Mut_options.Self.is_debug_key_enabled Mut_options.dkey_mutant then 358 | Buffer.output_buffer stdout buf ; 359 | Buffer.output_buffer out_file buf ; 360 | Format.pp_print_flush fmt () ; 361 | flush stdout ; 362 | flush out_file ; 363 | close_out out_file ; 364 | Buffer.clear buf 365 | in 366 | Project.on project print_in_file () ; 367 | Project.remove ~project () ; 368 | mutate filename summary_file fct (cpt + 1) t 369 | 370 | let run () = 371 | if Mut_options.Enabled.get () then ( 372 | let filename = 373 | List.hd (String.split_on_char '.' (List.hd (Kernel.Files.get ()))) 374 | in 375 | let funcname = Kernel_function.get_name (fst (Globals.entry_point ())) in 376 | let g = new gatherer funcname in 377 | Visitor.visitFramacFile (g :> Visitor.frama_c_inplace) (Ast.get ()) ; 378 | let mutations = g#get_mutations () in 379 | let n_mutations = List.length mutations in 380 | let dkey = Mut_options.dkey_progress in 381 | Mut_options.Self.feedback ~dkey "%i mutants" n_mutations ; 382 | let summary_file = open_out (Mut_options.Summary_File.get ()) in 383 | mutate filename summary_file funcname 0 mutations ; 384 | flush summary_file ; 385 | close_out summary_file ) 386 | 387 | let run = 388 | let deps = [Ast.self; Mut_options.Enabled.self] in 389 | let f, _self = State_builder.apply_once "mutation" deps run in 390 | f 391 | 392 | let () = Db.Main.extend run 393 | -------------------------------------------------------------------------------- /tests/search/oracle/search.err.oracle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gpetiot/Frama-C-Mutation/1a7fa546900a647ac284e2bebef6752722096ac6/tests/search/oracle/search.err.oracle -------------------------------------------------------------------------------- /tests/search/oracle/search.res.oracle: -------------------------------------------------------------------------------- 1 | [kernel] Parsing tests/search/search.c (with preprocessing) 2 | [mut:progress] 34 mutants 3 | [mut:progress] mutant 0 tests/search/search.c:21: `≡` --> `≢` 4 | [mut:mutant] mutant 0: 5 | /* Generated by Frama-C */ 6 | /*@ requires \valid(t + (0 .. 4)); */ 7 | void search(int *t, int x) 8 | { 9 | int i; 10 | int found = 0; 11 | i = 0; 12 | /*@ loop invariant 0 <= i <= 5; 13 | loop invariant 14 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 15 | loop assigns found, i; 16 | */ 17 | while (i <= 4) { 18 | if (*(t + i) == x) found = 1; 19 | i ++; 20 | } 21 | /*@ 22 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) != x); 23 | */ 24 | ; 25 | return; 26 | } 27 | 28 | 29 | [mut:progress] mutant 1 tests/search/search.c:21: `!=` --> `==` 30 | [mut:mutant] mutant 1: 31 | /* Generated by Frama-C */ 32 | /*@ requires \valid(t + (0 .. 4)); */ 33 | void search(int *t, int x) 34 | { 35 | int i; 36 | int found = 0; 37 | i = 0; 38 | /*@ loop invariant 0 <= i <= 5; 39 | loop invariant 40 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 41 | loop assigns found, i; 42 | */ 43 | while (i <= 4) { 44 | if (*(t + i) == x) found = 1; 45 | i ++; 46 | } 47 | /*@ 48 | assert found == 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 49 | */ 50 | ; 51 | return; 52 | } 53 | 54 | 55 | [mut:progress] mutant 2 tests/search/search.c:13: `==` --> `!=` 56 | [mut:mutant] mutant 2: 57 | /* Generated by Frama-C */ 58 | /*@ requires \valid(t + (0 .. 4)); */ 59 | void search(int *t, int x) 60 | { 61 | int i; 62 | int found = 0; 63 | i = 0; 64 | /*@ loop invariant 0 <= i <= 5; 65 | loop invariant 66 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) != x); 67 | loop assigns found, i; 68 | */ 69 | while (i <= 4) { 70 | if (*(t + i) == x) found = 1; 71 | i ++; 72 | } 73 | /*@ 74 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 75 | */ 76 | ; 77 | return; 78 | } 79 | 80 | 81 | [mut:progress] mutant 3 tests/search/search.c:13: `!=` --> `==` 82 | [mut:mutant] mutant 3: 83 | /* Generated by Frama-C */ 84 | /*@ requires \valid(t + (0 .. 4)); */ 85 | void search(int *t, int x) 86 | { 87 | int i; 88 | int found = 0; 89 | i = 0; 90 | /*@ loop invariant 0 <= i <= 5; 91 | loop invariant 92 | found == 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 93 | loop assigns found, i; 94 | */ 95 | while (i <= 4) { 96 | if (*(t + i) == x) found = 1; 97 | i ++; 98 | } 99 | /*@ 100 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 101 | */ 102 | ; 103 | return; 104 | } 105 | 106 | 107 | [mut:progress] 108 | mutant 4 tests/search/search.c:13: - loop invariant found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x) 109 | [mut:mutant] mutant 4: 110 | /* Generated by Frama-C */ 111 | /*@ requires \valid(t + (0 .. 4)); */ 112 | void search(int *t, int x) 113 | { 114 | int i; 115 | int found = 0; 116 | i = 0; 117 | /*@ loop invariant 0 <= i <= 5; 118 | loop assigns found, i; 119 | loop invariant \true; 120 | */ 121 | while (i <= 4) { 122 | if (*(t + i) == x) found = 1; 123 | i ++; 124 | } 125 | /*@ 126 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 127 | */ 128 | ; 129 | return; 130 | } 131 | 132 | 133 | [mut:progress] mutant 5 tests/search/search.c:12: `5` --> `5 + 3` 134 | [mut:mutant] mutant 5: 135 | /* Generated by Frama-C */ 136 | /*@ requires \valid(t + (0 .. 4)); */ 137 | void search(int *t, int x) 138 | { 139 | int i; 140 | int found = 0; 141 | i = 0; 142 | /*@ loop invariant 0 <= i <= 5 + 3; 143 | loop invariant 144 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 145 | loop assigns found, i; 146 | */ 147 | while (i <= 4) { 148 | if (*(t + i) == x) found = 1; 149 | i ++; 150 | } 151 | /*@ 152 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 153 | */ 154 | ; 155 | return; 156 | } 157 | 158 | 159 | [mut:progress] mutant 6 tests/search/search.c:12: `5` --> `5 + 2` 160 | [mut:mutant] mutant 6: 161 | /* Generated by Frama-C */ 162 | /*@ requires \valid(t + (0 .. 4)); */ 163 | void search(int *t, int x) 164 | { 165 | int i; 166 | int found = 0; 167 | i = 0; 168 | /*@ loop invariant 0 <= i <= 5 + 2; 169 | loop invariant 170 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 171 | loop assigns found, i; 172 | */ 173 | while (i <= 4) { 174 | if (*(t + i) == x) found = 1; 175 | i ++; 176 | } 177 | /*@ 178 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 179 | */ 180 | ; 181 | return; 182 | } 183 | 184 | 185 | [mut:progress] mutant 7 tests/search/search.c:12: `5` --> `5 + 1` 186 | [mut:mutant] mutant 7: 187 | /* Generated by Frama-C */ 188 | /*@ requires \valid(t + (0 .. 4)); */ 189 | void search(int *t, int x) 190 | { 191 | int i; 192 | int found = 0; 193 | i = 0; 194 | /*@ loop invariant 0 <= i <= 5 + 1; 195 | loop invariant 196 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 197 | loop assigns found, i; 198 | */ 199 | while (i <= 4) { 200 | if (*(t + i) == x) found = 1; 201 | i ++; 202 | } 203 | /*@ 204 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 205 | */ 206 | ; 207 | return; 208 | } 209 | 210 | 211 | [mut:progress] mutant 8 tests/search/search.c:12: `<=` --> `!=` 212 | [mut:mutant] mutant 8: 213 | /* Generated by Frama-C */ 214 | /*@ requires \valid(t + (0 .. 4)); */ 215 | void search(int *t, int x) 216 | { 217 | int i; 218 | int found = 0; 219 | i = 0; 220 | /*@ loop invariant 0 <= i && i != 5; 221 | loop invariant 222 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 223 | loop assigns found, i; 224 | */ 225 | while (i <= 4) { 226 | if (*(t + i) == x) found = 1; 227 | i ++; 228 | } 229 | /*@ 230 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 231 | */ 232 | ; 233 | return; 234 | } 235 | 236 | 237 | [mut:progress] mutant 9 tests/search/search.c:12: `<=` --> `==` 238 | [mut:mutant] mutant 9: 239 | /* Generated by Frama-C */ 240 | /*@ requires \valid(t + (0 .. 4)); */ 241 | void search(int *t, int x) 242 | { 243 | int i; 244 | int found = 0; 245 | i = 0; 246 | /*@ loop invariant 0 <= i == 5; 247 | loop invariant 248 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 249 | loop assigns found, i; 250 | */ 251 | while (i <= 4) { 252 | if (*(t + i) == x) found = 1; 253 | i ++; 254 | } 255 | /*@ 256 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 257 | */ 258 | ; 259 | return; 260 | } 261 | 262 | 263 | [mut:progress] mutant 10 tests/search/search.c:12: `<=` --> `>=` 264 | [mut:mutant] mutant 10: 265 | /* Generated by Frama-C */ 266 | /*@ requires \valid(t + (0 .. 4)); */ 267 | void search(int *t, int x) 268 | { 269 | int i; 270 | int found = 0; 271 | i = 0; 272 | /*@ loop invariant 0 <= i && i >= 5; 273 | loop invariant 274 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 275 | loop assigns found, i; 276 | */ 277 | while (i <= 4) { 278 | if (*(t + i) == x) found = 1; 279 | i ++; 280 | } 281 | /*@ 282 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 283 | */ 284 | ; 285 | return; 286 | } 287 | 288 | 289 | [mut:progress] mutant 11 tests/search/search.c:12: `<=` --> `>` 290 | [mut:mutant] mutant 11: 291 | /* Generated by Frama-C */ 292 | /*@ requires \valid(t + (0 .. 4)); */ 293 | void search(int *t, int x) 294 | { 295 | int i; 296 | int found = 0; 297 | i = 0; 298 | /*@ loop invariant 0 <= i && i > 5; 299 | loop invariant 300 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 301 | loop assigns found, i; 302 | */ 303 | while (i <= 4) { 304 | if (*(t + i) == x) found = 1; 305 | i ++; 306 | } 307 | /*@ 308 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 309 | */ 310 | ; 311 | return; 312 | } 313 | 314 | 315 | [mut:progress] mutant 12 tests/search/search.c:12: `<=` --> `<` 316 | [mut:mutant] mutant 12: 317 | /* Generated by Frama-C */ 318 | /*@ requires \valid(t + (0 .. 4)); */ 319 | void search(int *t, int x) 320 | { 321 | int i; 322 | int found = 0; 323 | i = 0; 324 | /*@ loop invariant 0 <= i < 5; 325 | loop invariant 326 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 327 | loop assigns found, i; 328 | */ 329 | while (i <= 4) { 330 | if (*(t + i) == x) found = 1; 331 | i ++; 332 | } 333 | /*@ 334 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 335 | */ 336 | ; 337 | return; 338 | } 339 | 340 | 341 | [mut:progress] mutant 13 tests/search/search.c:12: `i` --> `i + 3` 342 | [mut:mutant] mutant 13: 343 | /* Generated by Frama-C */ 344 | /*@ requires \valid(t + (0 .. 4)); */ 345 | void search(int *t, int x) 346 | { 347 | int i; 348 | int found = 0; 349 | i = 0; 350 | /*@ loop invariant 0 <= i + 3 && i <= 5; 351 | loop invariant 352 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 353 | loop assigns found, i; 354 | */ 355 | while (i <= 4) { 356 | if (*(t + i) == x) found = 1; 357 | i ++; 358 | } 359 | /*@ 360 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 361 | */ 362 | ; 363 | return; 364 | } 365 | 366 | 367 | [mut:progress] mutant 14 tests/search/search.c:12: `i` --> `i + 2` 368 | [mut:mutant] mutant 14: 369 | /* Generated by Frama-C */ 370 | /*@ requires \valid(t + (0 .. 4)); */ 371 | void search(int *t, int x) 372 | { 373 | int i; 374 | int found = 0; 375 | i = 0; 376 | /*@ loop invariant 0 <= i + 2 && i <= 5; 377 | loop invariant 378 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 379 | loop assigns found, i; 380 | */ 381 | while (i <= 4) { 382 | if (*(t + i) == x) found = 1; 383 | i ++; 384 | } 385 | /*@ 386 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 387 | */ 388 | ; 389 | return; 390 | } 391 | 392 | 393 | [mut:progress] mutant 15 tests/search/search.c:12: `i` --> `i + 1` 394 | [mut:mutant] mutant 15: 395 | /* Generated by Frama-C */ 396 | /*@ requires \valid(t + (0 .. 4)); */ 397 | void search(int *t, int x) 398 | { 399 | int i; 400 | int found = 0; 401 | i = 0; 402 | /*@ loop invariant 0 <= i + 1 && i <= 5; 403 | loop invariant 404 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 405 | loop assigns found, i; 406 | */ 407 | while (i <= 4) { 408 | if (*(t + i) == x) found = 1; 409 | i ++; 410 | } 411 | /*@ 412 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 413 | */ 414 | ; 415 | return; 416 | } 417 | 418 | 419 | [mut:progress] mutant 16 tests/search/search.c:12: `<=` --> `!=` 420 | [mut:mutant] mutant 16: 421 | /* Generated by Frama-C */ 422 | /*@ requires \valid(t + (0 .. 4)); */ 423 | void search(int *t, int x) 424 | { 425 | int i; 426 | int found = 0; 427 | i = 0; 428 | /*@ loop invariant 0 != i && i <= 5; 429 | loop invariant 430 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 431 | loop assigns found, i; 432 | */ 433 | while (i <= 4) { 434 | if (*(t + i) == x) found = 1; 435 | i ++; 436 | } 437 | /*@ 438 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 439 | */ 440 | ; 441 | return; 442 | } 443 | 444 | 445 | [mut:progress] mutant 17 tests/search/search.c:12: `<=` --> `==` 446 | [mut:mutant] mutant 17: 447 | /* Generated by Frama-C */ 448 | /*@ requires \valid(t + (0 .. 4)); */ 449 | void search(int *t, int x) 450 | { 451 | int i; 452 | int found = 0; 453 | i = 0; 454 | /*@ loop invariant 0 == i <= 5; 455 | loop invariant 456 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 457 | loop assigns found, i; 458 | */ 459 | while (i <= 4) { 460 | if (*(t + i) == x) found = 1; 461 | i ++; 462 | } 463 | /*@ 464 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 465 | */ 466 | ; 467 | return; 468 | } 469 | 470 | 471 | [mut:progress] mutant 18 tests/search/search.c:12: `<=` --> `>=` 472 | [mut:mutant] mutant 18: 473 | /* Generated by Frama-C */ 474 | /*@ requires \valid(t + (0 .. 4)); */ 475 | void search(int *t, int x) 476 | { 477 | int i; 478 | int found = 0; 479 | i = 0; 480 | /*@ loop invariant 0 >= i && i <= 5; 481 | loop invariant 482 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 483 | loop assigns found, i; 484 | */ 485 | while (i <= 4) { 486 | if (*(t + i) == x) found = 1; 487 | i ++; 488 | } 489 | /*@ 490 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 491 | */ 492 | ; 493 | return; 494 | } 495 | 496 | 497 | [mut:progress] mutant 19 tests/search/search.c:12: `<=` --> `>` 498 | [mut:mutant] mutant 19: 499 | /* Generated by Frama-C */ 500 | /*@ requires \valid(t + (0 .. 4)); */ 501 | void search(int *t, int x) 502 | { 503 | int i; 504 | int found = 0; 505 | i = 0; 506 | /*@ loop invariant 0 > i && i <= 5; 507 | loop invariant 508 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 509 | loop assigns found, i; 510 | */ 511 | while (i <= 4) { 512 | if (*(t + i) == x) found = 1; 513 | i ++; 514 | } 515 | /*@ 516 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 517 | */ 518 | ; 519 | return; 520 | } 521 | 522 | 523 | [mut:progress] mutant 20 tests/search/search.c:12: `<=` --> `<` 524 | [mut:mutant] mutant 20: 525 | /* Generated by Frama-C */ 526 | /*@ requires \valid(t + (0 .. 4)); */ 527 | void search(int *t, int x) 528 | { 529 | int i; 530 | int found = 0; 531 | i = 0; 532 | /*@ loop invariant 0 < i <= 5; 533 | loop invariant 534 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 535 | loop assigns found, i; 536 | */ 537 | while (i <= 4) { 538 | if (*(t + i) == x) found = 1; 539 | i ++; 540 | } 541 | /*@ 542 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 543 | */ 544 | ; 545 | return; 546 | } 547 | 548 | 549 | [mut:progress] mutant 21 tests/search/search.c:12: 0 <= i <= 5 cut right 550 | [mut:mutant] mutant 21: 551 | /* Generated by Frama-C */ 552 | /*@ requires \valid(t + (0 .. 4)); */ 553 | void search(int *t, int x) 554 | { 555 | int i; 556 | int found = 0; 557 | i = 0; 558 | /*@ loop invariant 0 <= i; 559 | loop invariant 560 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 561 | loop assigns found, i; 562 | */ 563 | while (i <= 4) { 564 | if (*(t + i) == x) found = 1; 565 | i ++; 566 | } 567 | /*@ 568 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 569 | */ 570 | ; 571 | return; 572 | } 573 | 574 | 575 | [mut:progress] mutant 22 tests/search/search.c:12: 0 <= i <= 5 cut left 576 | [mut:mutant] mutant 22: 577 | /* Generated by Frama-C */ 578 | /*@ requires \valid(t + (0 .. 4)); */ 579 | void search(int *t, int x) 580 | { 581 | int i; 582 | int found = 0; 583 | i = 0; 584 | /*@ loop invariant i <= 5; 585 | loop invariant 586 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 587 | loop assigns found, i; 588 | */ 589 | while (i <= 4) { 590 | if (*(t + i) == x) found = 1; 591 | i ++; 592 | } 593 | /*@ 594 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 595 | */ 596 | ; 597 | return; 598 | } 599 | 600 | 601 | [mut:progress] mutant 23 tests/search/search.c:12: - loop invariant 0 <= i <= 5 602 | [mut:mutant] mutant 23: 603 | /* Generated by Frama-C */ 604 | /*@ requires \valid(t + (0 .. 4)); */ 605 | void search(int *t, int x) 606 | { 607 | int i; 608 | int found = 0; 609 | i = 0; 610 | /*@ loop invariant 611 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 612 | loop assigns found, i; 613 | loop invariant \true; 614 | */ 615 | while (i <= 4) { 616 | if (*(t + i) == x) found = 1; 617 | i ++; 618 | } 619 | /*@ 620 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 621 | */ 622 | ; 623 | return; 624 | } 625 | 626 | 627 | [mut:progress] mutant 24 tests/search/search.c:16: `+` --> `*` 628 | [mut:mutant] mutant 24: 629 | /* Generated by Frama-C */ 630 | /*@ requires \valid(t + (0 .. 4)); */ 631 | void search(int *t, int x) 632 | { 633 | int i; 634 | int found = 0; 635 | i = 0; 636 | /*@ loop invariant 0 <= i <= 5; 637 | loop invariant 638 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 639 | loop assigns found, i; 640 | */ 641 | while (i <= 4) { 642 | if (*(t + i) == x) found = 1; 643 | i *= 1; 644 | } 645 | /*@ 646 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 647 | */ 648 | ; 649 | return; 650 | } 651 | 652 | 653 | [mut:progress] mutant 25 tests/search/search.c:16: `+` --> `-` 654 | [mut:mutant] mutant 25: 655 | /* Generated by Frama-C */ 656 | /*@ requires \valid(t + (0 .. 4)); */ 657 | void search(int *t, int x) 658 | { 659 | int i; 660 | int found = 0; 661 | i = 0; 662 | /*@ loop invariant 0 <= i <= 5; 663 | loop invariant 664 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 665 | loop assigns found, i; 666 | */ 667 | while (i <= 4) { 668 | if (*(t + i) == x) found = 1; 669 | i --; 670 | } 671 | /*@ 672 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 673 | */ 674 | ; 675 | return; 676 | } 677 | 678 | 679 | [mut:progress] mutant 26 tests/search/search.c:17: `==` --> `!=` 680 | [mut:mutant] mutant 26: 681 | /* Generated by Frama-C */ 682 | /*@ requires \valid(t + (0 .. 4)); */ 683 | void search(int *t, int x) 684 | { 685 | int i; 686 | int found = 0; 687 | i = 0; 688 | /*@ loop invariant 0 <= i <= 5; 689 | loop invariant 690 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 691 | loop assigns found, i; 692 | */ 693 | while (i <= 4) { 694 | if (*(t + i) != x) found = 1; 695 | i ++; 696 | } 697 | /*@ 698 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 699 | */ 700 | ; 701 | return; 702 | } 703 | 704 | 705 | [mut:progress] 706 | mutant 27 tests/search/search.c:17: `*(t + i) == x` --> `! (*(t + i) == x)` 707 | [mut:mutant] mutant 27: 708 | /* Generated by Frama-C */ 709 | /*@ requires \valid(t + (0 .. 4)); */ 710 | void search(int *t, int x) 711 | { 712 | int i; 713 | int found = 0; 714 | i = 0; 715 | /*@ loop invariant 0 <= i <= 5; 716 | loop invariant 717 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 718 | loop assigns found, i; 719 | */ 720 | while (i <= 4) { 721 | if (! (*(t + i) == x)) found = 1; 722 | i ++; 723 | } 724 | /*@ 725 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 726 | */ 727 | ; 728 | return; 729 | } 730 | 731 | 732 | [mut:progress] mutant 28 tests/search/search.c:16: `<=` --> `<` 733 | [mut:mutant] mutant 28: 734 | /* Generated by Frama-C */ 735 | /*@ requires \valid(t + (0 .. 4)); */ 736 | void search(int *t, int x) 737 | { 738 | int i; 739 | int found = 0; 740 | i = 0; 741 | /*@ loop invariant 0 <= i <= 5; 742 | loop invariant 743 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 744 | loop assigns found, i; 745 | */ 746 | while (i < 4) { 747 | if (*(t + i) == x) found = 1; 748 | i ++; 749 | } 750 | /*@ 751 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 752 | */ 753 | ; 754 | return; 755 | } 756 | 757 | 758 | [mut:progress] mutant 29 tests/search/search.c:16: `<=` --> `!=` 759 | [mut:mutant] mutant 29: 760 | /* Generated by Frama-C */ 761 | /*@ requires \valid(t + (0 .. 4)); */ 762 | void search(int *t, int x) 763 | { 764 | int i; 765 | int found = 0; 766 | i = 0; 767 | /*@ loop invariant 0 <= i <= 5; 768 | loop invariant 769 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 770 | loop assigns found, i; 771 | */ 772 | while (i != 4) { 773 | if (*(t + i) == x) found = 1; 774 | i ++; 775 | } 776 | /*@ 777 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 778 | */ 779 | ; 780 | return; 781 | } 782 | 783 | 784 | [mut:progress] mutant 30 tests/search/search.c:16: `<=` --> `==` 785 | [mut:mutant] mutant 30: 786 | /* Generated by Frama-C */ 787 | /*@ requires \valid(t + (0 .. 4)); */ 788 | void search(int *t, int x) 789 | { 790 | int i; 791 | int found = 0; 792 | i = 0; 793 | /*@ loop invariant 0 <= i <= 5; 794 | loop invariant 795 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 796 | loop assigns found, i; 797 | */ 798 | while (i == 4) { 799 | if (*(t + i) == x) found = 1; 800 | i ++; 801 | } 802 | /*@ 803 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 804 | */ 805 | ; 806 | return; 807 | } 808 | 809 | 810 | [mut:progress] mutant 31 tests/search/search.c:16: `<=` --> `>=` 811 | [mut:mutant] mutant 31: 812 | /* Generated by Frama-C */ 813 | /*@ requires \valid(t + (0 .. 4)); */ 814 | void search(int *t, int x) 815 | { 816 | int i; 817 | int found = 0; 818 | i = 0; 819 | /*@ loop invariant 0 <= i <= 5; 820 | loop invariant 821 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 822 | loop assigns found, i; 823 | */ 824 | while (i >= 4) { 825 | if (*(t + i) == x) found = 1; 826 | i ++; 827 | } 828 | /*@ 829 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 830 | */ 831 | ; 832 | return; 833 | } 834 | 835 | 836 | [mut:progress] mutant 32 tests/search/search.c:16: `<=` --> `>` 837 | [mut:mutant] mutant 32: 838 | /* Generated by Frama-C */ 839 | /*@ requires \valid(t + (0 .. 4)); */ 840 | void search(int *t, int x) 841 | { 842 | int i; 843 | int found = 0; 844 | i = 0; 845 | /*@ loop invariant 0 <= i <= 5; 846 | loop invariant 847 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 848 | loop assigns found, i; 849 | */ 850 | while (i > 4) { 851 | if (*(t + i) == x) found = 1; 852 | i ++; 853 | } 854 | /*@ 855 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 856 | */ 857 | ; 858 | return; 859 | } 860 | 861 | 862 | [mut:progress] mutant 33 tests/search/search.c:16: `i <= 4` --> `! (i <= 4)` 863 | [mut:mutant] mutant 33: 864 | /* Generated by Frama-C */ 865 | /*@ requires \valid(t + (0 .. 4)); */ 866 | void search(int *t, int x) 867 | { 868 | int i; 869 | int found = 0; 870 | i = 0; 871 | /*@ loop invariant 0 <= i <= 5; 872 | loop invariant 873 | found != 0 <==> (\exists integer k; 0 <= k < i && *(t + k) == x); 874 | loop assigns found, i; 875 | */ 876 | while (! (i <= 4)) { 877 | if (*(t + i) == x) found = 1; 878 | i ++; 879 | } 880 | /*@ 881 | assert found != 0 <==> (\exists integer i; 0 <= i <= 4 && *(t + i) == x); 882 | */ 883 | ; 884 | return; 885 | } 886 | 887 | 888 | -------------------------------------------------------------------------------- /tests/search/search.c: -------------------------------------------------------------------------------- 1 | 2 | /* run.config 3 | STDOPT: +"-main search -mut -mut-msg-key mutant,progress" 4 | */ 5 | 6 | /*@ requires \valid(t+(0..4)); 7 | @*/ 8 | void search(int*t, int x) { 9 | int i; 10 | int found = 0; 11 | 12 | /*@ loop invariant 0 <= i <= 5; 13 | @ loop invariant found <==> (\exists integer k; 0 <= k < i && t[k] == x); 14 | @ loop assigns found, i; 15 | @*/ 16 | for(i = 0; i <= 4; i++) { 17 | if(t[i] == x) 18 | found = 1; 19 | } 20 | 21 | //@ assert found <==> \exists integer i; 0 <= i <= 4 && t[i] == x; 22 | } 23 | -------------------------------------------------------------------------------- /tests/test_config.in: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gpetiot/Frama-C-Mutation/1a7fa546900a647ac284e2bebef6752722096ac6/tests/test_config.in --------------------------------------------------------------------------------