Skip to content

Simple normalizations for +1/-1 bounds scenarios #1128

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
Jul 20, 2021
Merged
Changes from 1 commit
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
f60113f
Add NormalizeUtils.h and NormalizeUtils.cpp
Jul 7, 2021
4e0ab90
Add NormalizeUtil::AddExprs helper method
Jul 7, 2021
de4c40e
Add NormalizeUtil::TransformAdditiveOp method
Jul 7, 2021
db8a01e
Fix typos
Jul 7, 2021
f0c0b14
Add ExprCreatorUtil::CreateUnaryOperator method
Jul 7, 2021
f8faae2
Add NormalizeUtil::GetAdditionOperands helper method
Jul 7, 2021
24d6c66
Rename variable in NormalizeUtil::TransformSingleAdditiveOp
Jul 7, 2021
2b4b9c9
Add ExprUtil::EnsureEqualBitWidths method
Jul 8, 2021
f6443fd
Add NormalizeUtil::GetRHSConstant helper method
Jul 8, 2021
e1a9630
Add NormalizeUtil::TransformAssocLeft method
Jul 8, 2021
7ee773e
Add NormalizeUtil::ConstantFold method
Jul 8, 2021
d6b25a6
Remove ConstantFoldUpperOffsets, GetRHSConstant, and EnsureEqualBitWi…
Jul 8, 2021
b99804d
Fix typos
Jul 12, 2021
fc09e82
Avoid creating an unnecessary binary operator in TransformAdditiveOp
Jul 12, 2021
5ca588b
Return argument expression from TransformAssocLeft if the argument is…
Jul 12, 2021
0ddfa57
Add NormalizeUpperBound method to CheckBoundsDeclarations
Jul 12, 2021
0078abd
Add CompareNormalizeBounds method to CheckBoundsDeclarations
Jul 12, 2021
b50dc1f
Remove expected warning from bounds widening test in bounds-context.c
Jul 12, 2021
ced9e4f
Add tests for comparing normalized bounds to bounds-decl-checking.c
Jul 12, 2021
cdd7b58
Merge branch 'master' of https://github.com/microsoft/checkedc-clang …
Jul 12, 2021
a375cae
Move declaration of PointerAndConst
Jul 13, 2021
ff5130b
Add comment explaining why we don't check for B - P
Jul 16, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add NormalizeUpperBound method to CheckBoundsDeclarations
  • Loading branch information
kakje committed Jul 12, 2021
commit 0ddfa574cb9286ebde4670cd1b2086c0c82861cb
77 changes: 77 additions & 0 deletions clang/lib/Sema/SemaBounds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include "clang/AST/AbstractSet.h"
#include "clang/AST/CanonBounds.h"
#include "clang/AST/ExprUtils.h"
#include "clang/AST/NormalizeUtils.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Sema/AvailableFactsAnalysis.h"
#include "clang/Sema/BoundsAnalysis.h"
Expand Down Expand Up @@ -2013,6 +2014,82 @@ namespace {
return ProofResult::Maybe;
}

// NormalizeUpperBound attempts to extract a Variable part and a Constant
// part from the upper bound expression E.
//
// If E can be expressed as:
// 1. (E1 + (E2 op1 A)) op2 B, or:
// 2. B + (E1 + (E2 op1 A))
// where:
// 1. E1 has pointer type, and:
// 2. E2 has integer type, and:
// 3. A and B are integer constants, and:
// 4. op1 and op2 are + or -
// then:
// 1. Variable = E1 + E2
// 2. Constant = A' + B', where A' is -A if op1 is - and B' is -B if
// op2 is -.
//
// If we cannot normalize E to one of these two forms, then Variable = E,
// Constant = 0, and NormalizeUpperBound returns false.
bool NormalizeUpperBound(Expr *E, Expr *&Variable, llvm::APSInt &Constant) {
Expr *PointerExpr;
Expr *ConstExpr;
llvm::APSInt C;

// E must be of the form X op2 Y, where op2 is + or -.
BinaryOperator *BO = dyn_cast<BinaryOperator>(E->IgnoreParens());
if (!BO)
goto exit;
if (!BinaryOperator::isAdditiveOp(BO->getOpcode()))
goto exit;

// E must be of the form P op2 B or B + P, where P has pointer type
// and B is an integer constant expression.
if (BO->getLHS()->getType()->isPointerType() &&
BO->getRHS()->isIntegerConstantExpr(C, S.Context)) {
PointerExpr = BO->getLHS();
ConstExpr = BO->getRHS();
} else if (BO->getOpcode() == BinaryOperatorKind::BO_Add &&
BO->getRHS()->getType()->isPointerType() &&
BO->getLHS()->isIntegerConstantExpr(C, S.Context)) {
PointerExpr = BO->getRHS();
ConstExpr = BO->getLHS();
} else
goto exit;

// Normalize X - Y operators in PointerExpr and its children to X + -Y.
// If we cannot, then PointerExpr is not a +/- operator, so we cannot
// continue to normalize.
PointerExpr = NormalizeUtil::TransformAdditiveOp(S, PointerExpr);
if (!PointerExpr)
goto exit;

// Associate PointerExpr to the left to get (E1 + E2) + E3.
// If we cannot, then we cannot continue to normalize.
PointerExpr = NormalizeUtil::TransformAssocLeft(S, PointerExpr);
if (!PointerExpr)
goto exit;

// We have PointerExpr of the form (E1 + E2) + E3. Try to constant fold
// ((E1 + E2) + E3) op2 B to (E1 + E2) + (E3 op2 B).
// If we can perform this constant folding, then Variable = E1 + E2 and
// Constant = E3 op2 B.
// Otherwise, Variable = E and Constant = 0.
Expr *PointerAndConst =
ExprCreatorUtil::CreateBinaryOperator(S, PointerExpr, ConstExpr,
BO->getOpcode());
return NormalizeUtil::ConstantFold(S, PointerAndConst, E->getType(),
Variable, Constant);

exit:
// Return (E, 0).
Variable = E;
uint64_t PointerWidth = S.Context.getTargetInfo().getPointerWidth(0);
Constant = llvm::APSInt(PointerWidth, false);
return false;
}

// Try to prove that PtrBase + Offset is within Bounds, where PtrBase has pointer type.
// Offset is optional and may be a nullptr.
ProofResult ProveMemoryAccessInRange(Expr *PtrBase, Expr *Offset, BoundsExpr *Bounds,
Expand Down