Skip to content

Bounds context: observed bounds [2/n] #827

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 9 commits into from
May 5, 2020
Merged

Conversation

kkjeer
Copy link
Contributor

@kkjeer kkjeer commented Apr 30, 2020

This PR replaces the UC bounds context member of CheckingState with ObservedBounds, and uses the observed bounds as the rvalue bounds for the value of a variable, rather than as the lvalue target bounds for a variable.

Context:

This is part of the ongoing work to improve the soundness of bounds checking involving assignments to variables. This work is also related to the bounds widening analysis (e.g. #821). After this PR is merged, and the ObservedBounds context is updated to reflect the widened bounds of nt_array_ptrs, the bounds checking can use the widened bounds as the rvalue bounds of the value of an nt_array_ptr variable.

Notable changes:

  • Rename the UC bounds context to ObservedBounds. This makes the meaning of the bounds expressions in the bounds context more clear: the observed bounds are the bounds that are currently known to be valid for a variable. These bounds are updated during bounds checking and will later be used to verify that the observed bounds imply the declared bounds for all variables after an assignment.
  • Do not use the observed bounds of a variable as the lvalue target bounds. The target bounds of a variable should always be the programmer-declared bounds.
  • Use the observed bounds of a variable as the rvalue bounds by modifying RValueCastBounds for LValueToRValue casts.

Tests:

  • Modified the bounds-context.c tests to reflect changes in how the bounds context is printed.
  • Passed manual testing on Windows.
  • Passed automated testing on Windows/Linux.

@@ -683,12 +685,14 @@ namespace {
SemaRef(SemaRef),
BoundsContextRef(Context) {}

bool VisitDeclaratorDecl(DeclaratorDecl *D) {
bool VisitVarDecl(VarDecl *D) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't D be a const VarDecl here?

@@ -683,12 +685,14 @@ namespace {
SemaRef(SemaRef),
BoundsContextRef(Context) {}

bool VisitDeclaratorDecl(DeclaratorDecl *D) {
bool VisitVarDecl(VarDecl *D) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a comment about what the bool return value of this function means?

BoundsExpr *Bounds = D->getBoundsExpr();
if (Bounds)
BoundsContextRef[D] = Bounds;
BoundsContextRef[D] = SemaRef.ExpandBoundsToRange(D, Bounds);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a comment here that the declared bounds are normalized to range bounds here?

@@ -820,19 +824,19 @@ namespace {
DumpEqualExpr(OS, State.G);
}

void DumpBoundsContext(raw_ostream &OS, BoundsContextTy UC) {
if (UC.empty())
void DumpBoundsContext(raw_ostream &OS, BoundsContextTy Context) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you change the Context parameter to be a reference?
void DumpBoundsContext(raw_ostream &OS, BoundsContextTy &Context)

DeclaratorDecl *Variable = *I;
if (!UC[Variable])
const VarDecl *Variable = *I;
if (!Context[Variable])
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this would insert the Variable in Context if it does not exist.

If you only want to test existence of key in a map please use this:
if (Context.count(Variable))

If you want to test existence and use the value, then use this:

auto it = Context.find(Variable);
if (it != Context.end()) {
  // use *it
}

BoundsContextTy Context2) {
BoundsContextTy IntersectedContext;
for (auto Pair : Context1) {
if (!Pair.second || !Context2[Pair.first])
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment here about checking for existence of key in map.

for (auto Pair : UC1) {
if (!Pair.second || !UC2[Pair.first])
// intersection of the contexts Context1 and Context2.
BoundsContextTy IntersectBoundsContexts(BoundsContextTy Context1,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be a templated function which can be used to intersect sets holding items of any type? See https://github.com/microsoft/checkedc-clang/blob/master/clang/lib/Sema/BoundsAnalysis.cpp#L686.

Going forward we should move these intersect, union, etc functions to a common file so that we can re-use them.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated IntersectBoundsContext to reset each in-scope variable to its normalized declared bounds. Now that it's more specialized to rely on variable declarations and bounds expressions, I don't think it lends itself as well to templating.

@mgrang
Copy link

mgrang commented May 1, 2020

The names UEQ, G, OV, etc sound very cryptic. Is it possible to rename them to more descriptive names in a separate PR?

@kkjeer
Copy link
Contributor Author

kkjeer commented May 2, 2020

The names UEQ, G, OV, etc sound very cryptic. Is it possible to rename them to more descriptive names in a separate PR?

Created #828 to track this.

Copy link

@mgrang mgrang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for addressing the review comments. LGTM.

@kkjeer kkjeer merged commit f2372b0 into master May 5, 2020
@kkjeer kkjeer deleted the bounds-context-observed-bounds branch May 5, 2020 17:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants