[cfe-dev] [StaticAnalyzer] Questions about SymbolDerived class and checkDeadSymbol callback

Haowei Wu via cfe-dev cfe-dev at lists.llvm.org
Tue May 30 18:07:27 PDT 2017


Hi

I am developing a resource leak checker that is very similar to
SimpleStreamChecker and I noticed an issue when tracking symbols that is
SymbolDerived type.

The source code of my checker can be downloaded at this link:
https://gist.github.com/zeroomega/2fcabf5979a0e42db1ccb8f30472d071

An example of resource leaks that my checker is trying to find is like this:

typedef uint32_t handle_t;
typedef uint32_t status_t;

status_t request(
  uint32_t flags,
  handle_t* out0,
  handle_t* out1);

status_t release(handle_t handle);

void checkLeak1(int tag) {
  handle_t sa, sb;
  request(0, &sa, &sb);
  if (tag > 0) {
    return;
  }
  release(sa);
  release(sb);
}


Function call "request(0, &sa, &sb)" will allocate 2 resource descriptors
(handles) to "sa" and "sb". The resource will be leaked if someone forgot
to call "release(sa)" on a resource descriptor (handle).

In my checker, I override "checkPostCall" callback to map the SymbolRef of
arguments "sa" and "sb" in any "request(0, &sa, &sb)" call to "Allocated"
state. And I use "checkPreCall" callback to map the SymbolRef of argument
"sa" in any "release(sa)" call to "Released" state. If a tracked SymbolRef
is dead when using "SymbolReaper.isDead()" API in "checkDeadSymbol"
callback and its state is "Allocated", this SymbolRef will be considered as
leaked and will be reported.

In the example code "checkLeak1" , there is an early return "if (tag > 0) {
return;}" that will not release any handles, which will cause leaks. My
checker can successfully detect this leak. However, when I change the leak
example to this:

void checkLeak2(int tag) {
  handle_t ha[2];
  request(0, ha, ha+1);
  if (tag > 0) {
    return;
  }
  release(ha[0]);
  release(ha[1]);
}


The checker will not report any leaks at all. Further debugging shows that
the static analyzer allocates a SymbolConjured symbol for array "ha" and
SymbolDerived symbols for item "ha[0]' and "ha[1]". These two SymbolDerived
symbols has parent symbol points to SymbolConjured symbol of "ha". In the
path of "if (tag > 0) { return;}", the SymbolDerived symbols of "ha[0]" and
"ha[1]" are not considered dead when using "SymbolReaper.isDead()". So no
leak is reported in this path. These two SymbolDerived symbols are
considered dead by "SymbolReaper.isDead()" at the end of path
"release(ha[0]);release(ha[1]);".


Another two examples can show this behavior more clearly:

void checkLeak3(int tag) {
  handle_t ha[2];
  request(0, ha, ha+1);
  return;
}

The checker will not report any leak on the code of "checkLeak3" example
because the SymbolDerived symbols of "ha[0]" and "ha[1]" are not considered
dead when "checkDeadSymbol" callback is invoked at "return;" But if I add
two fake assignments like this:

void checkLeak4(int tag) {
  handle_t ha[2];
  request(0, ha, ha+1);
  ha[0] = *ha;
  ha[1] = *(ha+1);
  return;
}

The checker will report leaks on "ha[0]" and "ha[1]" because the
SymbolDerived symbols of "ha[0]" and "ha[1]" are considered as dead this
time.


My question is:

Is this the intended behavior of clang static analyzer when processing
SymbolDerived symbols?
If so, what should I do to reliably detect the resource leaks like the
example in "checkLeak2"?

I already tried the method that check the liveness of the parent
SymbolConjured symbols of each SymbolDerived symbols. If a SymbolDerived
symbol's parent symbol is "dead", it will considered as dead as well.
However, this method does not work in the "checkLeak2" example, as the
SymbolConjured symbol "ha" is dead after analyzing "release(ha[0])" and
before "release(ha[1])", the analyzer will report "ha[1]" as leak because
"release(ha[1])" is not analyzed yet and parent symbol of "ha[1]" is
already dead and "ha[1]" is not in "Release" state.

Thanks for any help,

Haowei
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20170530/c625fc45/attachment.html>


More information about the cfe-dev mailing list