Don't suggest the developer use 'arc4random' instead of 'rand' when that function is not available. Fixes PR 6012.

llvm-svn: 93508
This commit is contained in:
Ted Kremenek 2010-01-15 08:20:31 +00:00
parent d74cc397c8
commit abf6ba1612
2 changed files with 48 additions and 3 deletions

View File

@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Basic/TargetInfo.h"
#include "clang/Analysis/PathSensitive/BugReporter.h"
#include "clang/Analysis/LocalCheckers.h"
#include "clang/AST/StmtVisitor.h"
@ -18,6 +19,12 @@
using namespace clang;
static bool isArc4RandomAvailable(const ASTContext &Ctx) {
const llvm::Triple &T = Ctx.Target.getTriple();
return T.getVendor() == llvm::Triple::Apple ||
T.getOS() == llvm::Triple::FreeBSD;
}
namespace {
class WalkAST : public StmtVisitor<WalkAST> {
BugReporter &BR;
@ -30,10 +37,13 @@ class WalkAST : public StmtVisitor<WalkAST> {
enum { num_setids = 6 };
IdentifierInfo *II_setid[num_setids];
const bool CheckRand;
public:
WalkAST(BugReporter &br) : BR(br),
II_gets(0), II_getpw(0), II_mktemp(0),
II_rand(), II_random(0), II_setid() {}
II_rand(), II_random(0), II_setid(),
CheckRand(isArc4RandomAvailable(BR.getContext())) {}
// Statement visitor methods.
void VisitCallExpr(CallExpr *CE);
@ -83,9 +93,11 @@ void WalkAST::VisitCallExpr(CallExpr *CE) {
CheckCall_gets(CE, FD);
CheckCall_getpw(CE, FD);
CheckCall_mktemp(CE, FD);
if (CheckRand) {
CheckCall_rand(CE, FD);
CheckCall_random(CE, FD);
}
}
// Recurse and check children.
VisitChildren(CE);

View File

@ -0,0 +1,33 @@
// RUN: %clang_cc1 -triple i686-pc-linux-gnu -analyze -warn-security-syntactic %s -verify
// This file complements 'security-syntax-checks.m', but tests that we omit
// specific checks on platforms where they don't make sense.
// Omit the 'rand' check since 'arc4random' is not available on Linux.
int rand(void);
double drand48(void);
double erand48(unsigned short[3]);
long jrand48(unsigned short[3]);
void lcong48(unsigned short[7]);
long lrand48(void);
long mrand48(void);
long nrand48(unsigned short[3]);
long random(void);
int rand_r(unsigned *);
void test_rand()
{
unsigned short a[7];
unsigned b;
rand(); // no-warning
drand48(); // no-warning
erand48(a); // no-warning
jrand48(a); // no-warning
lcong48(a); // no-warning
lrand48(); // no-warning
mrand48(); // no-warning
nrand48(a); // no-warning
rand_r(&b); // no-warning
random(); // no-warning
}