[cfe-dev] pointer values, taint propogation

McDowell, Raymond C. via cfe-dev cfe-dev at lists.llvm.org
Wed Feb 15 04:55:53 PST 2017


I didn't realize the screen captures would make things difficult.  Here's a version of the e-mail with text instead.

I would like to write a checker to make sure that pointers from untrusted sources are not dereferenced.  So I am playing around with the alpha.security.taint checker to try to understand how taint propagation works.  I put together some simple test cases:

#include <stdio.h>
#include <string.h>

void test(float f, char *sp1, char *sp2, char *sp3) {
  char *sv1, *sv2, *sv3;

  long long ll;
  scanf("%lld", &ll);    // ll is read from stdin, so is untrusted

  if (ll) {
    printf((char *)ll, f);    // flag: ll is untrusted
    sv1 = (char *)ll;
    printf(sv1, f);    // flag: sv1 = ll is untrusted
    sp1 = (char *)ll;
    printf(sp1, f);    // flag: sp1 = ll is untrusted

    printf((char *)NULL+ll, f);    // flag: ll is untrusted
    unsigned long u = 0;
    u += ll;
    printf((char *)u, f);    // flag: u = 0+ll is untrusted
    sv2 = NULL;
    sv2 += ll;
    printf(sv2, f);    // flag: sv2 = NULL+ll is untrusted
    sp2 = NULL;
    sp2 += ll;
    printf(sp2, f);    // flag: sp2 = NULL+ll is untrusted

    printf(sp3, f);
    sv3 = sp3;
    sv3 += ll;
    printf(sv3, f);    // flag: sv3 = sp3+ll is untrusted
    sp3 += ll;
    printf(sp3, f);    // flag: sp3 = sp3+ll is untrusted
  }
}

The indicated calls to printf should be flagged because an untrusted value is passed as the format string (the first argument).  When I run the alpha.security.taint checker on this, it only flags the last two.  Looking into this, I found that the static analyzer often assigns an unknown value to the result of casting from an integer to a pointer.  Taint can't be attached to an unknown value, so I need a known value for the pointer.  Although I'm not sure if this is really what we want to do, for now I added a post-check call-back on cast expressions to my checker that casts the integer to unsigned and then assigns the result as the pointer value.

void UntrustedDerefChecker::checkPostStmt(const CastExpr *CE, CheckerContext &ChCtx) const {
  ProgramStateRef St = ChCtx.getState();
  const LocationContext *LCtx = ChCtx.getLocationContext();
  if (CE->getCastKind() == CK_IntegralToPointer && St->getSVal(CE, LCtx).isUnknown()) {
    // if cast to pointer resulted in an unknown value, try casting to unsigned instead
    const Expr *SubExpr = CE->getSubExpr();
    QualType CastTy = ChCtx.getASTContext().UnsignedLongTy;
    QualType SubExprTy = SubExpr->getType();
    SVal Val = St->getSVal(SubExpr, LCtx);
    Val = St->getStateManager().getSValBuilder().evalIntegralCast(St, Val, CastTy, SubExprTy);
    ChCtx.addTransition(St->BindExpr(CE, LCtx, Val));
  }
}

When I run alpha.security.taint together with this on the test file, it flags the calls to printf where (char *)l and (char *)u are passed, but not the calls where sv1, sp1, (char *)NULL+l, sv2, or sp2 are passed, even though these are just different expressions with the same value.  I tried looking into this using the debugger, and found that when the analyzer calls ExprEngine::evalStore for the assignment statement (say "sv1 = (char *)ll"), it gives the pointer the appropriate value, but when the analyzer calls GenericTaintChecker::checkUncontrolledFormatString from the pre-check call-back for the call to printf on the following line of the test file, the pointer has an UnknownVal.  (See excepts from the debugging session below.)

Can anyone help me understand what is going on here?

Thanks,
Ray

(These debugger session excepts are inherently screen captures, but the gist of them is described above.)

[cid:image003.png at 01D28760.015ABE20]

[cid:image004.png at 01D28760.015ABE20]

[cid:image005.png at 01D28760.015ABE20]

[cid:image006.png at 01D28760.015ABE20]
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20170215/2b3b1442/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image003.png
Type: image/png
Size: 24875 bytes
Desc: image003.png
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20170215/2b3b1442/attachment.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image004.png
Type: image/png
Size: 20327 bytes
Desc: image004.png
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20170215/2b3b1442/attachment-0001.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image005.png
Type: image/png
Size: 46457 bytes
Desc: image005.png
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20170215/2b3b1442/attachment-0002.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image006.png
Type: image/png
Size: 13298 bytes
Desc: image006.png
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20170215/2b3b1442/attachment-0003.png>


More information about the cfe-dev mailing list