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

Reply via email to