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
[email protected]
https://lists.sourceforge.net/lists/listinfo/cil-users