Skip to content

Python: Add support for await in API graphs#5944

Merged
codeql-ci merged 5 commits intogithub:mainfrom
RasmusWL:async-api-graph-tests
Jun 16, 2021
Merged

Python: Add support for await in API graphs#5944
codeql-ci merged 5 commits intogithub:mainfrom
RasmusWL:async-api-graph-tests

Conversation

@RasmusWL
Copy link
Copy Markdown
Member

Plus a few other minor cleanups

RasmusWL added 5 commits May 21, 2021 15:57
Running the tests locally would result in thousands of results before
this 😱
Before this, I ended up extracting 454 modules locally 😱
I _really_ wanted to call this `.await()`, but that did not fit in with
the convention, or the corresponding `getPromised` in JS.

https://github.com/github/codeql/blob/54f191cfe37e136bcc7189b2fb01f44dbb01758b/javascript/ql/src/semmle/javascript/ApiGraphs.qll#L184
@RasmusWL RasmusWL requested a review from a team as a code owner May 21, 2021 15:13
@RasmusWL RasmusWL requested a review from tausbn May 21, 2021 15:13
@erik-krogh
Copy link
Copy Markdown
Contributor

erik-krogh commented Jun 8, 2021

We call the same concept getPromised in JavaScript: https://github.com/github/codeql/blob/main/javascript/ql/src/semmle/javascript/ApiGraphs.qll#L180-L184

@RasmusWL
Copy link
Copy Markdown
Member Author

RasmusWL commented Jun 9, 2021

We call the same concept getPromised in JavaScript: https://github.com/github/codeql/blob/main/javascript/ql/src/semmle/javascript/ApiGraphs.qll#L180-L184

Yep I noted that in c4e244e. This is called Awaitables in Python (docs), so I that's what I went with. @erik-krogh are you suggesting that we should also call it getPromised for Python, to keep the API graph interface consistent? or are you just providing additional info on how things are done in JS for inspiration?

@erik-krogh
Copy link
Copy Markdown
Contributor

We call the same concept getPromised in JavaScript: https://github.com/github/codeql/blob/main/javascript/ql/src/semmle/javascript/ApiGraphs.qll#L180-L184

Yep I noted that in c4e244e. This is called Awaitables in Python (docs), so I that's what I went with. @erik-krogh are you suggesting that we should also call it getPromised for Python, to keep the API graph interface consistent? or are you just providing additional info on how things are done in JS for inspiration?

Purely for inspiration.
And yeah, on further thought, calling it getAwaited in Python makes more sense than getPromised.

Copy link
Copy Markdown
Contributor

@tausbn tausbn left a comment

Choose a reason for hiding this comment

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

This looks good to me. 👍

My knowledge of await is fairly minimal, however, so there is one thing I'm wondering: Is there any situation where the difference between foo and await foo is significant?
By this I mean: what would happen if we were to silently step from the former to the latter, without adding a specifically labelled edge?

Would this result in false positives?

@erik-krogh
Copy link
Copy Markdown
Contributor

By this I mean: what would happen if we were to silently step from the former to the latter, without adding a specifically labelled edge?

Some context from JavaScript:
We have a taint-step that does exactly that (see PromiseTaintStep in Promises.qll).
But that is only enabled for TaintTracking configurations, not for DataFlow configurations.

@RasmusWL
Copy link
Copy Markdown
Member Author

RasmusWL commented Jun 10, 2021

My knowledge of await is fairly minimal, however, so there is one thing I'm wondering: Is there any situation where the difference between foo and await foo is significant?
By this I mean: what would happen if we were to silently step from the former to the latter, without adding a specifically labelled edge?

Would this result in false positives?

I guess you're thinking about whether we it would be worth it to make things more simple, by just ignoring this?

From the top of my head I can't really give any specific examples where silently stepping from foo to await foo would cause trouble in regards to modeling libraries, but I'm stuck with a feeling that ignoring this aspect is going to be a bit too magical, and make our analysis not respect the semantics of Python... I guess that's a rather vague argument, but I feel much more inclined towards explicitly using .getAwaited() 👍

As a more objective argument against, if we need to silently step in this way, wouldn't that also mean that API::moduleImport("foo").getMember("bar").getACall() should have both foo.bar() and await foo.bar() as results? -- and therefore it's result type could no longer be DataFlow::CallCfgNode, which seems like a big loss 😱 after thinking this over, I don't think this argument makes sense 😄 since we would probably only extend getAUse() and getReturn() to account for this...

@RasmusWL
Copy link
Copy Markdown
Member Author

Talked this over in person with @tausbn, and we decided that doing this automatically would be a bit too magic ✨ so we're going to go with .getAwaited() 👍

@codeql-ci codeql-ci merged commit bcafe53 into github:main Jun 16, 2021
@RasmusWL RasmusWL deleted the async-api-graph-tests branch June 16, 2021 15:46
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.

4 participants