[Analyzer] For the undefined value of array element, the tracking information is incomplete

Hi all,

For the code below, there is a undefined value assignment. However the report is incomplete, based on the report, we can’t know where the undefined value came from.

// clang -cc1 -analyze -analyzer-checker=core -analyzer-output=text test.c

void foo() {
char *argv[10];
const char* s = argv[2];
}

// Report information.

test.c:3:2: warning: Assigned value is garbage or undefined

const char *s = argv[2];

^ ~~~~~~~

test.c:3:2: note: Assigned value is garbage or undefined

const char *s = argv[2];

^ ~~~~~~~

1 warning generated.

The fix for this is not complex, adding the special hanle for ArraySubscriptExpr in peelOffOuterExpr() can achieve the goal.

static const Expr *peelOffOuterExpr(const Expr *Ex, const ExplodedNode *N) {
// ...

if (auto *ASE = dyn_cast<ArraySubscriptExpr>(Ex))

return peelOffOuterExpr(ASE->getBase(), N);

// ...
}

However, After we modified peelOffOuterExpr(), another problem emerged at this time. Although we got the information where the undefined value came from, the description is not correct.

test.c:3:2: warning: Assigned value is garbage or undefined

const char *s = argv[2];

^ ~~~~~~~

test.c:2:2: note: 'argv' initialized here

char *argv[10];

^~~~~~~~~~

test.c:3:2: note: Assigned value is garbage or undefined

const char *s = argv[2];

^ ~~~~~~~

1 warning generated.

The essential reason is that analyzer treat completely-undefined structures as defined values, see http://clang-developers.42468.n3.nabble.com/uninitialized-variable-tp4053392p4053393.html. That’s why showBRDiagnostics() gave the wrong description.


Clang Developers - uninitialized variable
uninitialized variable. I am writing a checker to check that a variable is given a value before it is accessed. So I created a checkLocation call-back: void checkLocation(SVal L, bool IsLoad, const…
clang-developers.42468.n3.nabble.com
|

  • |

I want to know if there is a simple and efficient way to determine whether the LazyCompoundVal is undefined or partially-undefined except iterating the ElementRegion bindings?

Thanks in advance!

Henry Wong
Qihoo 360 Codesafe Team

You’ve peeled off too much information. In this example you only need to track the element (in the form of the specific ElementRegion), but you’re trying to track the whole array instead. The information about index is crucial for that. You should not peel it off, but instead use it.

Also, the trackNullOrUndefValue visitor is a mess. These getDerefExpr/peelOffOuterExpr/etc functions have really weird contracts that nobody understands. Getting anything done here is very hard unless somebody actually does the work of decomposing the solution into simple clear steps (which is, well, the hardest part of programming).

If you ever need to see if a LazyCompoundVal is fully or partially (un)initialized, you can iterBindings(). This is non-typechecked lookup (i.e., you cannot figure out which specific sub-region is initialized by the value you look at, you only get a byte offset). You can also improve iterBindings() to make it possible to restrict the iteration to a single cluster, because within the LazyCompoundVal’s Store only the cluster that corresponds to the LazyCompoundVal’s parent region is relevant.