Hi, On Sat, Dec 19, 2009 at 12:48:39PM -0700, ThanhVu (Vu) Nguyen wrote: > I follow your suggestion and use ChangeDoChildrenPost and also not > mutate things directly. I also use method vstmt instead of method > vinstr. Below is my new version for changing > sprintf(buff,"a string") > to > snprintf(buff,sizeof(buff","a string"). > Please let me know if there's any possible side-effects in there.
Almost perfect (at first sight). See below. > Another question is that the code I have change the statement of the form > sprintf(buff,"a string") to snprintf(...) , so if I want to change a > different statement of the form something=sprintf(buff,"a string") to > something=snprintf, or foo(sprintf()) to foo(snprintf) ... , then I would > need to rewrite another pattern matching , e.g., match ins with Set instead of > Call ? Is there a more general way to not having to do a pattern matching > for > every case ? Just copy the first paramter of Call (e.g. rv): > |Call(rv,Lval(Var {vname="sprintf"},_),expl,loc)-> > let to_buf = L.hd expl in > Call(rv,snprintf,to_buf::(SizeOfE(to_buf)::L.tl expl),loc) There is no need to worry about more complex expressions (Set in particular): CIL normalizes everything so that function calls can only appear in Call statements. Your foo example would be transformed by CIL to "tmp = snprintf(...); foo(tmp);". > let snprintf_va = makeVarinfo true "snprintf" (TVoid []) > let snprintf = Lval((Var snprintf_va),NoOffset) > > class snprintfV ?(tracelist=[]) file = object > inherit nopCilVisitor > method vstmt s = ChangeDoChildrenPost( > s, > fun s -> if L.mem (s.sid) tracelist then ( > match s.skind with > |Instr il -> let new_il = L.map ( > fun ins -> match ins with > |Call(None,Lval(Var {vname="sprintf"},_),expl,loc)-> > let to_buf = L.hd expl in > Call(None,snprintf,to_buf::(SizeOfE(to_buf)::L.tl expl),loc) I'm not sure the SizeOfE will give a reliable result (imagine buf is a pointer on a malloc()ed area, rather than an static array - this is undecidable in the general case). But if your tracelist contains only statements on which this transformation is sound, this should be good. > | _ -> ins > ) il in > debug "old stmt:\n%s\nnew stmt:\n%s\n" (get_stmt s) (get_stmt > (mkStmt > (Instr new_il))); > {s with skind = Instr new_il} Here, I would rater do: s.skind <- Instr new_il; s This way, you do NOT copy s (but mutate it). And this what you want, because Goto statements might refere to s, and if you copy it they will continue refering to the old s. > | _ -> s > )else s > ) > end Hint: always run the CIL checks after your transformations, this will let you know if you broke some invariants in the code. Regards, -- Gabriel Kerneis ------------------------------------------------------------------------------ This SF.Net email is sponsored by the Verizon Developer Community Take advantage of Verizon's best-in-class app development support A streamlined, 14 day to market process makes app distribution fast and easy Join now and get one step closer to millions of Verizon customers http://p.sf.net/sfu/verizon-dev2dev _______________________________________________ CIL-users mailing list CIL-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/cil-users