From d4dbe3bfb6c4556d2b059f8170458d8524514e4d Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Sun, 24 Feb 2019 21:30:18 +0000 Subject: [PATCH] JavaScript: Back out parsing of qualified XML identifiers. Their syntax conflicts with the proposed function-bind operator, which is more important to support. --- .../src/com/semmle/jcorn/CustomParser.java | 27 +- .../tests/e4x/output/trap/tst.js.trap | 404 +++++++++--------- javascript/ql/src/semmle/javascript/E4X.qll | 3 + .../Declarations/UnusedVariable/funbind.js | 6 + 4 files changed, 219 insertions(+), 221 deletions(-) create mode 100644 javascript/ql/test/query-tests/Declarations/UnusedVariable/funbind.js diff --git a/javascript/extractor/src/com/semmle/jcorn/CustomParser.java b/javascript/extractor/src/com/semmle/jcorn/CustomParser.java index d36b721e3bb..32704af783d 100644 --- a/javascript/extractor/src/com/semmle/jcorn/CustomParser.java +++ b/javascript/extractor/src/com/semmle/jcorn/CustomParser.java @@ -39,13 +39,12 @@ import com.semmle.js.ast.XMLAnyName; import com.semmle.js.ast.XMLAttributeSelector; import com.semmle.js.ast.XMLDotDotExpression; import com.semmle.js.ast.XMLFilterExpression; -import com.semmle.js.ast.XMLQualifiedIdentifier; import com.semmle.util.data.Either; import com.semmle.util.data.Pair; /** * An extension of the standard jcorn parser with support for Mozilla-specific - * language extension (most of JavaScript 1.8.5) and JScript language extensions. + * language extension (most of JavaScript 1.8.5 and E4X) and JScript language extensions. */ public class CustomParser extends FlowParser { public CustomParser(Options options, String input, int startPos) { @@ -460,27 +459,7 @@ public class CustomParser extends FlowParser { // attribute identifier return parseAttributeIdentifier(new SourceLocation(start)); } else { - return parsePossiblyQualifiedIdentifier(); - } - } - - /** - * Parse a wildcard identifier, a qualified identifier, or a plain identifier. - */ - protected Expression parsePossiblyQualifiedIdentifier() { - SourceLocation start = new SourceLocation(startLoc); - Expression res = parsePropertySelector(start); - - if (!this.eat(doubleColon)) - return res; - - if (this.eat(TokenType.bracketL)) { - Expression e = parseExpression(false, null); - this.expect(TokenType.bracketR); - return this.finishNode(new XMLQualifiedIdentifier(start, res, e, true)); - } else { - Expression e = parsePropertySelector(new SourceLocation(startLoc)); - return this.finishNode(new XMLQualifiedIdentifier(start, res, e, false)); + return parsePropertySelector(new SourceLocation(startLoc)); } } @@ -508,7 +487,7 @@ public class CustomParser extends FlowParser { this.expect(TokenType.bracketR); return this.finishNode(new XMLAttributeSelector(start, idx, true)); } else { - return this.finishNode(new XMLAttributeSelector(start, parsePossiblyQualifiedIdentifier(), false)); + return this.finishNode(new XMLAttributeSelector(start, parsePropertySelector(new SourceLocation(startLoc)), false)); } } diff --git a/javascript/extractor/tests/e4x/output/trap/tst.js.trap b/javascript/extractor/tests/e4x/output/trap/tst.js.trap index 3098274bcba..2d05785b803 100644 --- a/javascript/extractor/tests/e4x/output/trap/tst.js.trap +++ b/javascript/extractor/tests/e4x/output/trap/tst.js.trap @@ -686,277 +686,287 @@ stmts(#20231,2,#20001,4,"message ... gStyle;") hasLocation(#20231,#20011) stmtContainers(#20231,#20001) #20232=* -exprs(#20232,14,#20231,0,"message ... ngStyle") +exprs(#20232,97,#20231,0,"message ... ngStyle") #20233=@"loc,{#10000},5,1,5,28" locations_default(#20233,#10000,5,1,5,28) hasLocation(#20232,#20233) enclosingStmt(#20232,#20231) exprContainers(#20232,#20001) #20234=* -exprs(#20234,79,#20232,0,"message") -hasLocation(#20234,#20095) +exprs(#20234,14,#20232,0,"message.@soap") +#20235=@"loc,{#10000},5,1,5,13" +locations_default(#20235,#10000,5,1,5,13) +hasLocation(#20234,#20235) enclosingStmt(#20234,#20231) exprContainers(#20234,#20001) -literals("message","message",#20234) -#20235=@"var;{message};{#20000}" -variables(#20235,"message",#20000) -bind(#20234,#20235) #20236=* -exprs(#20236,109,#20232,1,"@soap::encodingStyle") -#20237=@"loc,{#10000},5,9,5,28" -locations_default(#20237,#10000,5,9,5,28) -hasLocation(#20236,#20237) +exprs(#20236,79,#20234,0,"message") +hasLocation(#20236,#20095) enclosingStmt(#20236,#20231) exprContainers(#20236,#20001) +literals("message","message",#20236) +#20237=@"var;{message};{#20000}" +variables(#20237,"message",#20000) +bind(#20236,#20237) #20238=* -exprs(#20238,112,#20236,0,"soap::encodingStyle") -#20239=@"loc,{#10000},5,10,5,28" -locations_default(#20239,#10000,5,10,5,28) +exprs(#20238,109,#20234,1,"@soap") +#20239=@"loc,{#10000},5,9,5,13" +locations_default(#20239,#10000,5,9,5,13) hasLocation(#20238,#20239) enclosingStmt(#20238,#20231) exprContainers(#20238,#20001) #20240=* -exprs(#20240,79,#20238,0,"soap") +exprs(#20240,0,#20238,0,"soap") hasLocation(#20240,#20101) enclosingStmt(#20240,#20231) exprContainers(#20240,#20001) literals("soap","soap",#20240) -#20241=@"var;{soap};{#20000}" -variables(#20241,"soap",#20000) -bind(#20240,#20241) -#20242=* -exprs(#20242,0,#20238,1,"encodingStyle") -hasLocation(#20242,#20105) -enclosingStmt(#20242,#20231) -exprContainers(#20242,#20001) -literals("encodingStyle","encodingStyle",#20242) +#20241=* +exprs(#20241,79,#20232,1,"encodingStyle") +hasLocation(#20241,#20105) +enclosingStmt(#20241,#20231) +exprContainers(#20241,#20001) +literals("encodingStyle","encodingStyle",#20241) +#20242=@"var;{encodingStyle};{#20000}" +variables(#20242,"encodingStyle",#20000) +bind(#20241,#20242) #20243=* stmts(#20243,2,#20001,5,"message.soap::Body;") hasLocation(#20243,#20013) stmtContainers(#20243,#20001) #20244=* -exprs(#20244,14,#20243,0,"message.soap::Body") +exprs(#20244,97,#20243,0,"message.soap::Body") #20245=@"loc,{#10000},6,1,6,18" locations_default(#20245,#10000,6,1,6,18) hasLocation(#20244,#20245) enclosingStmt(#20244,#20243) exprContainers(#20244,#20001) #20246=* -exprs(#20246,79,#20244,0,"message") -hasLocation(#20246,#20109) +exprs(#20246,14,#20244,0,"message.soap") +#20247=@"loc,{#10000},6,1,6,12" +locations_default(#20247,#10000,6,1,6,12) +hasLocation(#20246,#20247) enclosingStmt(#20246,#20243) exprContainers(#20246,#20001) -literals("message","message",#20246) -bind(#20246,#20235) -#20247=* -exprs(#20247,112,#20244,1,"soap::Body") -#20248=@"loc,{#10000},6,9,6,18" -locations_default(#20248,#10000,6,9,6,18) -hasLocation(#20247,#20248) -enclosingStmt(#20247,#20243) -exprContainers(#20247,#20001) +#20248=* +exprs(#20248,79,#20246,0,"message") +hasLocation(#20248,#20109) +enclosingStmt(#20248,#20243) +exprContainers(#20248,#20001) +literals("message","message",#20248) +bind(#20248,#20237) #20249=* -exprs(#20249,79,#20247,0,"soap") +exprs(#20249,0,#20246,1,"soap") hasLocation(#20249,#20113) enclosingStmt(#20249,#20243) exprContainers(#20249,#20001) literals("soap","soap",#20249) -bind(#20249,#20241) #20250=* -exprs(#20250,0,#20247,1,"Body") +exprs(#20250,79,#20244,1,"Body") hasLocation(#20250,#20117) enclosingStmt(#20250,#20243) exprContainers(#20250,#20001) literals("Body","Body",#20250) -#20251=* -stmts(#20251,2,#20001,6,"items.@[f()];") -hasLocation(#20251,#20015) -stmtContainers(#20251,#20001) +#20251=@"var;{Body};{#20000}" +variables(#20251,"Body",#20000) +bind(#20250,#20251) #20252=* -exprs(#20252,14,#20251,0,"items.@[f()]") -#20253=@"loc,{#10000},7,1,7,12" -locations_default(#20253,#10000,7,1,7,12) -hasLocation(#20252,#20253) -enclosingStmt(#20252,#20251) -exprContainers(#20252,#20001) -#20254=* -exprs(#20254,79,#20252,0,"items") -hasLocation(#20254,#20121) -enclosingStmt(#20254,#20251) -exprContainers(#20254,#20001) -literals("items","items",#20254) -bind(#20254,#20190) +stmts(#20252,2,#20001,6,"items.@[f()];") +hasLocation(#20252,#20015) +stmtContainers(#20252,#20001) +#20253=* +exprs(#20253,14,#20252,0,"items.@[f()]") +#20254=@"loc,{#10000},7,1,7,12" +locations_default(#20254,#10000,7,1,7,12) +hasLocation(#20253,#20254) +enclosingStmt(#20253,#20252) +exprContainers(#20253,#20001) #20255=* -exprs(#20255,110,#20252,1,"@[f()]") -#20256=@"loc,{#10000},7,7,7,12" -locations_default(#20256,#10000,7,7,7,12) -hasLocation(#20255,#20256) -enclosingStmt(#20255,#20251) +exprs(#20255,79,#20253,0,"items") +hasLocation(#20255,#20121) +enclosingStmt(#20255,#20252) exprContainers(#20255,#20001) -#20257=* -exprs(#20257,13,#20255,0,"f()") -#20258=@"loc,{#10000},7,9,7,11" -locations_default(#20258,#10000,7,9,7,11) -hasLocation(#20257,#20258) -enclosingStmt(#20257,#20251) -exprContainers(#20257,#20001) -#20259=* -exprs(#20259,79,#20257,-1,"f") -hasLocation(#20259,#20129) -enclosingStmt(#20259,#20251) -exprContainers(#20259,#20001) -literals("f","f",#20259) -#20260=@"var;{f};{#20000}" -variables(#20260,"f",#20000) -bind(#20259,#20260) -#20261=* -stmts(#20261,2,#20001,7,"message.soap::[g()];") -hasLocation(#20261,#20017) -stmtContainers(#20261,#20001) +literals("items","items",#20255) +bind(#20255,#20190) +#20256=* +exprs(#20256,110,#20253,1,"@[f()]") +#20257=@"loc,{#10000},7,7,7,12" +locations_default(#20257,#10000,7,7,7,12) +hasLocation(#20256,#20257) +enclosingStmt(#20256,#20252) +exprContainers(#20256,#20001) +#20258=* +exprs(#20258,13,#20256,0,"f()") +#20259=@"loc,{#10000},7,9,7,11" +locations_default(#20259,#10000,7,9,7,11) +hasLocation(#20258,#20259) +enclosingStmt(#20258,#20252) +exprContainers(#20258,#20001) +#20260=* +exprs(#20260,79,#20258,-1,"f") +hasLocation(#20260,#20129) +enclosingStmt(#20260,#20252) +exprContainers(#20260,#20001) +literals("f","f",#20260) +#20261=@"var;{f};{#20000}" +variables(#20261,"f",#20000) +bind(#20260,#20261) #20262=* -exprs(#20262,14,#20261,0,"message.soap::[g()]") -#20263=@"loc,{#10000},8,1,8,19" -locations_default(#20263,#10000,8,1,8,19) -hasLocation(#20262,#20263) -enclosingStmt(#20262,#20261) -exprContainers(#20262,#20001) -#20264=* -exprs(#20264,79,#20262,0,"message") -hasLocation(#20264,#20139) -enclosingStmt(#20264,#20261) -exprContainers(#20264,#20001) -literals("message","message",#20264) -bind(#20264,#20235) +stmts(#20262,2,#20001,7,"message.soap::[g()];") +hasLocation(#20262,#20017) +stmtContainers(#20262,#20001) +#20263=* +exprs(#20263,97,#20262,0,"message.soap::[g()]") +#20264=@"loc,{#10000},8,1,8,19" +locations_default(#20264,#10000,8,1,8,19) +hasLocation(#20263,#20264) +enclosingStmt(#20263,#20262) +exprContainers(#20263,#20001) #20265=* -exprs(#20265,113,#20262,1,"soap::[g()]") -#20266=@"loc,{#10000},8,9,8,19" -locations_default(#20266,#10000,8,9,8,19) +exprs(#20265,14,#20263,0,"message.soap") +#20266=@"loc,{#10000},8,1,8,12" +locations_default(#20266,#10000,8,1,8,12) hasLocation(#20265,#20266) -enclosingStmt(#20265,#20261) +enclosingStmt(#20265,#20262) exprContainers(#20265,#20001) #20267=* -exprs(#20267,79,#20265,0,"soap") -hasLocation(#20267,#20143) -enclosingStmt(#20267,#20261) +exprs(#20267,79,#20265,0,"message") +hasLocation(#20267,#20139) +enclosingStmt(#20267,#20262) exprContainers(#20267,#20001) -literals("soap","soap",#20267) -bind(#20267,#20241) +literals("message","message",#20267) +bind(#20267,#20237) #20268=* -exprs(#20268,13,#20265,1,"g()") -#20269=@"loc,{#10000},8,16,8,18" -locations_default(#20269,#10000,8,16,8,18) -hasLocation(#20268,#20269) -enclosingStmt(#20268,#20261) +exprs(#20268,0,#20265,1,"soap") +hasLocation(#20268,#20143) +enclosingStmt(#20268,#20262) exprContainers(#20268,#20001) -#20270=* -exprs(#20270,79,#20268,-1,"g") -hasLocation(#20270,#20149) -enclosingStmt(#20270,#20261) -exprContainers(#20270,#20001) -literals("g","g",#20270) -#20271=@"var;{g};{#20000}" -variables(#20271,"g",#20000) -bind(#20270,#20271) -#20272=* -stmts(#20272,18,#20001,8,"var e = ... ;") -#20273=@"loc,{#10000},10,1,13,9" -locations_default(#20273,#10000,10,1,13,9) -hasLocation(#20272,#20273) -stmtContainers(#20272,#20001) -#20274=* -exprs(#20274,64,#20272,0,"e = ") -#20275=@"loc,{#10000},10,5,13,8" -locations_default(#20275,#10000,10,5,13,8) -hasLocation(#20274,#20275) -enclosingStmt(#20274,#20272) -exprContainers(#20274,#20001) -#20276=* -exprs(#20276,78,#20274,0,"e") -hasLocation(#20276,#20161) -enclosingStmt(#20276,#20272) -exprContainers(#20276,#20001) -literals("e","e",#20276) -decl(#20276,#20185) +literals("soap","soap",#20268) +#20269=* +exprs(#20269,7,#20263,1,"[g()]") +#20270=@"loc,{#10000},8,15,8,19" +locations_default(#20270,#10000,8,15,8,19) +hasLocation(#20269,#20270) +enclosingStmt(#20269,#20262) +exprContainers(#20269,#20001) +#20271=* +exprs(#20271,13,#20269,0,"g()") +#20272=@"loc,{#10000},8,16,8,18" +locations_default(#20272,#10000,8,16,8,18) +hasLocation(#20271,#20272) +enclosingStmt(#20271,#20262) +exprContainers(#20271,#20001) +#20273=* +exprs(#20273,79,#20271,-1,"g") +hasLocation(#20273,#20149) +enclosingStmt(#20273,#20262) +exprContainers(#20273,#20001) +literals("g","g",#20273) +#20274=@"var;{g};{#20000}" +variables(#20274,"g",#20000) +bind(#20273,#20274) +arraySize(#20269,1) +#20275=* +stmts(#20275,18,#20001,8,"var e = ... ;") +#20276=@"loc,{#10000},10,1,13,9" +locations_default(#20276,#10000,10,1,13,9) +hasLocation(#20275,#20276) +stmtContainers(#20275,#20001) #20277=* -exprs(#20277,89,#20274,1,"") -#20278=@"loc,{#10000},10,9,13,8" -locations_default(#20278,#10000,10,9,13,8) +exprs(#20277,64,#20275,0,"e = ") +#20278=@"loc,{#10000},10,5,13,8" +locations_default(#20278,#10000,10,5,13,8) hasLocation(#20277,#20278) -enclosingStmt(#20277,#20272) +enclosingStmt(#20277,#20275) exprContainers(#20277,#20001) #20279=* -exprs(#20279,0,#20277,-1,"elt") -hasLocation(#20279,#20167) -enclosingStmt(#20279,#20272) +exprs(#20279,78,#20277,0,"e") +hasLocation(#20279,#20161) +enclosingStmt(#20279,#20275) exprContainers(#20279,#20001) -literals("elt","elt",#20279) +literals("e","e",#20279) +decl(#20279,#20185) #20280=* -exprs(#20280,4,#20277,-2,"\n ]]> - ",#20280) -#20281=* -entry_cfg_node(#20281,#20001) -#20282=@"loc,{#10000},1,1,1,0" -locations_default(#20282,#10000,1,1,1,0) -hasLocation(#20281,#20282) -#20283=* -exit_cfg_node(#20283,#20001) -hasLocation(#20283,#20183) -successor(#20272,#20276) + ",#20283) +#20284=* +entry_cfg_node(#20284,#20001) +#20285=@"loc,{#10000},1,1,1,0" +locations_default(#20285,#10000,1,1,1,0) +hasLocation(#20284,#20285) +#20286=* +exit_cfg_node(#20286,#20001) +hasLocation(#20286,#20183) +successor(#20275,#20279) +successor(#20283,#20280) +successor(#20282,#20283) successor(#20280,#20277) -successor(#20279,#20280) -successor(#20277,#20274) -successor(#20276,#20279) -successor(#20274,#20283) -successor(#20261,#20264) -successor(#20270,#20268) +successor(#20279,#20282) +successor(#20277,#20286) +successor(#20262,#20267) +successor(#20269,#20273) +successor(#20273,#20271) +successor(#20271,#20263) successor(#20268,#20265) -successor(#20267,#20270) -successor(#20265,#20262) -successor(#20264,#20267) -successor(#20262,#20272) -successor(#20251,#20254) -successor(#20259,#20257) -successor(#20257,#20255) -successor(#20255,#20252) -successor(#20254,#20259) -successor(#20252,#20261) -successor(#20243,#20246) -successor(#20250,#20247) -successor(#20249,#20250) -successor(#20247,#20244) -successor(#20246,#20249) -successor(#20244,#20251) -successor(#20231,#20234) -successor(#20242,#20238) -successor(#20240,#20242) -successor(#20238,#20236) -successor(#20236,#20232) -successor(#20234,#20240) +successor(#20267,#20268) +successor(#20265,#20269) +successor(#20263,#20275) +successor(#20252,#20255) +successor(#20260,#20258) +successor(#20258,#20256) +successor(#20256,#20253) +successor(#20255,#20260) +successor(#20253,#20262) +successor(#20243,#20248) +successor(#20250,#20244) +successor(#20249,#20246) +successor(#20248,#20249) +successor(#20246,#20250) +successor(#20244,#20252) +successor(#20231,#20236) +successor(#20241,#20232) +successor(#20240,#20238) +successor(#20238,#20234) +successor(#20236,#20240) +successor(#20234,#20241) successor(#20232,#20243) successor(#20210,#20215) successor(#20217,#20223) successor(#20224,#20219) successor(#20223,#20221) successor(#20221,#20224) -#20284=* -guard_node(#20284,1,#20219) -hasLocation(#20284,#20220) -successor(#20284,#20211) -#20285=* -guard_node(#20285,0,#20219) -hasLocation(#20285,#20220) -successor(#20285,#20229) -successor(#20219,#20284) -successor(#20219,#20285) +#20287=* +guard_node(#20287,1,#20219) +hasLocation(#20287,#20220) +successor(#20287,#20211) +#20288=* +guard_node(#20288,0,#20219) +hasLocation(#20288,#20220) +successor(#20288,#20229) +successor(#20219,#20287) +successor(#20219,#20288) successor(#20230,#20225) successor(#20229,#20227) successor(#20227,#20230) @@ -981,6 +991,6 @@ successor(#20193,#20191) successor(#20191,#20187) successor(#20189,#20193) successor(#20187,#20194) -successor(#20281,#20186) +successor(#20284,#20186) numlines(#10000,13,12,0) filetype(#10000,"javascript") diff --git a/javascript/ql/src/semmle/javascript/E4X.qll b/javascript/ql/src/semmle/javascript/E4X.qll index 3d06a96aa1b..df7a151be20 100644 --- a/javascript/ql/src/semmle/javascript/E4X.qll +++ b/javascript/ql/src/semmle/javascript/E4X.qll @@ -13,6 +13,9 @@ module E4X { /** * An E4X qualified identifier of the form `q::n` or `q::[expr]`. + * + * Note that qualified identifiers are not currently supported by the parser, so snapshots + * will not usually contain any. */ class XMLQualifiedIdentifier extends Expr, @e4x_xml_qualident { /** diff --git a/javascript/ql/test/query-tests/Declarations/UnusedVariable/funbind.js b/javascript/ql/test/query-tests/Declarations/UnusedVariable/funbind.js new file mode 100644 index 00000000000..b3210a08775 --- /dev/null +++ b/javascript/ql/test/query-tests/Declarations/UnusedVariable/funbind.js @@ -0,0 +1,6 @@ +function test(bar, e) { + let foo = bar; + e.target::foo::baz(); +} + +// semmle-extractor-options: --experimental \ No newline at end of file