Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
18 changes: 17 additions & 1 deletion javascript/ql/src/semmle/javascript/GeneratedCode.qll
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,21 @@ private predicate hasManyInvocations(TopLevel tl) {
)
}

/**
* Holds if `f` is side effect free, and full of primitive literals, which is often a sign of generated data code.
*/
private predicate isData(File f) {
// heuristic: `f` has more than 1000 primitive literal expressions ...
count(SyntacticConstants::PrimitiveLiteralConstant e | e.getFile() = f) > 1000 and
// ... but no expressions with side effects ...
not exists (Expr e |
e.getFile() = f and
e.isImpure() and
// ... except for variable initializers
not e instanceof VariableDeclarator
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Does this mean we consider VariableDeclarators to be impure? That seems undesirable.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Yes, but that seems right to me.
They do modify the scope object after all.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

That's true, but modelling it seems overkill, particularly since we don't even model the scope object. Also, that modification isn't observable in any way, is it?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Hmm. I could go either way on this. On the one hand, shadowing variables in enclosing scopes and creation of properties on the global object are easily observable side effects, but on the other hand, I see what you mean regarding the expressive power of our analysis.
Do you want a change in this PR?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

You are right, of course, there are observable side effects, but I would still hesitate to ascribe them to the declarator, so on the whole I'd be in favour of changing this. It seems like a fairly minor and harmless change that would make this predicate look a bit less confusing.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Done.
Do we skip the full dist-compare for this change?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Thanks. Yes, we do.

)
}

/**
* Holds if `tl` looks like it contains generated code.
*/
Expand All @@ -108,7 +123,8 @@ predicate isGenerated(TopLevel tl) {
tl instanceof GWTGeneratedTopLevel or
tl instanceof DartGeneratedTopLevel or
exists (GeneratedCodeMarkerComment gcmc | tl = gcmc.getTopLevel()) or
hasManyInvocations(tl)
hasManyInvocations(tl) or
isData(tl.getFile())
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
| ai.1.2.3-build0123.js:0:0:0:0 | ai.1.2.3-build0123.js | library |
| bundle-directive.js:0:0:0:0 | bundle-directive.js | generated |
| data.js:0:0:0:0 | data.js | generated |
| exported-data.js:0:0:0:0 | exported-data.js | generated |
| jison-lex.js:0:0:0:0 | jison-lex.js | generated |
| jison.js:0:0:0:0 | jison.js | generated |
| jquery-datatables.js:0:0:0:0 | jquery-datatables.js | library |
Expand Down
Loading