<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body text="#000000" bgcolor="#FFFFFF">
You shouldn't do the "StoreMgr.getBinding(St,
loc::MemRegionVal(Arg0Reg)) --> Undefined" part; it's not what i
suggested and it doesn't work because Arg0Reg is already "dead" and
its value has been garbage-collected (i assume that by Arg0Reg you
mean the VarRegion for pos2).<br>
<br>
Like, if pos2 is never used later in the program, then we don't need
to remember its value. So if move_to_pos(pos2) is the last use of
pos2, we'll drop the binding and the Store would be empty.<br>
<br>
Accessing dead regions will produce unexpected results; the code for
getSVal()/getBinding() assumes that the region is live (or that the
expression is active when you try to retrieve a value of an
expression).<br>
<br>
In this case it's like "hmm, the user is reading from a local
variable, but it has no bindings, which means it has never been
written to (otherwise i would have remembered it), which means that
it's undefined behavior and contents of the variable are undefined".
The real reason why Store doesn't remember any bindings is because
it has correctly forgot about them.<br>
<br>
This is why we include the (lazy) copy of the old Store with the
LazyCompoundValue. In order to extract data from
lazyCompoundVal{0x4182e58,pos2}, you need to load the variable from
the Store 0x4182e58, *not* from the current Store. The region is
still live in that old store, but in the current store it's no
longer there.<br>
<br>
<br>
This is why in order to obtain <br>
<br>
<div class="moz-cite-prefix">On 6/26/19 3:22 PM, Torry Chen wrote:<br>
</div>
<blockquote type="cite"
cite="mid:CADmWND_yThU38XqkBxDD8=ruWs+QvMVQ4EgQoLEJgDEV7Ek8rA@mail.gmail.com">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<div dir="ltr">I tried State->dump() and it shows there is no
default binding for a struct variable that copies another. See
below. I certainly can (and should) use the field symbols for my
work. I was curious about the internals of the analyzer engine.
Thank you for the detailed explanation!<br>
<br>
struct XY pos1 = next_pos(10, 20); // Binding: pos1 ->
conj_$3{struct XY, LC1, S45538, #1}<br>
move_to_pos(pos1);<br>
// evalCall, State->dump():<br>
//<br>
// Store (direct and default bindings), 0x4176b88 :<br>
// (GlobalInternalSpaceRegion,0,default) : conj_$1{int, LC1,
S45538, #1}<br>
// (GlobalSystemSpaceRegion,0,default) : conj_$2{int, LC1,
S45538, #1}<br>
// (pos1,0,default) : conj_$3{struct XY, LC1, S45538, #1}<br>
//<br>
// Expressions by stack frame:<br>
// #0 Calling main
<br>
// (LC1, S45573) move_to_pos : &code{move_to_pos}<br>
// (LC1, S45581) pos1 : lazyCompoundVal{0x4176b88,pos1}<br>
//<br>
// Ranges are empty.<br>
//<br>
// StoreMgr.getBinding(St, loc::MemRegionVal(Arg0Reg)) --> <b>conj_$3{struct
XY, LC1, S45538, #1}</b><br>
<br>
struct XY pos2 = pos1; // Binding: pos2 ->
lazyCompoundVal{0x4176b88,pos1}<br>
move_to_pos(pos2);<br>
// evalCall, State->dump():<br>
//<br>
// Store (direct and default bindings), 0x4176b88 :<br>
// (GlobalInternalSpaceRegion,0,default) : conj_$1{int, LC1,
S45538, #1}<br>
// (GlobalSystemSpaceRegion,0,default) : conj_$2{int, LC1,
S45538, #1}<br>
// (pos1,0,default) : conj_$3{struct XY, LC1, S45538, #1}<br>
//<br>
// Expressions by stack frame:<br>
// #0 Calling main<br>
// (LC1, S45618) move_to_pos : &code{move_to_pos}<br>
// (LC1, S45626) pos2 : lazyCompoundVal{0x4182e58,pos2}<br>
//<br>
// Ranges are empty.<br>
//<br>
// StoreMgr.getBinding(St, loc::MemRegionVal(Arg0Reg)) --> <b>Undefined</b><br>
</div>
<br>
<div class="gmail_quote">
<div dir="ltr" class="gmail_attr">On Wed, 26 Jun 2019 at 12:15,
Artem Dergachev <<a href="mailto:noqnoqneo@gmail.com"
moz-do-not-send="true">noqnoqneo@gmail.com</a>> wrote:<br>
</div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px
0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div bgcolor="#FFFFFF"> Hmm, weird.<br>
<br>
I suspect that assignment was handled with "small struct
optimization", i.e. field-by-field rather than lazily (cf.
RegionStoreManager::tryBindSmallStruct).<br>
<br>
Could you do a State->dump() to verify that? If it shows
that there's no default binding but instead there are two
derived symbols bound to two different offsets, then the
information about the "whole struct symbol" is already more
or less lost: the static analyzer no longer remembers that
this whole structure is the same as pos1, but it does
remember that its fields, separately, are exactly the same
as they were in pos1, which is what you see by looking at
the fields separately.<br>
<br>
Generally we don't have many checkers that track structures
as a whole and we don't really know how *should* the checker
API look like in order to make such checkers easy to
implement. The only such checker that we have is
IteratorChecker and it kinda tries to do something but it's
not very convenient. For C++ objects i'm thinking of
tracking a "whole structure symbol" artificially, so that it
didn't have anything to do with the actual contents of the
structure but more with its semantic meaning: it would be
preserved by const operations (even if they mutate memory
contents of mutable fields) or through copies/moves and
additionally you would be able to attach state traits to it
without thinking about manually modeling copies/moves.<br>
<br>
I guess in your case, which seems to be more like a C world,
the ad-hoc solution would be to do something like<br>
<br>
let's see...<br>
pos2.x comes from pos1...<br>
pos2.y also comes from pos1...<br>
aha, got it!<br>
the whole pos2 comes from pos1!<br>
<br>
You will *anyway* have to do this because the programmer is
free to copy the structure field-by-field manually instead
of just assigning the structure. This would also happen in
C++ if the structure has a non-trivial constructor. For the
same reason it's not enough to check only 'x' but skip 'y':
the programmer can easily overwrite one field but not the
other field.<br>
<br>
Finally, i'm surprised that it returns a UndefinedVal (i.e.,
in particular, it allows you to unwrap the Optional) instead
of None. This sounds like a bug. But it might be because the
structure does indeed have an undefined default binding
(eg., this happens when it's allocated by malloc() or
operator new). It'd make sense because assigning every field
wouldn't overwrite the default binding. Which, in turn,
should remind you that relying on the "structure symbol" in
order to figure out what the contents of the structure are
is not a good idea unless your structure is immutable and
completely opaque or you somehow know that it's freshly
created. But direct bindings to fields are actually always
trustworthy. That's how our memory model works.<br>
<br>
<br>
<div class="gmail-m_-910006867637439416moz-cite-prefix">On
6/25/19 9:10 PM, Torry Chen wrote:<br>
</div>
<blockquote type="cite">
<div dir="ltr">Thank you Artem! It seems
StoreManager::getDefaultBinding() won't work if the
struct variable is copied. As shown below,
getDefaultBinding() returns an undefined SVal.<br>
<br>
I could go down into fields to get the derived symbols
for X and Y respectively, and then use getParentSymbol()
to get the symbol for the whole struct. This looks
cumbersome though. Is there a more convenient way to get
the symbol for the whole struct in this case?<br>
<br>
<font face="courier new, monospace">// checkBind: pos1
-> conj_$3{struct XY, LC1, S45418, #1}<br>
struct XY pos1 = next_pos(10, 20);<br>
<br>
// checkBind: pos2 ->
lazyCompoundVal{0x5d4bb38,pos1}<br>
struct XY pos2 = pos1;<br>
<br>
move_to_pos(pos2);</font><br>
<br>
<font face="courier new, monospace">/** evalCall for
move_to_pos():<br>
SVal Pos = C.getSVal(CE->getArg(0));<br>
ProgramStateRef State = C.getState();<br>
StoreManager &StoreMgr =
State->getStateManager().getStoreManager();<br>
auto LCV =
Pos.getAs<nonloc::LazyCompoundVal>();<br>
SVal LCSVal = *StoreMgr.getDefaultBinding(*LCV);<br>
LCSVal.dump() // <- Undefined<br>
...<br>
const Store St = LCV->getCVData()->getStore();<br>
const SVal FieldSVal = StoreMgr.getBinding(St,
loc::MemRegionVal(FieldReg));<br>
FieldSVal.dump(); // <- derived_$4{conj_$3{struct
XY, LC1, S45418, #1},pos1->X}<br>
<br>
const auto *SD =
dyn_cast<SymbolDerived>(FieldSVal.getAsSymbol());<br>
const auto ParentSym = SD->getParentSymbol();<br>
ParentSym.dump(); // <- conj_$3{struct XY, LC1,
S45418, #1}<br>
**/</font><br>
</div>
<br>
<div class="gmail_quote">
<div dir="ltr" class="gmail_attr">On Tue, 25 Jun 2019 at
14:06, Artem Dergachev <<a
href="mailto:noqnoqneo@gmail.com" target="_blank"
moz-do-not-send="true">noqnoqneo@gmail.com</a>>
wrote:<br>
</div>
<blockquote class="gmail_quote" style="margin:0px 0px
0px 0.8ex;border-left:1px solid
rgb(204,204,204);padding-left:1ex">
<div bgcolor="#FFFFFF"> The "0x4aa1c58" part of
"lazyCompoundVal{0x4aa1c58,pos1}" is a Store object.
You can access it with getStore() and then read it
with the help of a StoreManager.<br>
<br>
Hmm, we seem to already have a convenient API for
that, you can do
StoreManager::getDefaultBinding(nonloc::LazyCompoundVal)
directly if all you need is a default-bound conjured
symbol. But if you want to lookup, say, specific
fields in the structure (X and Y separately), you'll
need to do getBinding() on manually constructed
FieldRegions (in your case it doesn't look very
useful because the whole structure is conjured
anyway).<br>
<br>
I guess at this point you might like the chapter 5
of my old workbook (<a
class="gmail-m_-910006867637439416gmail-m_-4861931114608865060moz-txt-link-freetext"
href="https://github.com/haoNoQ/clang-analyzer-guide/releases/download/v0.1/clang-analyzer-guide-v0.1.pdf"
target="_blank" moz-do-not-send="true">https://github.com/haoNoQ/clang-analyzer-guide/releases/download/v0.1/clang-analyzer-guide-v0.1.pdf</a>),
as for now it seems to be the only place where
different kinds of values are explained.<br>
<br>
<br>
<div
class="gmail-m_-910006867637439416gmail-m_-4861931114608865060moz-cite-prefix">On
6/25/19 2:35 AM, Torry Chen via cfe-dev wrote:<br>
</div>
<blockquote type="cite">
<div dir="ltr">My project has a struct type as
follows and I'm writing a checker for some
functions that take the struct value as an
argument. In the checkPreCall function I see the
argument is an LazyCompoundVal, not a symbol as
it would be for a primitive type. I tried a few
ways to extract the symbol from the
LazyCompountVal with no luck. Hope to get some
help here.<br>
<br>
<font face="courier new, monospace">struct XY {<br>
uint64_t X;<br>
uint64_t Y;<br>
};<br>
<br>
...<br>
// checkBind: pos1 -> conj_$3{struct XY,
LC1, S63346, #1}</font>
<div><span>struct XY pos1 = next_pos(...);</span> <font
face="courier new, monospace"><br>
<br>
// checkPreCall: Arg0:
lazyCompoundVal{0x4aa1c58,pos1}<br>
move_to_pos(pos1);</font><br>
</div>
</div>
<br>
<fieldset
class="gmail-m_-910006867637439416gmail-m_-4861931114608865060mimeAttachmentHeader"></fieldset>
<pre class="gmail-m_-910006867637439416gmail-m_-4861931114608865060moz-quote-pre">_______________________________________________
cfe-dev mailing list
<a class="gmail-m_-910006867637439416gmail-m_-4861931114608865060moz-txt-link-abbreviated" href="mailto:cfe-dev@lists.llvm.org" target="_blank" moz-do-not-send="true">cfe-dev@lists.llvm.org</a>
<a class="gmail-m_-910006867637439416gmail-m_-4861931114608865060moz-txt-link-freetext" href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" target="_blank" moz-do-not-send="true">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a>
</pre>
</blockquote>
<br>
</div>
</blockquote>
</div>
</blockquote>
<br>
</div>
</blockquote>
</div>
</blockquote>
<br>
</body>
</html>