Skip to content

Conversation

@ghost
Copy link

@ghost ghost commented Nov 1, 2018

This PR introduces js/useless-defensive-code as a recommendation query. The query is based on syntactic patterns, and type inference for a variable in each pattern.

Defensive code is typically a condition that prevents null or undefined values from causing a crash later on. Defensive code is useless when the condition evaluates to a single value for all execution paths. In that case, the condition might as well be removed. I welcome a discussion of the patterns.

The end result is that:

  1. Some alerts from js/trivial-conditional and js/comparison-between-incompatible-types are whitelisted
  2. The above whitelisted alerts are flagged by js/useless-defensive-code
  3. Additional, more advanced, unnecessary defensive code variants are also flagged by js/useless-defensive-code

The most important consequence of this is that the remaining alerts from js/trivial-conditional and js/comparison-between-incompatible-types now are much more severe on average. A secondary consequence is that alerts caused by type inference improvements will be easier to judge the value of.

Please note that the query deliberately treats cases like o === undefined || o.p and o === undefined && o.p identically, for the sake of simplicity. It is the responsibility of another query to flag the definite error in the latter case.

Bullet 1 and 2 above may cause a special kind of wobbliness: if we gain precision because of a simpler program or because of an improved analysis implementation, then additional alerts may be flagged by js/useless-defensive-code, while a more complex program may change those alerts to js/trivial-conditional. C.f. another evaluation.

An oldish evaluation shows that performance is fine and an interesting amount of result changes, with a net additional 69 alerts that the programmer will be presented for by default. A smaller, but more recent, evaluation on top of the current master shows that this still scales.

@ghost ghost added the JS label Nov 1, 2018
@ghost ghost self-requested a review as a code owner November 1, 2018 07:49
@asger-semmle
Copy link
Contributor

While we're on the subject, am I the only one who thinks the word "useless" sounds rude? I liked the previously suggested "unnecessary defensive programming".

Do I understand it correctly that this will not introduce any new alerts, but merely reclassify existing ones into this less severe query? It's not quite clear from bullet 3 if this means new alerts.

@ghost
Copy link
Author

ghost commented Nov 1, 2018

The phrasing is inherited from js/trivial-conditional aka UselessConditional.ql which has @name Useless conditional. We should change both or none.


Brand new alerts will be added because of some additional constant folding steps in this query. Consider the simple case of:

    if (u !== undefined) {
        u.p;
    }

This is obviously not flagged by js/heterogeneous-comparison because the comparison is homogeneous, and it is not flagged by js/trivial-conditional because we do not have a type inference step for the result of a comparison.
Another example is:

    typeof f === "function" && f();

Maybe we should let js/trivial-conditional know that null coerces to false, but that is the only low hanging fruit I have seen.

@ghost ghost added the documentation label Nov 1, 2018
@xiemaisi
Copy link

xiemaisi commented Nov 5, 2018

Ping @Semmle/doc on whether "useless" is considered rude; as a non-native speaker I don't feel qualified to judge.

Copy link

@xiemaisi xiemaisi left a comment

Choose a reason for hiding this comment

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

Wow, that's a lot of new code! A few comments and suggestions.

Overall, the large number of syntactic checks seems quite cumbersome and I'm not confident I fully understand all of the patterns being checked for. This is the sort of thing we managed to avoid in the type inference by using a more precise lattice for analysing refinement conditions, but such an approach may well not apply here. If it helps us avoid false positives that's good.

@ghost
Copy link
Author

ghost commented Nov 5, 2018

Overall, the large number of syntactic checks seems quite cumbersome.

Agreed, but I believe we must use syntactic checks to identify the relevant programming patterns.

This could be simplified a bit if we added constant folding for boolean results to the type inference, but we decided that it may not be worth it for just this query and js/trivial-conditional. Such a constant folding would also mean that js/trivial-conditional needed a whitelist for the js/heterogenous-comparison.

and I'm not confident I fully understand all of the patterns being checked for.

I have added source code examples to the docstrings.

@ghost
Copy link
Author

ghost commented Nov 7, 2018

Rebased on current master to make the tests for js/trivial-conditional work.

Copy link
Contributor

@semmledocs-ac semmledocs-ac left a comment

Choose a reason for hiding this comment

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

I've commented on the use of "useless" but haven't done a review as such.

@mchammer01
Copy link
Contributor

Asked @semmledocs-ac for help as I'm not a native speaker either. Please let me know when this is ready for a doc review. Thanks.

@ghost
Copy link
Author

ghost commented Nov 7, 2018

@mc-semmle I have addressed the "is useless" comments, and this PR is ready for doc review.

@@ -0,0 +1,32 @@
/**
* @name Useless defensive code
Copy link
Contributor

Choose a reason for hiding this comment

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

Are we happy with the use of the word "Useless" in the query name?

@@ -0,0 +1,32 @@
/**
* @name Useless defensive code
* @description If the situation some defensive code guards against never
Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry but I don't understand what you mean in the description. Would it be possible to rephrase so it's clearer?


However, if the situation that some defensive code guards
against never can occur, then the defensive code serves no purpose and
it can safely be removed.
Copy link
Contributor

Choose a reason for hiding this comment

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

Remove "it"?
...then the defensive code serves no purpose and can safely be removed.

<p>

However, due to coercion rules, <code>v ==
undefined</code> holds for both the situation where <code>v</code>
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here - remove "it"?
so the v == null guard serves no purpose, and can be removed:

@mchammer01
Copy link
Contributor

mchammer01 commented Nov 7, 2018

@esben-semmle - doc review completed. This LGTM, I have just made a few minor comments / suggestions. Feel free to ignore them if you don't agree.

@ghost
Copy link
Author

ghost commented Nov 8, 2018

Thank you @mc-semmle

The query description is now "Defensive code that guards against a situation that never happens is not needed." And the query name is "Unneeded defensive code"

@mchammer01
Copy link
Contributor

Thank you for the updates @esben-semmle - LGTM 👍

mchammer01
mchammer01 previously approved these changes Nov 8, 2018
Copy link
Contributor

@mchammer01 mchammer01 left a comment

Choose a reason for hiding this comment

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

Good to go from my perspective. Thanks for the last amendments.

xiemaisi
xiemaisi previously approved these changes Nov 9, 2018
@xiemaisi
Copy link

Conflicts.

@ghost
Copy link
Author

ghost commented Nov 13, 2018

Conflicts resolved.

@xiemaisi xiemaisi merged commit a499009 into github:master Nov 13, 2018
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