JS: introduce 'Util::describeExpression'

This commit is contained in:
Esben Sparre Andreasen
2018-10-31 09:09:09 +01:00
parent b743ee4179
commit 4e54af3b41
5 changed files with 109 additions and 20 deletions

View File

@@ -1,3 +1,5 @@
import javascript
/**
* Provides general-purpose utility predicates.
*/
@@ -34,3 +36,36 @@ bindingset[str, maxLength, explanation]
string truncate(string str, int maxLength, string explanation) {
if str.length() > maxLength then result = str.prefix(maxLength) + explanation else result = str
}
/**
* Gets a string that describes `e`.
*/
string describeExpression(Expr e) {
if e instanceof InvokeExpr then
exists (string prefix, string suffix |
result = prefix + suffix |
( if e instanceof NewExpr then
prefix = "constructor call"
else if e instanceof MethodCallExpr then
prefix = "method call"
else
prefix = "call"
) and
(
if exists(e.(InvokeExpr).getCalleeName()) then
suffix = " to " + e.(InvokeExpr).getCalleeName()
else
suffix = ""
)
)
else if e instanceof Comparison then
result = "comparison"
else if e instanceof VarAccess then
result = "use of variable '" + e.(VarAccess).getName() + "'"
else if e instanceof PropAccess and exists (e.(PropAccess).getPropertyName()) then
result = "use of property '" + e.(PropAccess).getPropertyName() + "'"
else if e instanceof LogNotExpr then
result = "negation"
else
result = "expression"
}

View File

@@ -0,0 +1,36 @@
| tst.js:1:1:15:2 | (functi ... !'';\\n}) | expression |
| tst.js:1:2:15:1 | functio ... !'';\\n} | expression |
| tst.js:2:5:2:5 | v | use of variable 'v' |
| tst.js:3:5:3:5 | o | use of variable 'o' |
| tst.js:3:5:3:7 | o.m | use of property 'm' |
| tst.js:3:5:3:9 | o.m() | method call to m |
| tst.js:3:7:3:7 | m | expression |
| tst.js:4:5:4:5 | f | use of variable 'f' |
| tst.js:4:5:4:7 | f() | call to f |
| tst.js:5:5:5:5 | x | use of variable 'x' |
| tst.js:5:5:5:10 | x == y | comparison |
| tst.js:5:10:5:10 | y | use of variable 'y' |
| tst.js:6:5:6:5 | o | use of variable 'o' |
| tst.js:6:5:6:7 | o.p | use of property 'p' |
| tst.js:6:7:6:7 | p | expression |
| tst.js:7:5:7:11 | new K() | constructor call to K |
| tst.js:7:9:7:9 | K | use of variable 'K' |
| tst.js:8:5:8:5 | a | use of variable 'a' |
| tst.js:8:5:8:9 | a + b | expression |
| tst.js:8:9:8:9 | b | use of variable 'b' |
| tst.js:9:5:9:10 | new "" | constructor call |
| tst.js:9:9:9:10 | "" | expression |
| tst.js:10:5:10:6 | "" | expression |
| tst.js:10:5:10:8 | ""() | call |
| tst.js:11:5:11:5 | o | use of variable 'o' |
| tst.js:11:5:11:8 | o[x] | expression |
| tst.js:11:7:11:7 | x | use of variable 'x' |
| tst.js:12:5:12:5 | o | use of variable 'o' |
| tst.js:12:5:12:10 | o['x'] | use of property 'x' |
| tst.js:12:7:12:9 | 'x' | expression |
| tst.js:13:5:13:5 | o | use of variable 'o' |
| tst.js:13:5:13:10 | o['x'] | use of property 'x' |
| tst.js:13:5:13:12 | o['x']() | method call to x |
| tst.js:13:7:13:9 | 'x' | expression |
| tst.js:14:5:14:7 | !'' | negation |
| tst.js:14:6:14:7 | '' | expression |

View File

@@ -0,0 +1,4 @@
import semmle.javascript.Util
from Expr e
select e, describeExpression(e)

View File

@@ -1 +1,15 @@
// used by qltest to identify the language
(function() {
v;
o.m();
f();
x == y;
o.p;
new K();
a + b;
new "";
""();
o[x];
o['x'];
o['x']();
!'';
});

View File

@@ -1,22 +1,22 @@
| UselessConditional.js:5:7:5:12 | !lines | This expression always evaluates to false. |
| UselessConditional.js:12:34:12:79 | (v = ne ... k] = v) | This logical 'and' expression can be replaced with a comma expression. |
| UselessConditional.js:17:9:17:9 | a | Variable 'a' always evaluates to false here. |
| UselessConditional.js:18:9:18:9 | b | Variable 'b' always evaluates to false here. |
| UselessConditional.js:21:9:21:9 | a | Variable 'a' always evaluates to false here. |
| UselessConditional.js:22:9:22:9 | b | Variable 'b' always evaluates to false here. |
| UselessConditional.js:26:6:26:6 | x | Variable 'x' always evaluates to true here. |
| UselessConditional.js:27:7:27:13 | new X() | This expression always evaluates to true. |
| UselessConditional.js:28:7:28:7 | x | Variable 'x' always evaluates to true here. |
| UselessConditional.js:29:8:29:8 | x | Variable 'x' always evaluates to true here. |
| UselessConditional.js:30:8:30:14 | new X() | This expression always evaluates to true. |
| UselessConditional.js:33:7:33:7 | x | Variable 'x' always evaluates to false here. |
| UselessConditional.js:54:9:54:13 | known | Variable 'known' always evaluates to false here. |
| UselessConditional.js:60:9:60:15 | unknown | Variable 'unknown' always evaluates to false here. |
| UselessConditional.js:65:5:65:5 | x | Variable 'x' always evaluates to true here. |
| UselessConditional.js:76:13:76:13 | x | Variable 'x' always evaluates to true here. |
| UselessConditional.js:82:13:82:13 | x | Variable 'x' always evaluates to true here. |
| UselessConditional.js:17:9:17:9 | a | Use of variable 'a' always evaluates to false here. |
| UselessConditional.js:18:9:18:9 | b | Use of variable 'b' always evaluates to false here. |
| UselessConditional.js:21:9:21:9 | a | Use of variable 'a' always evaluates to false here. |
| UselessConditional.js:22:9:22:9 | b | Use of variable 'b' always evaluates to false here. |
| UselessConditional.js:26:6:26:6 | x | Use of variable 'x' always evaluates to true here. |
| UselessConditional.js:27:7:27:13 | new X() | This constructor call to X always evaluates to true. |
| UselessConditional.js:28:7:28:7 | x | Use of variable 'x' always evaluates to true here. |
| UselessConditional.js:29:8:29:8 | x | Use of variable 'x' always evaluates to true here. |
| UselessConditional.js:30:8:30:14 | new X() | This constructor call to X always evaluates to true. |
| UselessConditional.js:33:7:33:7 | x | Use of variable 'x' always evaluates to false here. |
| UselessConditional.js:54:9:54:13 | known | Use of variable 'known' always evaluates to false here. |
| UselessConditional.js:60:9:60:15 | unknown | Use of variable 'unknown' always evaluates to false here. |
| UselessConditional.js:65:5:65:5 | x | Use of variable 'x' always evaluates to true here. |
| UselessConditional.js:76:13:76:13 | x | Use of variable 'x' always evaluates to true here. |
| UselessConditional.js:82:13:82:13 | x | Use of variable 'x' always evaluates to true here. |
| UselessConditional.js:89:10:89:16 | x, true | This expression always evaluates to true. |
| UselessConditionalGood.js:58:12:58:13 | x2 | Variable 'x2' always evaluates to false here. |
| UselessConditionalGood.js:69:12:69:13 | xy | Variable 'xy' always evaluates to false here. |
| UselessConditionalGood.js:85:12:85:13 | xy | Variable 'xy' always evaluates to false here. |
| UselessConditionalGood.js:97:12:97:13 | xy | Variable 'xy' always evaluates to false here. |
| UselessConditionalGood.js:58:12:58:13 | x2 | Use of variable 'x2' always evaluates to false here. |
| UselessConditionalGood.js:69:12:69:13 | xy | Use of variable 'xy' always evaluates to false here. |
| UselessConditionalGood.js:85:12:85:13 | xy | Use of variable 'xy' always evaluates to false here. |
| UselessConditionalGood.js:97:12:97:13 | xy | Use of variable 'xy' always evaluates to false here. |