mirror of
https://github.com/intel/llvm.git
synced 2026-01-31 16:29:50 +08:00
Add trivial buffer overflow checking in Sema.
llvm-svn: 125640
This commit is contained in:
@@ -3379,6 +3379,10 @@ def warn_not_compound_assign : Warning<
|
||||
def warn_explicit_conversion_functions : Warning<
|
||||
"explicit conversion functions are a C++0x extension">, InGroup<CXX0x>;
|
||||
|
||||
def warn_array_index_out_of_bounds : Warning<
|
||||
"array index %select{precedes first|excedes last}0 array element">,
|
||||
InGroup<DiagGroup<"array-bounds">>;
|
||||
|
||||
def warn_printf_write_back : Warning<
|
||||
"use of '%%n' in format string discouraged (potentially insecure)">,
|
||||
InGroup<FormatSecurity>;
|
||||
|
||||
@@ -5056,7 +5056,8 @@ public:
|
||||
SourceLocation getLocationOfStringLiteralByte(const StringLiteral *SL,
|
||||
unsigned ByteNo) const;
|
||||
|
||||
private:
|
||||
private:
|
||||
void CheckArrayAccess(const ArraySubscriptExpr *ae);
|
||||
bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall);
|
||||
bool CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall);
|
||||
|
||||
|
||||
@@ -3080,3 +3080,33 @@ void Sema::CheckCastAlign(Expr *Op, QualType T, SourceRange TRange) {
|
||||
<< TRange << Op->getSourceRange();
|
||||
}
|
||||
|
||||
void Sema::CheckArrayAccess(const clang::ArraySubscriptExpr *ae) {
|
||||
const DeclRefExpr *dr =
|
||||
dyn_cast<DeclRefExpr>(ae->getBase()->IgnoreParenImpCasts());
|
||||
if (!dr)
|
||||
return;
|
||||
const VarDecl *vd = cast<VarDecl>(dr->getDecl());
|
||||
const ConstantArrayType *cat = Context.getAsConstantArrayType(vd->getType());
|
||||
if (!cat)
|
||||
return;
|
||||
const Expr *idx = ae->getIdx();
|
||||
if (idx->isValueDependent())
|
||||
return;
|
||||
llvm::APSInt result;
|
||||
if (!idx->isIntegerConstantExpr(result, Context))
|
||||
return;
|
||||
unsigned kind = 2;
|
||||
if (result.slt(0))
|
||||
kind = /* precedes */ 0;
|
||||
else {
|
||||
const llvm::APInt &size = cat->getSize();
|
||||
if (size.getBitWidth() > result.getBitWidth())
|
||||
result = result.sext(size.getBitWidth());
|
||||
if (result.sge(size))
|
||||
kind = /* excedes */ 1;
|
||||
}
|
||||
if (kind < 2)
|
||||
Diag(ae->getBase()->getLocEnd(), diag::warn_array_index_out_of_bounds)
|
||||
<< kind << idx->getSourceRange();
|
||||
}
|
||||
|
||||
|
||||
@@ -294,6 +294,9 @@ void Sema::DefaultLvalueConversion(Expr *&E) {
|
||||
if (T.hasQualifiers())
|
||||
T = T.getUnqualifiedType();
|
||||
|
||||
if (const ArraySubscriptExpr *ae = dyn_cast<ArraySubscriptExpr>(E))
|
||||
CheckArrayAccess(ae);
|
||||
|
||||
E = ImplicitCastExpr::Create(Context, T, CK_LValueToRValue,
|
||||
E, 0, VK_RValue);
|
||||
}
|
||||
@@ -7242,6 +7245,11 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS,
|
||||
Diag(UO->getOperatorLoc(), diag::note_indirection_through_null);
|
||||
}
|
||||
|
||||
// Check for trivial buffer overflows.
|
||||
if (const ArraySubscriptExpr *ae
|
||||
= dyn_cast<ArraySubscriptExpr>(LHS->IgnoreParenCasts()))
|
||||
CheckArrayAccess(ae);
|
||||
|
||||
// C99 6.5.16p3: The type of an assignment expression is the type of the
|
||||
// left operand unless the left operand has qualified type, in which case
|
||||
// it is the unqualified version of the type of the left operand.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-check-buffer-overflows -verify %s
|
||||
// RUN: %clang_cc1 -Wno-array-bounds -analyze -analyzer-check-objc-mem -analyzer-check-buffer-overflows -verify %s
|
||||
|
||||
// Tests doing an out-of-bounds access after the end of an array using:
|
||||
// - constant integer index
|
||||
|
||||
16
clang/test/Sema/array-bounds.c
Normal file
16
clang/test/Sema/array-bounds.c
Normal file
@@ -0,0 +1,16 @@
|
||||
// RUN: %clang_cc1 -verify %s
|
||||
|
||||
int foo() {
|
||||
int x[2];
|
||||
int y[2];
|
||||
int *p = &y[2]; // no-warning
|
||||
(void) sizeof(x[2]); // no-warning
|
||||
y[2] = 2; // expected-warning{{array index excedes last array element}}
|
||||
return x[2] + // expected-warning{{array index excedes last array element}}
|
||||
y[-1] + // expected-warning{{array index precedes first array element}}
|
||||
x[sizeof(x)] + // expected-warning{{array index excedes last array element}}
|
||||
x[sizeof(x) / sizeof(x[0])] + // expected-warning{{array index excedes last array element}}
|
||||
x[sizeof(x) / sizeof(x[0]) - 1] + // no-warning
|
||||
x[sizeof(x[2])]; // expected-warning{{array index excedes last array element}}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user