Skip to content

C++: prototype for off-by-one in array-typed field #10562

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 11 commits into from
Oct 6, 2022

Conversation

rdmarsh2
Copy link
Contributor

No description provided.

@github-actions github-actions bot added the C++ label Sep 23, 2022
Copy link
Contributor

@MathiasVP MathiasVP left a comment

Choose a reason for hiding this comment

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

Looks good so far! It's great to see that you managed to build the correct Linux and find the CVE we expected 🎉.

@@ -0,0 +1,24 @@
/**
* @id cpp/constant-size-array-off-by-one
* @kind path-problem
Copy link
Contributor

Choose a reason for hiding this comment

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

The metadata suggests that this is a path-problem but you've not imported DataFlow::PathGraph, and the columns selected also doesn't match the format expected for path-problems.

where
size = fai.getField().getUnspecifiedType().(ArrayType).getArraySize() and
DataFlow::localInstructionFlow(fai, pai.getLeft()) and
DataFlow::localInstructionFlow(pai, ao.getAnyDef()) and
Copy link
Contributor

Choose a reason for hiding this comment

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

The point of this conjunct is to ensure that the computed address is actually dereferenced, right? If so, it seems this could use the same interprocedural dataflow config we created in https://github.com/github/codeql/pull/10438/files#diff-f245ae0a243ae41fb7d507426991139388edd94c3dee54575550955762664b3cR200, right?

On the other hand, the set of sources in this query might be so large that it's not feasible to do global dataflow.

So if we do want to keep it local, I suggest we speed it up by a forward and backward pruning step before computing the transitive closure.

This currently copy-pastes some predicates from InvalidPointerDeref.ql.
Those should be moved to a library file in a followup
Copy link
Contributor

@MathiasVP MathiasVP left a comment

Choose a reason for hiding this comment

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

Looks like there's good progress here! Do you think it's time to take it out of draft soon?

isInvalidPointerDerefSink(sink, deref, operation) and
isConstantSizeOverflowSource(f, source.asInstruction(), delta)
select source,
"This pointer arithmetic may have an off-by-" + (delta + 1) + " error allowing it to overrun $@ at this $@",
Copy link
Contributor

Choose a reason for hiding this comment

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

This will remove the Code Scanning alert (but you obviously need to accept all the test changes as well in that case).

Suggested change
"This pointer arithmetic may have an off-by-" + (delta + 1) + " error allowing it to overrun $@ at this $@",
"This pointer arithmetic may have an off-by-" + (delta + 1) + " error allowing it to overrun $@ at this $@.",

isFieldAddressSource(f, source) and
pai.getLeft() = sink.asInstruction() and
f.getUnspecifiedType().(ArrayType).getArraySize() = size and
semBounded(getSemanticExpr(pai.getRight()), b, bound, true, _) and
Copy link
Contributor

Choose a reason for hiding this comment

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

I was confused for a second about why you didn't use b for anything (since I just assumed it would be any SemBound), but now I see that b is a SemZeroBound. I think it would have been clear for me from the start if this line had instead been:

Suggested change
semBounded(getSemanticExpr(pai.getRight()), b, bound, true, _) and
semBounded(getSemanticExpr(pai.getRight()), any(SemZeroBound zero), bound, true, _) and

(and then obviously not included b in the list of existentially-quantified variables).

@rdmarsh2 rdmarsh2 marked this pull request as ready for review September 30, 2022 18:23
@rdmarsh2 rdmarsh2 requested a review from a team as a code owner September 30, 2022 18:23
MathiasVP
MathiasVP previously approved these changes Sep 30, 2022
Copy link
Contributor

@MathiasVP MathiasVP left a comment

Choose a reason for hiding this comment

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

LGTM!

@github-actions
Copy link
Contributor

github-actions bot commented Sep 30, 2022

QHelp previews:

cpp/ql/src/experimental/Security/CWE/CWE-193/ConstantSizeArrayOffByOne.qhelp

Constant array overflow

The program performs an out-of-bounds read or write operation. In addition to causing program instability, techniques exist which may allow an attacker to use this vulnerability to execute arbitrary code.

Recommendation

Ensure that pointer dereferences are properly guarded to ensure that they cannot be used to read or write past the end of the allocation.

Example

The first example uses a for loop which is improperly bounded by a non-strict less-than operation and will write one position past the end of the array. The second example bounds the for loop properly with a strict less-than operation.

#define MAX_SIZE 1024

struct FixedArray {
  int buf[MAX_SIZE];
};

int main(){
  FixedArray arr;

  for(int i = 0; i <= MAX_SIZE; i++) {
    arr.buf[i] = 0; // BAD
  }

  for(int i = 0; i < MAX_SIZE; i++) {
    arr.buf[i] = 0; // GOOD
  }
}

References

Copy link
Contributor

@MathiasVP MathiasVP left a comment

Choose a reason for hiding this comment

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

LGTM otherwise

@MathiasVP
Copy link
Contributor

Also just a minor question about the title of the PR: There's nothing "prototypy" about this query anymore, right? That is, this is a fully-fledged query that we expect to promote to Code Scanning this coming quarter, correct?

@MathiasVP MathiasVP merged commit a856bc8 into github:main Oct 6, 2022
@rdmarsh2 rdmarsh2 deleted the rdmarsh2/cpp/field-off-by-one branch October 13, 2022 16:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants