-
Notifications
You must be signed in to change notification settings - Fork 1.9k
CPP: Improvements to Buffer.qll #270
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
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
c747f24
CPP: Fix the initialized array case in getBufferSize.
geoffw0 ef8ca5d
CPP: Replace def-use with dataflow in getBufferSize.
geoffw0 beb21f9
CPP: Separate the dataflow case from dynamic allocation.
geoffw0 fe6c9f9
CPP: Stricter dataflow in getBufferSize.
geoffw0 8ab830f
CPP: Allow multiple dataflow sources.
geoffw0 8163def
CPP: Alter the dataflow case.
geoffw0 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This use or
forexreminds me of the code that was removed in https://git.semmle.com/Semmle/code/commit/90a05cd6fafcd2e179c49f17a5b67bb01de2b57d because it had bad performance on certain pathological snapshots. I'm guessing the same transformation could be needed here.As I understand it, the performance is quadratic in the number of
def: for eachdefthe implicitexistswill find one or moreresult, and then each of thoseresultwill be checked against every otherdefin the implicitforall.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, as I understand it the issue is that
forex(x | y)is not a primitive language feature but syntax sugar forforall(x | y) and exists(x | y). Which is usually fine, but ifycontains a variable from outside theforexit's possible to produce a cartesian product. I haven't been able to characterize exactly when this happens.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nevertheless I've made the change, and it has no noticeable effect on performance (as we'd expect outside of extreme cases).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One way to see the the problem is that if you wrote
forallinstead offorexhere, the compiler would rightfully complain thatresultwas not bound: for abufferExprwith no associateddef, any value ofresultwould satisfy theforall. This would makeresulttake infinitely many values in the sense that the type checker considersintto be infinite.In other words, the
forallcan only check whether a candidate forresulthas the desired properties -- it cannot generate a candidate. When it's joined with anexists, the candidates can be generated byexists, and then each candidate is checked by theforall. If there are n different candidates, and each candidate needs to be compared for equality with the n other candidates, then the run time is n^2.As I'm writing this out, I can see that it would take some quite contrived code to trigger the quadratic behaviour.