Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b073fcf

Browse files
author
Esben Sparre Andreasen
committed
JS: add query: js/useless-defensive-code
1 parent 7b215ec commit b073fcf

13 files changed

Lines changed: 438 additions & 0 deletions

javascript/config/suites/javascript/maintainability-more

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
+ semmlecode-javascript-queries/Declarations/DuplicateVarDecl.ql: /Maintainability/Declarations
77
+ semmlecode-javascript-queries/Declarations/UnusedParameter.ql: /Maintainability/Declarations
88
+ semmlecode-javascript-queries/Declarations/UnusedVariable.ql: /Maintainability/Declarations
9+
+ semmlecode-javascript-queries/Expressions/UselessDefensiveProgramming.ql: /Maintainability/Expressions
910
+ semmlecode-javascript-queries/LanguageFeatures/ArgumentsCallerCallee.ql: /Maintainability/Language Features
1011
+ semmlecode-javascript-queries/LanguageFeatures/ConditionalComments.ql: /Maintainability/Language Features
1112
+ semmlecode-javascript-queries/LanguageFeatures/Eval.ql: /Maintainability/Language Features
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
<p>
7+
8+
Defensive code can prevent unforeseen circumstances from
9+
causing fatal program behaviors.
10+
11+
A common defensive code pattern is to guard
12+
against dereferencing the values <code>null</code> or
13+
<code>undefined</code>.
14+
15+
However, if the situation that some defensive code guards
16+
against never can occur, then the defensive code serves no purpose and
17+
it can safely be removed.
18+
19+
</p>
20+
21+
</overview>
22+
<recommendation>
23+
24+
<p>
25+
26+
Examine the surrounding code to determine if the defensive
27+
code is worth keeping despite providing no practical use. If it is no
28+
longer needed, remove it.
29+
30+
</p>
31+
32+
</recommendation>
33+
<example>
34+
35+
<p>
36+
37+
The following example shows a <code>cleanupLater</code>
38+
function that asynchronously will perform a cleanup task after some
39+
delay. When the cleanup task completes, the function invokes the
40+
provided callback parameter <code>cb</code>.
41+
42+
To prevent a crash by invoking <code>cb</code> when it
43+
has the value <code>undefined</code>, defensive code guards
44+
the invocation by checking if <code>cb</code> is truthy.
45+
46+
</p>
47+
48+
<sample src="examples/UselessDefensiveProgramming1_bad.js" />
49+
50+
<p>
51+
52+
However, the <code>cleanupLater</code> function is always
53+
invoked with a callback argument, so the defensive code condition
54+
always holds, and it is therefore not
55+
required. The function can therefore be simplified to:
56+
57+
</p>
58+
59+
<sample src="examples/UselessDefensiveProgramming1_good.js" />
60+
61+
<p>
62+
63+
Guarding against the same situation multiple times is
64+
another example of defensive code that provides no practical use. The
65+
example below shows a function that assigns a value to a property of
66+
an object, where defensive code ensures that the assigned value is not
67+
<code>undefined</code> or <code>null</code>.
68+
69+
</p>
70+
71+
<sample src="examples/UselessDefensiveProgramming2_bad.js" />
72+
73+
<p>
74+
75+
However, due to coercion rules, <code>v ==
76+
undefined</code> holds for both the situation where <code>v</code>
77+
is<code>undefined</code> and the situation where <code>v</code>
78+
is<code>null</code>, so the <code>v == null</code>
79+
guard serves no purpose, and it can be removed:
80+
81+
</p>
82+
83+
<sample src="examples/UselessDefensiveProgramming2_good.js" />
84+
85+
</example>
86+
<references>
87+
88+
<li>Wikipedia: <a href="https://en.wikipedia.org/wiki/Defensive_programming">Defensive programming</a>.</li>
89+
90+
</references>
91+
</qhelp>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* @name Useless defensive code
3+
* @description If the situation some defensive code guards against never
4+
* happens, then the defensive code is not needed.
5+
* @kind problem
6+
* @problem.severity recommendation
7+
* @id js/useless-defensive-code
8+
* @tags correctness
9+
* external/cwe/cwe-570
10+
* external/cwe/cwe-571
11+
* @precision very-high
12+
*/
13+
14+
import javascript
15+
import semmle.javascript.DefensiveProgramming
16+
17+
from DefensiveExpression e, boolean cv
18+
where e.getTheTestResult() = cv
19+
select e, "This guard always evaluates to " + cv + "."
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
function cleanupLater(delay, cb) {
2+
setTimeout(function() {
3+
cleanup();
4+
if (cb) { // BAD: useless check, `cb` is always truthy
5+
cb();
6+
}
7+
}, delay)
8+
}
9+
10+
cleanupLater(1000, function(){console.log("Cleanup done")});
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
function cleanupLater(delay, cb) {
2+
setTimeout(function() {
3+
cleanupNow();
4+
// GOOD: no need to guard the invocation
5+
cb();
6+
}, delay)
7+
}
8+
9+
cleanupLater(function(){console.log("Cleanup done")});
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
function setSafeStringProp(o, prop, v) {
2+
// BAD: `v == null` is useless
3+
var safe = v == undefined || v == null? '': v;
4+
o[prop] = safe;
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
function setSafeStringProp(o, prop, v) {
2+
// GOOD: `v == undefined` handles both `undefined` and `null`
3+
var safe = v == undefined? '': v;
4+
o[prop] = safe;
5+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
| global-module-definition.js:10:8:10:11 | Mod2 | This guard always evaluates to false. |
2+
| module-environment-detection.js:3:13:3:41 | typeof ... efined' | This guard always evaluates to true. |
3+
| module-environment-detection.js:15:9:15:37 | typeof ... efined' | This guard always evaluates to true. |
4+
| module-environment-detection.js:23:8:23:36 | typeof ... efined' | This guard always evaluates to true. |
5+
| tst2.js:4:12:4:35 | typeof ... efined" | This guard always evaluates to true. |
6+
| tst.js:13:10:13:11 | u_ | This guard always evaluates to false. |
7+
| tst.js:14:10:14:11 | n_ | This guard always evaluates to false. |
8+
| tst.js:15:10:15:11 | o_ | This guard always evaluates to true. |
9+
| tst.js:18:5:18:5 | u | This guard always evaluates to false. |
10+
| tst.js:19:5:19:5 | n | This guard always evaluates to false. |
11+
| tst.js:20:5:20:5 | o | This guard always evaluates to true. |
12+
| tst.js:23:5:23:5 | u | This guard always evaluates to false. |
13+
| tst.js:24:5:24:5 | n | This guard always evaluates to false. |
14+
| tst.js:25:5:25:5 | o | This guard always evaluates to true. |
15+
| tst.js:28:5:28:6 | !u | This guard always evaluates to true. |
16+
| tst.js:29:5:29:6 | !n | This guard always evaluates to true. |
17+
| tst.js:30:5:30:6 | !o | This guard always evaluates to false. |
18+
| tst.js:33:5:33:7 | !!u | This guard always evaluates to false. |
19+
| tst.js:34:5:34:7 | !!n | This guard always evaluates to false. |
20+
| tst.js:35:5:35:7 | !!o | This guard always evaluates to true. |
21+
| tst.js:38:5:38:18 | u != undefined | This guard always evaluates to false. |
22+
| tst.js:39:5:39:18 | n != undefined | This guard always evaluates to false. |
23+
| tst.js:40:5:40:18 | o != undefined | This guard always evaluates to true. |
24+
| tst.js:43:5:43:18 | u == undefined | This guard always evaluates to true. |
25+
| tst.js:44:5:44:18 | n == undefined | This guard always evaluates to true. |
26+
| tst.js:45:5:45:18 | o == undefined | This guard always evaluates to false. |
27+
| tst.js:48:5:48:19 | u === undefined | This guard always evaluates to true. |
28+
| tst.js:49:5:49:19 | n === undefined | This guard always evaluates to false. |
29+
| tst.js:50:5:50:19 | o === undefined | This guard always evaluates to false. |
30+
| tst.js:53:9:53:9 | u | This guard always evaluates to false. |
31+
| tst.js:56:9:56:9 | n | This guard always evaluates to false. |
32+
| tst.js:59:9:59:9 | o | This guard always evaluates to true. |
33+
| tst.js:66:5:66:5 | u | This guard always evaluates to false. |
34+
| tst.js:67:5:67:5 | n | This guard always evaluates to false. |
35+
| tst.js:68:5:68:5 | o | This guard always evaluates to true. |
36+
| tst.js:71:9:71:23 | u !== undefined | This guard always evaluates to false. |
37+
| tst.js:74:9:74:23 | n !== undefined | This guard always evaluates to true. |
38+
| tst.js:77:9:77:23 | o !== undefined | This guard always evaluates to true. |
39+
| tst.js:84:9:84:22 | u == undefined | This guard always evaluates to true. |
40+
| tst.js:85:9:85:22 | n == undefined | This guard always evaluates to true. |
41+
| tst.js:86:9:86:22 | o == undefined | This guard always evaluates to false. |
42+
| tst.js:89:9:89:22 | u != undefined | This guard always evaluates to false. |
43+
| tst.js:90:9:90:22 | n != undefined | This guard always evaluates to false. |
44+
| tst.js:91:9:91:22 | o != undefined | This guard always evaluates to true. |
45+
| tst.js:94:9:94:32 | typeof ... efined" | This guard always evaluates to true. |
46+
| tst.js:95:9:95:32 | typeof ... efined" | This guard always evaluates to false. |
47+
| tst.js:96:9:96:32 | typeof ... efined" | This guard always evaluates to false. |
48+
| tst.js:100:5:100:27 | typeof ... nction" | This guard always evaluates to true. |
49+
| tst.js:101:5:101:27 | typeof ... nction" | This guard always evaluates to false. |
50+
| tst.js:114:5:114:15 | empty_array | This guard always evaluates to true. |
51+
| tst.js:115:5:115:22 | pseudo_empty_array | This guard always evaluates to true. |
52+
| tst.js:116:5:116:19 | non_empty_array | This guard always evaluates to true. |
53+
| tst.js:124:6:124:20 | u !== undefined | This guard always evaluates to false. |
54+
| tst.js:124:25:124:34 | u !== null | This guard always evaluates to true. |
55+
| tst.js:125:5:125:19 | u !== undefined | This guard always evaluates to false. |
56+
| tst.js:125:24:125:33 | u !== null | This guard always evaluates to true. |
57+
| tst.js:127:5:127:18 | u != undefined | This guard always evaluates to false. |
58+
| tst.js:127:23:127:31 | u != null | This guard always evaluates to false. |
59+
| tst.js:127:23:127:31 | u != null | This guard always evaluates to true. |
60+
| tst.js:128:5:128:18 | u == undefined | This guard always evaluates to true. |
61+
| tst.js:128:23:128:31 | u == null | This guard always evaluates to false. |
62+
| tst.js:128:23:128:31 | u == null | This guard always evaluates to true. |
63+
| tst.js:129:5:129:19 | u !== undefined | This guard always evaluates to false. |
64+
| tst.js:129:24:129:33 | u !== null | This guard always evaluates to true. |
65+
| tst.js:130:5:130:22 | !(u === undefined) | This guard always evaluates to false. |
66+
| tst.js:130:27:130:39 | !(u === null) | This guard always evaluates to true. |
67+
| tst.js:131:5:131:19 | u === undefined | This guard always evaluates to true. |
68+
| tst.js:131:24:131:33 | u === null | This guard always evaluates to false. |
69+
| tst.js:132:7:132:21 | u === undefined | This guard always evaluates to true. |
70+
| tst.js:132:26:132:35 | u === null | This guard always evaluates to false. |
71+
| tst.js:133:5:133:22 | !(u === undefined) | This guard always evaluates to false. |
72+
| tst.js:133:27:133:36 | u !== null | This guard always evaluates to true. |
73+
| tst.js:135:5:135:18 | u == undefined | This guard always evaluates to true. |
74+
| tst.js:135:23:135:31 | u == null | This guard always evaluates to true. |
75+
| tst.js:138:24:138:33 | x === null | This guard always evaluates to false. |
76+
| tst.js:140:13:140:22 | x === null | This guard always evaluates to false. |
77+
| tst.js:156:23:156:31 | x != null | This guard always evaluates to true. |
78+
| tst.js:158:13:158:21 | x != null | This guard always evaluates to true. |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Expressions/UselessDefensiveProgramming.ql
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
var Mod1;
2+
(function (Mod1) {
3+
Mod1.p = 42;
4+
})(Mod1 || (Mod1 = {}));
5+
6+
(function(){
7+
var Mod2;
8+
(function (Mod2) {
9+
Mod2.p = 42;
10+
})(Mod2 || (Mod2 = {})); // NOT OK
11+
});

0 commit comments

Comments
 (0)