<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="Generator" content="Microsoft Word 14 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
{font-family:Tahoma;
panose-1:2 11 6 4 3 5 4 4 2 4;}
@font-face
{font-family:Consolas;
panose-1:2 11 6 9 2 2 4 3 2 4;}
@font-face
{font-family:"Lucida Console";
panose-1:2 11 6 9 4 5 4 2 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0in;
margin-bottom:.0001pt;
font-size:11.0pt;
font-family:"Calibri","sans-serif";
color:black;}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:blue;
text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
{mso-style-priority:99;
color:purple;
text-decoration:underline;}
pre
{mso-style-priority:99;
mso-style-link:"HTML Preformatted Char";
margin:0in;
margin-bottom:.0001pt;
font-size:10.0pt;
font-family:"Courier New";
color:black;}
p.MsoAcetate, li.MsoAcetate, div.MsoAcetate
{mso-style-priority:99;
mso-style-link:"Balloon Text Char";
margin:0in;
margin-bottom:.0001pt;
font-size:8.0pt;
font-family:"Tahoma","sans-serif";
color:black;}
span.HTMLPreformattedChar
{mso-style-name:"HTML Preformatted Char";
mso-style-priority:99;
mso-style-link:"HTML Preformatted";
font-family:Consolas;
color:black;}
span.EmailStyle19
{mso-style-type:personal;
font-family:"Calibri","sans-serif";
color:windowtext;}
span.EmailStyle20
{mso-style-type:personal;
font-family:"Calibri","sans-serif";
color:#1F497D;}
span.EmailStyle21
{mso-style-type:personal-reply;
font-family:"Calibri","sans-serif";
color:#1F497D;}
span.BalloonTextChar
{mso-style-name:"Balloon Text Char";
mso-style-priority:99;
mso-style-link:"Balloon Text";
font-family:"Tahoma","sans-serif";
color:black;}
.MsoChpDefault
{mso-style-type:export-only;
font-size:10.0pt;}
@page WordSection1
{size:8.5in 11.0in;
margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
{page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body bgcolor="white" lang="EN-US" link="blue" vlink="purple">
<div class="WordSection1">
<p class="MsoNormal"><span style="color:#1F497D">To follow up on my own question, in case others have it later… Here’s what I did, that seems to be working:<o:p></o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:10.0pt;font-family:"Lucida Console";color:windowtext"> SVal BuffBase, BuffSize;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:10.0pt;font-family:"Lucida Console";color:windowtext"> MemRegionManager &MRMgr = St->getStateManager().getRegionManager();<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:10.0pt;font-family:"Lucida Console";color:windowtext"> const TypedValueRegion *BuffReg = Buff.castAs<nonloc::LazyCompoundVal>().getCVData()->getRegion();<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:10.0pt;font-family:"Lucida Console";color:windowtext"> const RecordType *BuffRTy = BuffReg->getValueType()->getAsStructureType();<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:10.0pt;font-family:"Lucida Console";color:windowtext"> assert(BuffRTy && "Input buffer value is not a structure");<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:10.0pt;font-family:"Lucida Console";color:windowtext"> const RecordDecl *BuffRD = BuffRTy->getDecl()->getDefinition();<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:10.0pt;font-family:"Lucida Console";color:windowtext"> assert(BuffRD && "Input buffer structure has no definition");<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:10.0pt;font-family:"Lucida Console";color:windowtext"> for (const auto *F : BuffRD->fields()) {<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:10.0pt;font-family:"Lucida Console";color:windowtext"> if (F->getName() == "base") {<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:10.0pt;font-family:"Lucida Console";color:windowtext"> BuffBase = St->getSVal(MRMgr.getFieldRegion(F, BuffReg));<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:10.0pt;font-family:"Lucida Console";color:windowtext"> }<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:10.0pt;font-family:"Lucida Console";color:windowtext"> else if (F->getName() == "size") {<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:10.0pt;font-family:"Lucida Console";color:windowtext"> BuffSize = St->getSVal(MRMgr.getFieldRegion(F, BuffReg));<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:10.0pt;font-family:"Lucida Console";color:windowtext"> }<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:10.0pt;font-family:"Lucida Console";color:windowtext"> }<o:p></o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D">The above code sets BuffBase and BuffSize to be SVals for the field values in the structure SVal Buff. To assign values to the fields (instead of reading their current values), I used code like the following:<o:p></o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:10.0pt;font-family:"Lucida Console";color:windowtext"> const VarRegion *BuffReg = Buff.getAsRegion()->getAs<VarRegion>();<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:10.0pt;font-family:"Lucida Console";color:windowtext"> const RecordType *BuffRTy = BuffReg->getValueType()->getAsStructureType();<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:10.0pt;font-family:"Lucida Console";color:windowtext"> assert(BuffRTy && "Output buffer value is not a structure");<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:10.0pt;font-family:"Lucida Console";color:windowtext"> const RecordDecl *BuffRD = BuffRTy->getDecl()->getDefinition();<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:10.0pt;font-family:"Lucida Console";color:windowtext"> assert(BuffRD && "Output buffer structure has no definition");<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:10.0pt;font-family:"Lucida Console";color:windowtext"> for (const auto *F : BuffRD->fields()) {<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:10.0pt;font-family:"Lucida Console";color:windowtext"> if (F->getName() == "size") {<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:10.0pt;font-family:"Lucida Console";color:windowtext"> const FieldRegion *SizeFR = St->getStateManager().getRegionManager().getFieldRegion(F, BuffReg);<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:10.0pt;font-family:"Lucida Console";color:windowtext"> St = St->bindLoc(loc::MemRegionVal(SizeFR), Size);<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:10.0pt;font-family:"Lucida Console";color:windowtext"> }<o:p></o:p></span></p>
<p class="MsoNormal" style="text-autospace:none"><span style="font-size:10.0pt;font-family:"Lucida Console";color:windowtext"> }<o:p></o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D">This changes the size field to have the value Size.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D"><o:p> </o:p></span></p>
<div>
<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal"><b><span style="font-size:10.0pt;font-family:"Tahoma","sans-serif";color:windowtext">From:</span></b><span style="font-size:10.0pt;font-family:"Tahoma","sans-serif";color:windowtext"> McDowell, Raymond C.
<br>
<b>Sent:</b> Friday, May 13, 2016 1:14 PM<br>
<b>To:</b> 'Alexey Sidorin'; cfe-dev@lists.llvm.org<br>
<b>Subject:</b> RE: [cfe-dev] Static Checker: getting svals for a struct field value<o:p></o:p></span></p>
</div>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><span style="color:#1F497D">Thanks, Alexey, for your help.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D">Here’s a more detailed explanation of what I’m trying to do. In our project we’ve created a struct type containing a pointer to a buffer and the size of the buffer (in bytes), so that we can pass these around
together and not lose track of the buffer size. I’m trying to write a checker that will make sure that any buffer access is in bounds by checking that 0 <= offset and offset + chunk_size < buffer_size, where chunk_size is the size of the data being read from
/ written to the buffer.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D">Your suggestions have helped a lot, but I’m still stuck getting from the Buffer (struct) SVal to its RecordType. You said to use SVal::getAsRegion() method to get the MemRegion. The next step would seem to
be using the getValueType() and getAsStructureType() methods, but first I need to convert the MemRegion to a VarRegion or a TypedValueRegion. I tried each of these (using MemRegion::getAs), but both resulted in the checker crashing.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="color:#1F497D"><o:p> </o:p></span></p>
<div>
<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal"><b><span style="font-size:10.0pt;font-family:"Tahoma","sans-serif";color:windowtext">From:</span></b><span style="font-size:10.0pt;font-family:"Tahoma","sans-serif";color:windowtext"> Alexey Sidorin [<a href="mailto:alexey.v.sidorin@ya.ru">mailto:alexey.v.sidorin@ya.ru</a>]
<br>
<b>Sent:</b> Monday, May 09, 2016 5:16 PM<br>
<b>To:</b> McDowell, Raymond C.; <a href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a><br>
<b>Subject:</b> Re: [cfe-dev] Static Checker: getting svals for a struct field value<o:p></o:p></span></p>
</div>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<p class="MsoNormal" style="margin-bottom:12.0pt">Hello Raymond,<br>
<br>
1. You can get the Store with ProgramState::getStore() method().<br>
2. To process an SVal representing a region, you may use SVal::getAsRegion() method. But I'm not sure what you really need here, could you explain more detailedly?<br>
3. Your approach for FieldRegion will work, but it is better to search for a FieldDecl in your RecordDecl first and only then get its FieldRegion. FieldDecl has getName() method allowing doing this, so your code will look like:<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;margin-left:.5in">
for (const auto *F : structRD->fields()) {<br>
if (F->getName == "fieldName") {<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;margin-left:.5in">
FieldRegion *FR = MRMgr.getFieldRegion(F, structReg);<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;margin-left:.5in">
size = State->getSVal(FR);<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto;margin-left:.5in">
}<br>
}<o:p></o:p></p>
<p class="MsoNormal"><br>
where State is of ProgramStateRef type.<br>
<br>
<br>
09.05.2016 21:55, McDowell, Raymond C. via cfe-dev пишет:<o:p></o:p></p>
</div>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<p class="MsoNormal">I am new to building Clang static checkers and need some help. I am implementing a PreCall callback function that checks calls to a certain family of functions (from a local library) that takes a struct as an argument. I see how to get
the SVal and Expr for the argument using CallEvent::getArgSVal() and CallEvent::getArgExpr(). What I’m struggling with is how to go from the SVal for the struct to an SVal for one of its fields. In particular, how do I get the memory region associated with
the struct value? Once I have that, I think I know how to go from there, e.g.:<o:p></o:p></p>
<p class="MsoNormal"> <o:p></o:p></p>
<p class="MsoNormal" style="margin-left:.5in">RecordType *structTy = structReg->getValueType()->getAsStructureType();<o:p></o:p></p>
<p class="MsoNormal" style="margin-left:.5in">assert(structTy && “Value is not a structure”);<o:p></o:p></p>
<p class="MsoNormal" style="margin-left:.5in">RecordDecl *structRD = structTy ->getDecl()->getDefinition();<o:p></o:p></p>
<p class="MsoNormal" style="margin-left:.5in">assert(structRD && “structure has no definition”);<o:p></o:p></p>
<p class="MsoNormal" style="margin-left:.5in">for (const auto *F : structRD->fields()) {<o:p></o:p></p>
<p class="MsoNormal" style="margin-left:.5in"> FieldRegion *FR = MRMgr.getFieldRegion(F, structReg);<o:p></o:p></p>
<p class="MsoNormal" style="margin-left:.5in"> if (FR->getDec()->getName() == “fieldName”)<o:p></o:p></p>
<p class="MsoNormal" style="margin-left:.5in"> size = StoreMgr.getBinding(store, loc::MemRegionVal(FR));<o:p></o:p></p>
<p class="MsoNormal" style="margin-left:.5in">}<o:p></o:p></p>
<p class="MsoNormal"> <o:p></o:p></p>
<p class="MsoNormal">But how do I get the memory region structReg? And how do I get the Store store?<o:p></o:p></p>
<p class="MsoNormal"> <o:p></o:p></p>
<p class="MsoNormal">Thanks!<o:p></o:p></p>
<p class="MsoNormal" style="margin-bottom:12.0pt"><span style="font-size:12.0pt;font-family:"Times New Roman","serif""><br>
<br>
<o:p></o:p></span></p>
<pre>_______________________________________________<o:p></o:p></pre>
<pre>cfe-dev mailing list<o:p></o:p></pre>
<pre><a href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a><o:p></o:p></pre>
<pre><a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><o:p></o:p></pre>
</blockquote>
<p class="MsoNormal"><span style="font-size:12.0pt;font-family:"Times New Roman","serif""><o:p> </o:p></span></p>
</div>
</body>
</html>