<div dir="ltr">Hi<div><br></div><div>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.</div><div><br></div><div>The source code of my checker can be downloaded at this link: <a href="https://gist.github.com/zeroomega/2fcabf5979a0e42db1ccb8f30472d071">https://gist.github.com/zeroomega/2fcabf5979a0e42db1ccb8f30472d071</a></div><div><br></div><div>An example of resource leaks that my checker is trying to find is like this:</div><div><br></div><div><div>typedef uint32_t handle_t;</div><div>typedef uint32_t status_t;</div><div><br></div><div>status_t request(</div><div>  uint32_t flags,</div><div>  handle_t* out0,</div><div>  handle_t* out1);</div><div><br></div><div>status_t release(handle_t handle);</div></div><div><br></div><div><div>void checkLeak1(int tag) {</div><div>  handle_t sa, sb;</div><div>  request(0, &sa, &sb);</div><div>  if (tag > 0) {</div><div>    return;</div><div>  }</div><div>  release(sa);</div><div>  release(sb);</div><div>}</div></div><div><br></div><div><br></div><div>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). </div><div><br></div><div>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.</div><div><br></div><div>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:</div><div><br></div><div><div>void checkLeak2(int tag) {</div><div>  handle_t ha[2];</div><div>  request(0, ha, ha+1);</div><div>  if (tag > 0) {</div><div>    return;</div><div>  }</div><div>  release(ha[0]);</div><div>  release(ha[1]);</div><div>}</div></div><div><br></div><div><br></div><div>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]);".</div><div><br></div><div><br></div><div>Another two examples can show this behavior more clearly: </div><div><br></div><div><div>void checkLeak3(int tag) {</div><div>  handle_t ha[2];</div><div>  request(0, ha, ha+1);</div><div>  return;</div><div>}</div></div><div><br></div><div>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:<br></div><div><br></div><div><div>void checkLeak4(int tag) {</div><div>  handle_t ha[2];</div><div>  request(0, ha, ha+1);</div><div>  ha[0] = *ha;</div><div>  ha[1] = *(ha+1);</div><div>  return;</div><div>}</div></div><div><br></div><div>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.<br></div><div><br></div><div><br></div><div>My question is: </div><div><br></div><div>Is this the intended behavior of clang static analyzer when processing SymbolDerived symbols?</div><div>If so, what should I do to reliably detect the resource leaks like the example in "checkLeak2"? </div><div><br></div><div>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.</div><div><br></div><div>Thanks for any help,</div><div><br></div><div>Haowei</div></div>