Merge pull request #4282 from erik-krogh/es2021

Approved by esbena
This commit is contained in:
CodeQL CI
2020-09-22 05:34:35 -07:00
committed by GitHub
28 changed files with 1167 additions and 45 deletions

View File

@@ -20,6 +20,7 @@
- [underscore](https://www.npmjs.com/package/underscore)
* Analyzing files with the ".cjs" extension is now supported.
* ES2021 features are now supported.
## New queries

View File

@@ -531,9 +531,14 @@ public class Parser {
int next2 = charAt(this.pos + 2);
if (this.options.esnext()) {
if (next == '.' && !('0' <= next2 && next2 <= '9')) // '?.', but not '?.X' where X is a digit
return this.finishOp(TokenType.questiondot, 2);
if (next == '?') // '??'
return this.finishOp(TokenType.questionquestion, 2);
return this.finishOp(TokenType.questiondot, 2);
if (next == '?') { // '??'
if (next2 == '=') { // ??=
return this.finishOp(TokenType.assign, 3);
}
return this.finishOp(TokenType.questionquestion, 2);
}
}
return this.finishOp(TokenType.question, 1);
}
@@ -566,8 +571,11 @@ public class Parser {
private Token readToken_pipe_amp(int code) { // '|&'
int next = charAt(this.pos + 1);
if (next == code)
int next2 = charAt(this.pos + 2);
if (next == code) { // && ||
if (next2 == 61) return this.finishOp(TokenType.assign, 3); // &&= ||=
return this.finishOp(code == 124 ? TokenType.logicalOR : TokenType.logicalAND, 2);
}
if (next == 61) return this.finishOp(TokenType.assign, 2);
return this.finishOp(code == 124 ? TokenType.bitwiseOR : TokenType.bitwiseAND, 1);
}
@@ -709,8 +717,8 @@ public class Parser {
case 42: // '%*'
return this.readToken_mult_modulo_exp(code);
case 124:
case 38: // '|&'
case 124: // '|'
case 38: // '&'
return this.readToken_pipe_amp(code);
case 94: // '^'

View File

@@ -43,7 +43,7 @@ public class Main {
* A version identifier that should be updated every time the extractor changes in such a way that
* it may produce different tuples for the same file under the same {@link ExtractorConfig}.
*/
public static final String EXTRACTOR_VERSION = "2020-09-12";
public static final String EXTRACTOR_VERSION = "2020-09-17";
public static final Pattern NEWLINE = Pattern.compile("\n");

View File

@@ -0,0 +1,9 @@
var x = 1;
var y = 2;
var foo = x && y;
var bar = x &&= y;
console.log(x); // 2
x &&= y;
x ||= y;
x ??= y;

View File

@@ -0,0 +1,8 @@
1_000_000_000 // Ah, so a billion
101_475_938.38 // And this is hundreds of millions
let fee = 123_00; // $123 (12300 cents, apparently)
let fee = 12_300; // $12,300 (woah, that fee!)
let amount = 12345_00; // 12,345 (1234500 cents, apparently)
let amount = 123_4500; // 123.45 (4-fixed financial)
let amount = 1_234_500; // 1,234,500

View File

@@ -0,0 +1,3 @@
{
"experimental": true
}

View File

@@ -0,0 +1,633 @@
#10000=@"/assign.js;sourcefile"
files(#10000,"/assign.js","assign","js",0)
#10001=@"/;folder"
folders(#10001,"/","")
containerparent(#10001,#10000)
#10002=@"loc,{#10000},0,0,0,0"
locations_default(#10002,#10000,0,0,0,0)
hasLocation(#10000,#10002)
#20000=@"global_scope"
scopes(#20000,0)
#20001=@"script;{#10000},1,1"
#20002=*
comments(#20002,0,#20001," 2","// 2")
#20003=@"loc,{#10000},5,17,5,20"
locations_default(#20003,#10000,5,17,5,20)
hasLocation(#20002,#20003)
#20004=*
lines(#20004,#20001,"var x = 1;","
")
#20005=@"loc,{#10000},1,1,1,10"
locations_default(#20005,#10000,1,1,1,10)
hasLocation(#20004,#20005)
#20006=*
lines(#20006,#20001,"var y = 2;","
")
#20007=@"loc,{#10000},2,1,2,10"
locations_default(#20007,#10000,2,1,2,10)
hasLocation(#20006,#20007)
#20008=*
lines(#20008,#20001,"var foo = x && y;","
")
#20009=@"loc,{#10000},3,1,3,17"
locations_default(#20009,#10000,3,1,3,17)
hasLocation(#20008,#20009)
#20010=*
lines(#20010,#20001,"var bar = x &&= y;","
")
#20011=@"loc,{#10000},4,1,4,18"
locations_default(#20011,#10000,4,1,4,18)
hasLocation(#20010,#20011)
#20012=*
lines(#20012,#20001,"console.log(x); // 2","
")
#20013=@"loc,{#10000},5,1,5,20"
locations_default(#20013,#10000,5,1,5,20)
hasLocation(#20012,#20013)
#20014=*
lines(#20014,#20001,"","
")
#20015=@"loc,{#10000},6,1,6,0"
locations_default(#20015,#10000,6,1,6,0)
hasLocation(#20014,#20015)
#20016=*
lines(#20016,#20001,"x &&= y;","
")
#20017=@"loc,{#10000},7,1,7,8"
locations_default(#20017,#10000,7,1,7,8)
hasLocation(#20016,#20017)
#20018=*
lines(#20018,#20001,"x ||= y;","
")
#20019=@"loc,{#10000},8,1,8,8"
locations_default(#20019,#10000,8,1,8,8)
hasLocation(#20018,#20019)
#20020=*
lines(#20020,#20001,"x ??= y;","
")
#20021=@"loc,{#10000},9,1,9,8"
locations_default(#20021,#10000,9,1,9,8)
hasLocation(#20020,#20021)
numlines(#20001,9,8,1)
#20022=*
tokeninfo(#20022,7,#20001,0,"var")
#20023=@"loc,{#10000},1,1,1,3"
locations_default(#20023,#10000,1,1,1,3)
hasLocation(#20022,#20023)
#20024=*
tokeninfo(#20024,6,#20001,1,"x")
#20025=@"loc,{#10000},1,5,1,5"
locations_default(#20025,#10000,1,5,1,5)
hasLocation(#20024,#20025)
#20026=*
tokeninfo(#20026,8,#20001,2,"=")
#20027=@"loc,{#10000},1,7,1,7"
locations_default(#20027,#10000,1,7,1,7)
hasLocation(#20026,#20027)
#20028=*
tokeninfo(#20028,3,#20001,3,"1")
#20029=@"loc,{#10000},1,9,1,9"
locations_default(#20029,#10000,1,9,1,9)
hasLocation(#20028,#20029)
#20030=*
tokeninfo(#20030,8,#20001,4,";")
#20031=@"loc,{#10000},1,10,1,10"
locations_default(#20031,#10000,1,10,1,10)
hasLocation(#20030,#20031)
#20032=*
tokeninfo(#20032,7,#20001,5,"var")
#20033=@"loc,{#10000},2,1,2,3"
locations_default(#20033,#10000,2,1,2,3)
hasLocation(#20032,#20033)
#20034=*
tokeninfo(#20034,6,#20001,6,"y")
#20035=@"loc,{#10000},2,5,2,5"
locations_default(#20035,#10000,2,5,2,5)
hasLocation(#20034,#20035)
#20036=*
tokeninfo(#20036,8,#20001,7,"=")
#20037=@"loc,{#10000},2,7,2,7"
locations_default(#20037,#10000,2,7,2,7)
hasLocation(#20036,#20037)
#20038=*
tokeninfo(#20038,3,#20001,8,"2")
#20039=@"loc,{#10000},2,9,2,9"
locations_default(#20039,#10000,2,9,2,9)
hasLocation(#20038,#20039)
#20040=*
tokeninfo(#20040,8,#20001,9,";")
#20041=@"loc,{#10000},2,10,2,10"
locations_default(#20041,#10000,2,10,2,10)
hasLocation(#20040,#20041)
#20042=*
tokeninfo(#20042,7,#20001,10,"var")
#20043=@"loc,{#10000},3,1,3,3"
locations_default(#20043,#10000,3,1,3,3)
hasLocation(#20042,#20043)
#20044=*
tokeninfo(#20044,6,#20001,11,"foo")
#20045=@"loc,{#10000},3,5,3,7"
locations_default(#20045,#10000,3,5,3,7)
hasLocation(#20044,#20045)
#20046=*
tokeninfo(#20046,8,#20001,12,"=")
#20047=@"loc,{#10000},3,9,3,9"
locations_default(#20047,#10000,3,9,3,9)
hasLocation(#20046,#20047)
#20048=*
tokeninfo(#20048,6,#20001,13,"x")
#20049=@"loc,{#10000},3,11,3,11"
locations_default(#20049,#10000,3,11,3,11)
hasLocation(#20048,#20049)
#20050=*
tokeninfo(#20050,8,#20001,14,"&&")
#20051=@"loc,{#10000},3,13,3,14"
locations_default(#20051,#10000,3,13,3,14)
hasLocation(#20050,#20051)
#20052=*
tokeninfo(#20052,6,#20001,15,"y")
#20053=@"loc,{#10000},3,16,3,16"
locations_default(#20053,#10000,3,16,3,16)
hasLocation(#20052,#20053)
#20054=*
tokeninfo(#20054,8,#20001,16,";")
#20055=@"loc,{#10000},3,17,3,17"
locations_default(#20055,#10000,3,17,3,17)
hasLocation(#20054,#20055)
#20056=*
tokeninfo(#20056,7,#20001,17,"var")
#20057=@"loc,{#10000},4,1,4,3"
locations_default(#20057,#10000,4,1,4,3)
hasLocation(#20056,#20057)
#20058=*
tokeninfo(#20058,6,#20001,18,"bar")
#20059=@"loc,{#10000},4,5,4,7"
locations_default(#20059,#10000,4,5,4,7)
hasLocation(#20058,#20059)
#20060=*
tokeninfo(#20060,8,#20001,19,"=")
#20061=@"loc,{#10000},4,9,4,9"
locations_default(#20061,#10000,4,9,4,9)
hasLocation(#20060,#20061)
#20062=*
tokeninfo(#20062,6,#20001,20,"x")
#20063=@"loc,{#10000},4,11,4,11"
locations_default(#20063,#10000,4,11,4,11)
hasLocation(#20062,#20063)
#20064=*
tokeninfo(#20064,8,#20001,21,"&&=")
#20065=@"loc,{#10000},4,13,4,15"
locations_default(#20065,#10000,4,13,4,15)
hasLocation(#20064,#20065)
#20066=*
tokeninfo(#20066,6,#20001,22,"y")
#20067=@"loc,{#10000},4,17,4,17"
locations_default(#20067,#10000,4,17,4,17)
hasLocation(#20066,#20067)
#20068=*
tokeninfo(#20068,8,#20001,23,";")
#20069=@"loc,{#10000},4,18,4,18"
locations_default(#20069,#10000,4,18,4,18)
hasLocation(#20068,#20069)
#20070=*
tokeninfo(#20070,6,#20001,24,"console")
#20071=@"loc,{#10000},5,1,5,7"
locations_default(#20071,#10000,5,1,5,7)
hasLocation(#20070,#20071)
#20072=*
tokeninfo(#20072,8,#20001,25,".")
#20073=@"loc,{#10000},5,8,5,8"
locations_default(#20073,#10000,5,8,5,8)
hasLocation(#20072,#20073)
#20074=*
tokeninfo(#20074,6,#20001,26,"log")
#20075=@"loc,{#10000},5,9,5,11"
locations_default(#20075,#10000,5,9,5,11)
hasLocation(#20074,#20075)
#20076=*
tokeninfo(#20076,8,#20001,27,"(")
#20077=@"loc,{#10000},5,12,5,12"
locations_default(#20077,#10000,5,12,5,12)
hasLocation(#20076,#20077)
#20078=*
tokeninfo(#20078,6,#20001,28,"x")
#20079=@"loc,{#10000},5,13,5,13"
locations_default(#20079,#10000,5,13,5,13)
hasLocation(#20078,#20079)
#20080=*
tokeninfo(#20080,8,#20001,29,")")
#20081=@"loc,{#10000},5,14,5,14"
locations_default(#20081,#10000,5,14,5,14)
hasLocation(#20080,#20081)
#20082=*
tokeninfo(#20082,8,#20001,30,";")
#20083=@"loc,{#10000},5,15,5,15"
locations_default(#20083,#10000,5,15,5,15)
hasLocation(#20082,#20083)
#20084=*
tokeninfo(#20084,6,#20001,31,"x")
#20085=@"loc,{#10000},7,1,7,1"
locations_default(#20085,#10000,7,1,7,1)
hasLocation(#20084,#20085)
next_token(#20002,#20084)
#20086=*
tokeninfo(#20086,8,#20001,32,"&&=")
#20087=@"loc,{#10000},7,3,7,5"
locations_default(#20087,#10000,7,3,7,5)
hasLocation(#20086,#20087)
#20088=*
tokeninfo(#20088,6,#20001,33,"y")
#20089=@"loc,{#10000},7,7,7,7"
locations_default(#20089,#10000,7,7,7,7)
hasLocation(#20088,#20089)
#20090=*
tokeninfo(#20090,8,#20001,34,";")
#20091=@"loc,{#10000},7,8,7,8"
locations_default(#20091,#10000,7,8,7,8)
hasLocation(#20090,#20091)
#20092=*
tokeninfo(#20092,6,#20001,35,"x")
#20093=@"loc,{#10000},8,1,8,1"
locations_default(#20093,#10000,8,1,8,1)
hasLocation(#20092,#20093)
#20094=*
tokeninfo(#20094,8,#20001,36,"||=")
#20095=@"loc,{#10000},8,3,8,5"
locations_default(#20095,#10000,8,3,8,5)
hasLocation(#20094,#20095)
#20096=*
tokeninfo(#20096,6,#20001,37,"y")
#20097=@"loc,{#10000},8,7,8,7"
locations_default(#20097,#10000,8,7,8,7)
hasLocation(#20096,#20097)
#20098=*
tokeninfo(#20098,8,#20001,38,";")
#20099=@"loc,{#10000},8,8,8,8"
locations_default(#20099,#10000,8,8,8,8)
hasLocation(#20098,#20099)
#20100=*
tokeninfo(#20100,6,#20001,39,"x")
#20101=@"loc,{#10000},9,1,9,1"
locations_default(#20101,#10000,9,1,9,1)
hasLocation(#20100,#20101)
#20102=*
tokeninfo(#20102,8,#20001,40,"??=")
#20103=@"loc,{#10000},9,3,9,5"
locations_default(#20103,#10000,9,3,9,5)
hasLocation(#20102,#20103)
#20104=*
tokeninfo(#20104,6,#20001,41,"y")
#20105=@"loc,{#10000},9,7,9,7"
locations_default(#20105,#10000,9,7,9,7)
hasLocation(#20104,#20105)
#20106=*
tokeninfo(#20106,8,#20001,42,";")
#20107=@"loc,{#10000},9,8,9,8"
locations_default(#20107,#10000,9,8,9,8)
hasLocation(#20106,#20107)
#20108=*
tokeninfo(#20108,0,#20001,43,"")
#20109=@"loc,{#10000},10,1,10,0"
locations_default(#20109,#10000,10,1,10,0)
hasLocation(#20108,#20109)
toplevels(#20001,0)
#20110=@"loc,{#10000},1,1,10,0"
locations_default(#20110,#10000,1,1,10,0)
hasLocation(#20001,#20110)
#20111=@"var;{x};{#20000}"
variables(#20111,"x",#20000)
#20112=@"var;{y};{#20000}"
variables(#20112,"y",#20000)
#20113=@"var;{foo};{#20000}"
variables(#20113,"foo",#20000)
#20114=@"var;{bar};{#20000}"
variables(#20114,"bar",#20000)
#20115=*
stmts(#20115,18,#20001,0,"var x = 1;")
hasLocation(#20115,#20005)
stmt_containers(#20115,#20001)
#20116=*
exprs(#20116,64,#20115,0,"x = 1")
#20117=@"loc,{#10000},1,5,1,9"
locations_default(#20117,#10000,1,5,1,9)
hasLocation(#20116,#20117)
enclosing_stmt(#20116,#20115)
expr_containers(#20116,#20001)
#20118=*
exprs(#20118,78,#20116,0,"x")
hasLocation(#20118,#20025)
enclosing_stmt(#20118,#20115)
expr_containers(#20118,#20001)
literals("x","x",#20118)
decl(#20118,#20111)
#20119=*
exprs(#20119,3,#20116,1,"1")
hasLocation(#20119,#20029)
enclosing_stmt(#20119,#20115)
expr_containers(#20119,#20001)
literals("1","1",#20119)
#20120=*
stmts(#20120,18,#20001,1,"var y = 2;")
hasLocation(#20120,#20007)
stmt_containers(#20120,#20001)
#20121=*
exprs(#20121,64,#20120,0,"y = 2")
#20122=@"loc,{#10000},2,5,2,9"
locations_default(#20122,#10000,2,5,2,9)
hasLocation(#20121,#20122)
enclosing_stmt(#20121,#20120)
expr_containers(#20121,#20001)
#20123=*
exprs(#20123,78,#20121,0,"y")
hasLocation(#20123,#20035)
enclosing_stmt(#20123,#20120)
expr_containers(#20123,#20001)
literals("y","y",#20123)
decl(#20123,#20112)
#20124=*
exprs(#20124,3,#20121,1,"2")
hasLocation(#20124,#20039)
enclosing_stmt(#20124,#20120)
expr_containers(#20124,#20001)
literals("2","2",#20124)
#20125=*
stmts(#20125,18,#20001,2,"var foo = x && y;")
hasLocation(#20125,#20009)
stmt_containers(#20125,#20001)
#20126=*
exprs(#20126,64,#20125,0,"foo = x && y")
#20127=@"loc,{#10000},3,5,3,16"
locations_default(#20127,#10000,3,5,3,16)
hasLocation(#20126,#20127)
enclosing_stmt(#20126,#20125)
expr_containers(#20126,#20001)
#20128=*
exprs(#20128,78,#20126,0,"foo")
hasLocation(#20128,#20045)
enclosing_stmt(#20128,#20125)
expr_containers(#20128,#20001)
literals("foo","foo",#20128)
decl(#20128,#20113)
#20129=*
exprs(#20129,44,#20126,1,"x && y")
#20130=@"loc,{#10000},3,11,3,16"
locations_default(#20130,#10000,3,11,3,16)
hasLocation(#20129,#20130)
enclosing_stmt(#20129,#20125)
expr_containers(#20129,#20001)
#20131=*
exprs(#20131,79,#20129,0,"x")
hasLocation(#20131,#20049)
enclosing_stmt(#20131,#20125)
expr_containers(#20131,#20001)
literals("x","x",#20131)
bind(#20131,#20111)
#20132=*
exprs(#20132,79,#20129,1,"y")
hasLocation(#20132,#20053)
enclosing_stmt(#20132,#20125)
expr_containers(#20132,#20001)
literals("y","y",#20132)
bind(#20132,#20112)
#20133=*
stmts(#20133,18,#20001,3,"var bar = x &&= y;")
hasLocation(#20133,#20011)
stmt_containers(#20133,#20001)
#20134=*
exprs(#20134,64,#20133,0,"bar = x &&= y")
#20135=@"loc,{#10000},4,5,4,17"
locations_default(#20135,#10000,4,5,4,17)
hasLocation(#20134,#20135)
enclosing_stmt(#20134,#20133)
expr_containers(#20134,#20001)
#20136=*
exprs(#20136,78,#20134,0,"bar")
hasLocation(#20136,#20059)
enclosing_stmt(#20136,#20133)
expr_containers(#20136,#20001)
literals("bar","bar",#20136)
decl(#20136,#20114)
#20137=*
exprs(#20137,116,#20134,1,"x &&= y")
#20138=@"loc,{#10000},4,11,4,17"
locations_default(#20138,#10000,4,11,4,17)
hasLocation(#20137,#20138)
enclosing_stmt(#20137,#20133)
expr_containers(#20137,#20001)
#20139=*
exprs(#20139,79,#20137,0,"x")
hasLocation(#20139,#20063)
enclosing_stmt(#20139,#20133)
expr_containers(#20139,#20001)
literals("x","x",#20139)
bind(#20139,#20111)
#20140=*
exprs(#20140,79,#20137,1,"y")
hasLocation(#20140,#20067)
enclosing_stmt(#20140,#20133)
expr_containers(#20140,#20001)
literals("y","y",#20140)
bind(#20140,#20112)
#20141=*
stmts(#20141,2,#20001,4,"console.log(x);")
#20142=@"loc,{#10000},5,1,5,15"
locations_default(#20142,#10000,5,1,5,15)
hasLocation(#20141,#20142)
stmt_containers(#20141,#20001)
#20143=*
exprs(#20143,13,#20141,0,"console.log(x)")
#20144=@"loc,{#10000},5,1,5,14"
locations_default(#20144,#10000,5,1,5,14)
hasLocation(#20143,#20144)
enclosing_stmt(#20143,#20141)
expr_containers(#20143,#20001)
#20145=*
exprs(#20145,14,#20143,-1,"console.log")
#20146=@"loc,{#10000},5,1,5,11"
locations_default(#20146,#10000,5,1,5,11)
hasLocation(#20145,#20146)
enclosing_stmt(#20145,#20141)
expr_containers(#20145,#20001)
#20147=*
exprs(#20147,79,#20145,0,"console")
hasLocation(#20147,#20071)
enclosing_stmt(#20147,#20141)
expr_containers(#20147,#20001)
literals("console","console",#20147)
#20148=@"var;{console};{#20000}"
variables(#20148,"console",#20000)
bind(#20147,#20148)
#20149=*
exprs(#20149,0,#20145,1,"log")
hasLocation(#20149,#20075)
enclosing_stmt(#20149,#20141)
expr_containers(#20149,#20001)
literals("log","log",#20149)
#20150=*
exprs(#20150,79,#20143,0,"x")
hasLocation(#20150,#20079)
enclosing_stmt(#20150,#20141)
expr_containers(#20150,#20001)
literals("x","x",#20150)
bind(#20150,#20111)
#20151=*
stmts(#20151,2,#20001,5,"x &&= y;")
hasLocation(#20151,#20017)
stmt_containers(#20151,#20001)
#20152=*
exprs(#20152,116,#20151,0,"x &&= y")
#20153=@"loc,{#10000},7,1,7,7"
locations_default(#20153,#10000,7,1,7,7)
hasLocation(#20152,#20153)
enclosing_stmt(#20152,#20151)
expr_containers(#20152,#20001)
#20154=*
exprs(#20154,79,#20152,0,"x")
hasLocation(#20154,#20085)
enclosing_stmt(#20154,#20151)
expr_containers(#20154,#20001)
literals("x","x",#20154)
bind(#20154,#20111)
#20155=*
exprs(#20155,79,#20152,1,"y")
hasLocation(#20155,#20089)
enclosing_stmt(#20155,#20151)
expr_containers(#20155,#20001)
literals("y","y",#20155)
bind(#20155,#20112)
#20156=*
stmts(#20156,2,#20001,6,"x ||= y;")
hasLocation(#20156,#20019)
stmt_containers(#20156,#20001)
#20157=*
exprs(#20157,117,#20156,0,"x ||= y")
#20158=@"loc,{#10000},8,1,8,7"
locations_default(#20158,#10000,8,1,8,7)
hasLocation(#20157,#20158)
enclosing_stmt(#20157,#20156)
expr_containers(#20157,#20001)
#20159=*
exprs(#20159,79,#20157,0,"x")
hasLocation(#20159,#20093)
enclosing_stmt(#20159,#20156)
expr_containers(#20159,#20001)
literals("x","x",#20159)
bind(#20159,#20111)
#20160=*
exprs(#20160,79,#20157,1,"y")
hasLocation(#20160,#20097)
enclosing_stmt(#20160,#20156)
expr_containers(#20160,#20001)
literals("y","y",#20160)
bind(#20160,#20112)
#20161=*
stmts(#20161,2,#20001,7,"x ??= y;")
hasLocation(#20161,#20021)
stmt_containers(#20161,#20001)
#20162=*
exprs(#20162,118,#20161,0,"x ??= y")
#20163=@"loc,{#10000},9,1,9,7"
locations_default(#20163,#10000,9,1,9,7)
hasLocation(#20162,#20163)
enclosing_stmt(#20162,#20161)
expr_containers(#20162,#20001)
#20164=*
exprs(#20164,79,#20162,0,"x")
hasLocation(#20164,#20101)
enclosing_stmt(#20164,#20161)
expr_containers(#20164,#20001)
literals("x","x",#20164)
bind(#20164,#20111)
#20165=*
exprs(#20165,79,#20162,1,"y")
hasLocation(#20165,#20105)
enclosing_stmt(#20165,#20161)
expr_containers(#20165,#20001)
literals("y","y",#20165)
bind(#20165,#20112)
#20166=*
entry_cfg_node(#20166,#20001)
#20167=@"loc,{#10000},1,1,1,0"
locations_default(#20167,#10000,1,1,1,0)
hasLocation(#20166,#20167)
#20168=*
exit_cfg_node(#20168,#20001)
hasLocation(#20168,#20109)
successor(#20161,#20164)
successor(#20164,#20165)
successor(#20164,#20168)
successor(#20165,#20164)
successor(#20162,#20168)
successor(#20156,#20159)
#20169=*
guard_node(#20169,1,#20159)
hasLocation(#20169,#20093)
successor(#20169,#20161)
#20170=*
guard_node(#20170,0,#20159)
hasLocation(#20170,#20093)
successor(#20170,#20160)
successor(#20159,#20169)
successor(#20159,#20170)
successor(#20160,#20159)
successor(#20157,#20161)
successor(#20151,#20154)
#20171=*
guard_node(#20171,1,#20154)
hasLocation(#20171,#20085)
successor(#20171,#20155)
#20172=*
guard_node(#20172,0,#20154)
hasLocation(#20172,#20085)
successor(#20172,#20156)
successor(#20154,#20171)
successor(#20154,#20172)
successor(#20155,#20154)
successor(#20152,#20156)
successor(#20141,#20147)
successor(#20150,#20143)
successor(#20149,#20145)
successor(#20147,#20149)
successor(#20145,#20150)
successor(#20143,#20151)
successor(#20133,#20136)
#20173=*
guard_node(#20173,1,#20139)
hasLocation(#20173,#20063)
successor(#20173,#20140)
#20174=*
guard_node(#20174,0,#20139)
hasLocation(#20174,#20063)
successor(#20174,#20134)
successor(#20139,#20173)
successor(#20139,#20174)
successor(#20140,#20139)
successor(#20137,#20134)
successor(#20136,#20139)
successor(#20134,#20141)
successor(#20125,#20128)
successor(#20129,#20131)
#20175=*
guard_node(#20175,1,#20131)
hasLocation(#20175,#20049)
successor(#20175,#20132)
#20176=*
guard_node(#20176,0,#20131)
hasLocation(#20176,#20049)
successor(#20176,#20126)
successor(#20131,#20175)
successor(#20131,#20176)
successor(#20132,#20126)
successor(#20128,#20129)
successor(#20126,#20133)
successor(#20120,#20123)
successor(#20124,#20121)
successor(#20123,#20124)
successor(#20121,#20125)
successor(#20115,#20118)
successor(#20119,#20116)
successor(#20118,#20119)
successor(#20116,#20120)
successor(#20166,#20115)
numlines(#10000,9,8,1)
filetype(#10000,"javascript")

View File

@@ -0,0 +1,435 @@
#10000=@"/numeric.js;sourcefile"
files(#10000,"/numeric.js","numeric","js",0)
#10001=@"/;folder"
folders(#10001,"/","")
containerparent(#10001,#10000)
#10002=@"loc,{#10000},0,0,0,0"
locations_default(#10002,#10000,0,0,0,0)
hasLocation(#10000,#10002)
#20000=@"global_scope"
scopes(#20000,0)
#20001=@"script;{#10000},1,1"
#20002=*
comments(#20002,0,#20001," Ah, so a billion","// Ah, so a billion")
#20003=@"loc,{#10000},1,25,1,43"
locations_default(#20003,#10000,1,25,1,43)
hasLocation(#20002,#20003)
#20004=*
comments(#20004,0,#20001," And this is hundreds of millions","// And ... illions")
#20005=@"loc,{#10000},2,25,2,59"
locations_default(#20005,#10000,2,25,2,59)
hasLocation(#20004,#20005)
#20006=*
comments(#20006,0,#20001," $123 (12300 cents, apparently)","// $123 ... rently)")
#20007=@"loc,{#10000},4,25,4,57"
locations_default(#20007,#10000,4,25,4,57)
hasLocation(#20006,#20007)
#20008=*
comments(#20008,0,#20001," $12,300 (woah, that fee!)","// $12, ... t fee!)")
#20009=@"loc,{#10000},5,25,5,52"
locations_default(#20009,#10000,5,25,5,52)
hasLocation(#20008,#20009)
#20010=*
comments(#20010,0,#20001," 12,345 (1234500 cents, apparently)","// 12,3 ... rently)")
#20011=@"loc,{#10000},6,25,6,61"
locations_default(#20011,#10000,6,25,6,61)
hasLocation(#20010,#20011)
#20012=*
comments(#20012,0,#20001," 123.45 (4-fixed financial)","// 123. ... ancial)")
#20013=@"loc,{#10000},7,25,7,53"
locations_default(#20013,#10000,7,25,7,53)
hasLocation(#20012,#20013)
#20014=*
comments(#20014,0,#20001," 1,234,500","// 1,234,500")
#20015=@"loc,{#10000},8,25,8,36"
locations_default(#20015,#10000,8,25,8,36)
hasLocation(#20014,#20015)
#20016=*
lines(#20016,#20001,"1_000_000_000 // Ah, so a billion","
")
#20017=@"loc,{#10000},1,1,1,43"
locations_default(#20017,#10000,1,1,1,43)
hasLocation(#20016,#20017)
#20018=*
lines(#20018,#20001,"101_475_938.38 // And this is hundreds of millions","
")
#20019=@"loc,{#10000},2,1,2,59"
locations_default(#20019,#10000,2,1,2,59)
hasLocation(#20018,#20019)
#20020=*
lines(#20020,#20001,"","
")
#20021=@"loc,{#10000},3,1,3,0"
locations_default(#20021,#10000,3,1,3,0)
hasLocation(#20020,#20021)
#20022=*
lines(#20022,#20001,"let fee = 123_00; // $123 (12300 cents, apparently)","
")
#20023=@"loc,{#10000},4,1,4,57"
locations_default(#20023,#10000,4,1,4,57)
hasLocation(#20022,#20023)
#20024=*
lines(#20024,#20001,"let fee = 12_300; // $12,300 (woah, that fee!)","
")
#20025=@"loc,{#10000},5,1,5,52"
locations_default(#20025,#10000,5,1,5,52)
hasLocation(#20024,#20025)
#20026=*
lines(#20026,#20001,"let amount = 12345_00; // 12,345 (1234500 cents, apparently)","
")
#20027=@"loc,{#10000},6,1,6,61"
locations_default(#20027,#10000,6,1,6,61)
hasLocation(#20026,#20027)
#20028=*
lines(#20028,#20001,"let amount = 123_4500; // 123.45 (4-fixed financial)","
")
#20029=@"loc,{#10000},7,1,7,53"
locations_default(#20029,#10000,7,1,7,53)
hasLocation(#20028,#20029)
#20030=*
lines(#20030,#20001,"let amount = 1_234_500; // 1,234,500","
")
#20031=@"loc,{#10000},8,1,8,36"
locations_default(#20031,#10000,8,1,8,36)
hasLocation(#20030,#20031)
numlines(#20001,8,7,7)
#20032=*
tokeninfo(#20032,3,#20001,0,"1_000_000_000")
#20033=@"loc,{#10000},1,1,1,13"
locations_default(#20033,#10000,1,1,1,13)
hasLocation(#20032,#20033)
#20034=*
tokeninfo(#20034,3,#20001,1,"101_475_938.38")
#20035=@"loc,{#10000},2,1,2,14"
locations_default(#20035,#10000,2,1,2,14)
hasLocation(#20034,#20035)
next_token(#20002,#20034)
#20036=*
tokeninfo(#20036,7,#20001,2,"let")
#20037=@"loc,{#10000},4,1,4,3"
locations_default(#20037,#10000,4,1,4,3)
hasLocation(#20036,#20037)
next_token(#20004,#20036)
#20038=*
tokeninfo(#20038,6,#20001,3,"fee")
#20039=@"loc,{#10000},4,5,4,7"
locations_default(#20039,#10000,4,5,4,7)
hasLocation(#20038,#20039)
#20040=*
tokeninfo(#20040,8,#20001,4,"=")
#20041=@"loc,{#10000},4,9,4,9"
locations_default(#20041,#10000,4,9,4,9)
hasLocation(#20040,#20041)
#20042=*
tokeninfo(#20042,3,#20001,5,"123_00")
#20043=@"loc,{#10000},4,11,4,16"
locations_default(#20043,#10000,4,11,4,16)
hasLocation(#20042,#20043)
#20044=*
tokeninfo(#20044,8,#20001,6,";")
#20045=@"loc,{#10000},4,17,4,17"
locations_default(#20045,#10000,4,17,4,17)
hasLocation(#20044,#20045)
#20046=*
tokeninfo(#20046,7,#20001,7,"let")
#20047=@"loc,{#10000},5,1,5,3"
locations_default(#20047,#10000,5,1,5,3)
hasLocation(#20046,#20047)
next_token(#20006,#20046)
#20048=*
tokeninfo(#20048,6,#20001,8,"fee")
#20049=@"loc,{#10000},5,5,5,7"
locations_default(#20049,#10000,5,5,5,7)
hasLocation(#20048,#20049)
#20050=*
tokeninfo(#20050,8,#20001,9,"=")
#20051=@"loc,{#10000},5,9,5,9"
locations_default(#20051,#10000,5,9,5,9)
hasLocation(#20050,#20051)
#20052=*
tokeninfo(#20052,3,#20001,10,"12_300")
#20053=@"loc,{#10000},5,11,5,16"
locations_default(#20053,#10000,5,11,5,16)
hasLocation(#20052,#20053)
#20054=*
tokeninfo(#20054,8,#20001,11,";")
#20055=@"loc,{#10000},5,17,5,17"
locations_default(#20055,#10000,5,17,5,17)
hasLocation(#20054,#20055)
#20056=*
tokeninfo(#20056,7,#20001,12,"let")
#20057=@"loc,{#10000},6,1,6,3"
locations_default(#20057,#10000,6,1,6,3)
hasLocation(#20056,#20057)
next_token(#20008,#20056)
#20058=*
tokeninfo(#20058,6,#20001,13,"amount")
#20059=@"loc,{#10000},6,5,6,10"
locations_default(#20059,#10000,6,5,6,10)
hasLocation(#20058,#20059)
#20060=*
tokeninfo(#20060,8,#20001,14,"=")
#20061=@"loc,{#10000},6,12,6,12"
locations_default(#20061,#10000,6,12,6,12)
hasLocation(#20060,#20061)
#20062=*
tokeninfo(#20062,3,#20001,15,"12345_00")
#20063=@"loc,{#10000},6,14,6,21"
locations_default(#20063,#10000,6,14,6,21)
hasLocation(#20062,#20063)
#20064=*
tokeninfo(#20064,8,#20001,16,";")
#20065=@"loc,{#10000},6,22,6,22"
locations_default(#20065,#10000,6,22,6,22)
hasLocation(#20064,#20065)
#20066=*
tokeninfo(#20066,7,#20001,17,"let")
#20067=@"loc,{#10000},7,1,7,3"
locations_default(#20067,#10000,7,1,7,3)
hasLocation(#20066,#20067)
next_token(#20010,#20066)
#20068=*
tokeninfo(#20068,6,#20001,18,"amount")
#20069=@"loc,{#10000},7,5,7,10"
locations_default(#20069,#10000,7,5,7,10)
hasLocation(#20068,#20069)
#20070=*
tokeninfo(#20070,8,#20001,19,"=")
#20071=@"loc,{#10000},7,12,7,12"
locations_default(#20071,#10000,7,12,7,12)
hasLocation(#20070,#20071)
#20072=*
tokeninfo(#20072,3,#20001,20,"123_4500")
#20073=@"loc,{#10000},7,14,7,21"
locations_default(#20073,#10000,7,14,7,21)
hasLocation(#20072,#20073)
#20074=*
tokeninfo(#20074,8,#20001,21,";")
#20075=@"loc,{#10000},7,22,7,22"
locations_default(#20075,#10000,7,22,7,22)
hasLocation(#20074,#20075)
#20076=*
tokeninfo(#20076,7,#20001,22,"let")
#20077=@"loc,{#10000},8,1,8,3"
locations_default(#20077,#10000,8,1,8,3)
hasLocation(#20076,#20077)
next_token(#20012,#20076)
#20078=*
tokeninfo(#20078,6,#20001,23,"amount")
#20079=@"loc,{#10000},8,5,8,10"
locations_default(#20079,#10000,8,5,8,10)
hasLocation(#20078,#20079)
#20080=*
tokeninfo(#20080,8,#20001,24,"=")
#20081=@"loc,{#10000},8,12,8,12"
locations_default(#20081,#10000,8,12,8,12)
hasLocation(#20080,#20081)
#20082=*
tokeninfo(#20082,3,#20001,25,"1_234_500")
#20083=@"loc,{#10000},8,14,8,22"
locations_default(#20083,#10000,8,14,8,22)
hasLocation(#20082,#20083)
#20084=*
tokeninfo(#20084,8,#20001,26,";")
#20085=@"loc,{#10000},8,23,8,23"
locations_default(#20085,#10000,8,23,8,23)
hasLocation(#20084,#20085)
#20086=*
tokeninfo(#20086,0,#20001,27,"")
#20087=@"loc,{#10000},9,1,9,0"
locations_default(#20087,#10000,9,1,9,0)
hasLocation(#20086,#20087)
next_token(#20014,#20086)
toplevels(#20001,0)
#20088=@"loc,{#10000},1,1,9,0"
locations_default(#20088,#10000,1,1,9,0)
hasLocation(#20001,#20088)
#20089=@"var;{fee};{#20000}"
variables(#20089,"fee",#20000)
#20090=@"var;{amount};{#20000}"
variables(#20090,"amount",#20000)
#20091=*
stmts(#20091,2,#20001,0,"1_000_000_000")
hasLocation(#20091,#20033)
stmt_containers(#20091,#20001)
#20092=*
exprs(#20092,3,#20091,0,"1_000_000_000")
hasLocation(#20092,#20033)
enclosing_stmt(#20092,#20091)
expr_containers(#20092,#20001)
literals("1000000000","1_000_000_000",#20092)
#20093=*
stmts(#20093,2,#20001,1,"101_475_938.38")
hasLocation(#20093,#20035)
stmt_containers(#20093,#20001)
#20094=*
exprs(#20094,3,#20093,0,"101_475_938.38")
hasLocation(#20094,#20035)
enclosing_stmt(#20094,#20093)
expr_containers(#20094,#20001)
literals("1.0147593838E8","101_475_938.38",#20094)
#20095=*
stmts(#20095,23,#20001,2,"let fee = 123_00;")
#20096=@"loc,{#10000},4,1,4,17"
locations_default(#20096,#10000,4,1,4,17)
hasLocation(#20095,#20096)
stmt_containers(#20095,#20001)
#20097=*
exprs(#20097,64,#20095,0,"fee = 123_00")
#20098=@"loc,{#10000},4,5,4,16"
locations_default(#20098,#10000,4,5,4,16)
hasLocation(#20097,#20098)
enclosing_stmt(#20097,#20095)
expr_containers(#20097,#20001)
#20099=*
exprs(#20099,78,#20097,0,"fee")
hasLocation(#20099,#20039)
enclosing_stmt(#20099,#20095)
expr_containers(#20099,#20001)
literals("fee","fee",#20099)
decl(#20099,#20089)
#20100=*
exprs(#20100,3,#20097,1,"123_00")
hasLocation(#20100,#20043)
enclosing_stmt(#20100,#20095)
expr_containers(#20100,#20001)
literals("12300","123_00",#20100)
#20101=*
stmts(#20101,23,#20001,3,"let fee = 12_300;")
#20102=@"loc,{#10000},5,1,5,17"
locations_default(#20102,#10000,5,1,5,17)
hasLocation(#20101,#20102)
stmt_containers(#20101,#20001)
#20103=*
exprs(#20103,64,#20101,0,"fee = 12_300")
#20104=@"loc,{#10000},5,5,5,16"
locations_default(#20104,#10000,5,5,5,16)
hasLocation(#20103,#20104)
enclosing_stmt(#20103,#20101)
expr_containers(#20103,#20001)
#20105=*
exprs(#20105,78,#20103,0,"fee")
hasLocation(#20105,#20049)
enclosing_stmt(#20105,#20101)
expr_containers(#20105,#20001)
literals("fee","fee",#20105)
decl(#20105,#20089)
#20106=*
exprs(#20106,3,#20103,1,"12_300")
hasLocation(#20106,#20053)
enclosing_stmt(#20106,#20101)
expr_containers(#20106,#20001)
literals("12300","12_300",#20106)
#20107=*
stmts(#20107,23,#20001,4,"let amo ... 345_00;")
#20108=@"loc,{#10000},6,1,6,22"
locations_default(#20108,#10000,6,1,6,22)
hasLocation(#20107,#20108)
stmt_containers(#20107,#20001)
#20109=*
exprs(#20109,64,#20107,0,"amount = 12345_00")
#20110=@"loc,{#10000},6,5,6,21"
locations_default(#20110,#10000,6,5,6,21)
hasLocation(#20109,#20110)
enclosing_stmt(#20109,#20107)
expr_containers(#20109,#20001)
#20111=*
exprs(#20111,78,#20109,0,"amount")
hasLocation(#20111,#20059)
enclosing_stmt(#20111,#20107)
expr_containers(#20111,#20001)
literals("amount","amount",#20111)
decl(#20111,#20090)
#20112=*
exprs(#20112,3,#20109,1,"12345_00")
hasLocation(#20112,#20063)
enclosing_stmt(#20112,#20107)
expr_containers(#20112,#20001)
literals("1234500","12345_00",#20112)
#20113=*
stmts(#20113,23,#20001,5,"let amo ... 3_4500;")
#20114=@"loc,{#10000},7,1,7,22"
locations_default(#20114,#10000,7,1,7,22)
hasLocation(#20113,#20114)
stmt_containers(#20113,#20001)
#20115=*
exprs(#20115,64,#20113,0,"amount = 123_4500")
#20116=@"loc,{#10000},7,5,7,21"
locations_default(#20116,#10000,7,5,7,21)
hasLocation(#20115,#20116)
enclosing_stmt(#20115,#20113)
expr_containers(#20115,#20001)
#20117=*
exprs(#20117,78,#20115,0,"amount")
hasLocation(#20117,#20069)
enclosing_stmt(#20117,#20113)
expr_containers(#20117,#20001)
literals("amount","amount",#20117)
decl(#20117,#20090)
#20118=*
exprs(#20118,3,#20115,1,"123_4500")
hasLocation(#20118,#20073)
enclosing_stmt(#20118,#20113)
expr_containers(#20118,#20001)
literals("1234500","123_4500",#20118)
#20119=*
stmts(#20119,23,#20001,6,"let amo ... 34_500;")
#20120=@"loc,{#10000},8,1,8,23"
locations_default(#20120,#10000,8,1,8,23)
hasLocation(#20119,#20120)
stmt_containers(#20119,#20001)
#20121=*
exprs(#20121,64,#20119,0,"amount = 1_234_500")
#20122=@"loc,{#10000},8,5,8,22"
locations_default(#20122,#10000,8,5,8,22)
hasLocation(#20121,#20122)
enclosing_stmt(#20121,#20119)
expr_containers(#20121,#20001)
#20123=*
exprs(#20123,78,#20121,0,"amount")
hasLocation(#20123,#20079)
enclosing_stmt(#20123,#20119)
expr_containers(#20123,#20001)
literals("amount","amount",#20123)
decl(#20123,#20090)
#20124=*
exprs(#20124,3,#20121,1,"1_234_500")
hasLocation(#20124,#20083)
enclosing_stmt(#20124,#20119)
expr_containers(#20124,#20001)
literals("1234500","1_234_500",#20124)
#20125=*
entry_cfg_node(#20125,#20001)
#20126=@"loc,{#10000},1,1,1,0"
locations_default(#20126,#10000,1,1,1,0)
hasLocation(#20125,#20126)
#20127=*
exit_cfg_node(#20127,#20001)
hasLocation(#20127,#20087)
successor(#20119,#20123)
successor(#20124,#20121)
successor(#20123,#20124)
successor(#20121,#20127)
successor(#20113,#20117)
successor(#20118,#20115)
successor(#20117,#20118)
successor(#20115,#20119)
successor(#20107,#20111)
successor(#20112,#20109)
successor(#20111,#20112)
successor(#20109,#20113)
successor(#20101,#20105)
successor(#20106,#20103)
successor(#20105,#20106)
successor(#20103,#20107)
successor(#20095,#20099)
successor(#20100,#20097)
successor(#20099,#20100)
successor(#20097,#20101)
successor(#20093,#20094)
successor(#20094,#20095)
successor(#20091,#20092)
successor(#20092,#20093)
successor(#20125,#20091)
numlines(#10000,8,7,7)
filetype(#10000,"javascript")

View File

@@ -31,7 +31,7 @@ predicate isStringSplitOrReplace(MethodCallExpr mce) {
mce.getMethodName() = name and
mce.getNumArgument() = arity
|
name = "replace" and arity = 2
name = ["replace", "replaceAll"] and arity = 2
or
name = "split" and
(arity = 1 or arity = 2)

View File

@@ -70,7 +70,7 @@ predicate regExpMatchesString(RegExpTerm t, string s) {
from MethodCallExpr repl, string s, string friendly
where
repl.getMethodName() = "replace" and
repl.getMethodName() = ["replace", "replaceAll"] and
matchesString(repl.getArgument(0), s) and
repl.getArgument(1).getStringValue() = s and
(if s = "" then friendly = "the empty string" else friendly = "'" + s + "'")

View File

@@ -75,7 +75,7 @@ DataFlow::Node schemeCheck(DataFlow::Node nd, DangerousScheme scheme) {
exists(DataFlow::MethodCallNode stringop |
stringop.getMethodName().matches("trim%") or
stringop.getMethodName().matches("to%Case") or
stringop.getMethodName() = "replace"
stringop.getMethodName() = ["replace", "replaceAll"]
|
result = schemeCheck(stringop, scheme) and
nd = stringop.getReceiver()

View File

@@ -79,6 +79,7 @@ predicate allBackslashesEscaped(DataFlow::Node nd) {
// flow through string methods
exists(DataFlow::MethodCallNode mc, string m |
m = "replace" or
m = "replaceAll" or
m = "slice" or
m = "substr" or
m = "substring" or

View File

@@ -117,11 +117,11 @@ class ResolvedES2015PromiseDefinition extends ResolvedPromiseDefinition {
}
/**
* An aggregated promise produced either by `Promise.all` or `Promise.race`.
* An aggregated promise produced either by `Promise.all`, `Promise.race`, or `Promise.any`.
*/
class AggregateES2015PromiseDefinition extends PromiseCreationCall {
AggregateES2015PromiseDefinition() {
exists(string m | m = "all" or m = "race" |
exists(string m | m = "all" or m = "race" or m = "any" |
this = DataFlow::globalVarRef("Promise").getAMemberCall(m)
)
}

View File

@@ -102,7 +102,7 @@ private class IteratorExceptionStep extends DataFlow::MethodCallNode, DataFlow::
*/
class StringReplaceCall extends DataFlow::MethodCallNode {
StringReplaceCall() {
getMethodName() = "replace" and
getMethodName() = ["replace", "replaceAll"] and
(getNumArgument() = 2 or getReceiver().mayHaveStringValue(_))
}
@@ -128,9 +128,9 @@ class StringReplaceCall extends DataFlow::MethodCallNode {
/**
* Holds if this is a global replacement, that is, the first argument is a regular expression
* with the `g` flag.
* with the `g` flag, or this is a call to `.replaceAll()`.
*/
predicate isGlobal() { getRegExp().isGlobal() }
predicate isGlobal() { getRegExp().isGlobal() or getMethodName() = "replaceAll" }
/**
* Holds if this call to `replace` replaces `old` with `new`.

View File

@@ -427,6 +427,7 @@ module TaintTracking {
name = "padStart" or
name = "repeat" or
name = "replace" or
name = "replaceAll" or
name = "slice" or
name = "small" or
name = "split" or
@@ -452,7 +453,7 @@ module TaintTracking {
exists(int i | pred.asExpr() = succ.getAstNode().(MethodCallExpr).getArgument(i) |
name = "concat"
or
name = "replace" and i = 1
name = ["replace", "replaceAll"] and i = 1
)
)
or
@@ -707,7 +708,8 @@ module TaintTracking {
*/
private ControlFlowNode getACaptureSetter(DataFlow::Node input) {
exists(DataFlow::MethodCallNode call | result = call.asExpr() |
call.getMethodName() = ["search", "replace", "match"] and input = call.getReceiver()
call.getMethodName() = ["search", "replace", "replaceAll", "match"] and
input = call.getReceiver()
or
call.getMethodName() = ["test", "exec"] and input = call.getArgument(0)
)

View File

@@ -15,9 +15,7 @@ abstract class HeuristicAdditionalTaintStep extends DataFlow::ValueNode { }
* A call to `tainted.replace(x, y)` that preserves taint.
*/
private class HeuristicStringManipulationTaintStep extends HeuristicAdditionalTaintStep,
TaintTracking::AdditionalTaintStep, DataFlow::MethodCallNode {
HeuristicStringManipulationTaintStep() { getMethodName() = "replace" }
TaintTracking::AdditionalTaintStep, StringReplaceCall {
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
pred = getReceiver() and succ = this
}

View File

@@ -34,15 +34,11 @@ module CleartextLogging {
/**
* A call to `.replace()` that seems to mask sensitive information.
*/
class MaskingReplacer extends Barrier, DataFlow::MethodCallNode {
class MaskingReplacer extends Barrier, StringReplaceCall {
MaskingReplacer() {
this.getCalleeName() = "replace" and
exists(RegExpLiteral reg |
reg = this.getArgument(0).getALocalSource().asExpr() and
reg.isGlobal() and
any(RegExpDot term).getLiteral() = reg
) and
exists(this.getArgument(1).getStringValue())
this.isGlobal() and
exists(this.getRawReplacement().getStringValue()) and
any(RegExpDot term).getLiteral() = getRegExp().asExpr()
}
}

View File

@@ -218,12 +218,12 @@ module TaintedPath {
output = this
or
// non-global replace or replace of something other than /\.\./g, /[/]/g, or /[\.]/g.
this.getCalleeName() = "replace" and
this instanceof StringReplaceCall and
input = getReceiver() and
output = this and
not exists(RegExpLiteral literal, RegExpTerm term |
getArgument(0).getALocalSource().asExpr() = literal and
literal.isGlobal() and
this.(StringReplaceCall).getRegExp().asExpr() = literal and
this.(StringReplaceCall).isGlobal() and
literal.getRoot() = term
|
term.getAMatchedString() = "/" or
@@ -247,16 +247,15 @@ module TaintedPath {
/**
* A call that removes all instances of "../" in the prefix of the string.
*/
class DotDotSlashPrefixRemovingReplace extends DataFlow::CallNode {
class DotDotSlashPrefixRemovingReplace extends StringReplaceCall {
DataFlow::Node input;
DataFlow::Node output;
DotDotSlashPrefixRemovingReplace() {
this.getCalleeName() = "replace" and
input = getReceiver() and
output = this and
exists(RegExpLiteral literal, RegExpTerm term |
getArgument(0).getALocalSource().asExpr() = literal and
getRegExp().asExpr() = literal and
(term instanceof RegExpStar or term instanceof RegExpPlus) and
term.getChild(0) = getADotDotSlashMatcher()
|
@@ -298,17 +297,16 @@ module TaintedPath {
/**
* A call that removes all "." or ".." from a path, without also removing all forward slashes.
*/
class DotRemovingReplaceCall extends DataFlow::CallNode {
class DotRemovingReplaceCall extends StringReplaceCall {
DataFlow::Node input;
DataFlow::Node output;
DotRemovingReplaceCall() {
this.getCalleeName() = "replace" and
input = getReceiver() and
output = this and
isGlobal() and
exists(RegExpLiteral literal, RegExpTerm term |
getArgument(0).getALocalSource().asExpr() = literal and
literal.isGlobal() and
getRegExp().asExpr() = literal and
literal.getRoot() = term and
not term.getAMatchedString() = "/"
|

View File

@@ -39,10 +39,9 @@ module UnsafeJQueryPlugin {
StringConcatenation::taintStep(pred, succ, _, any(int i | i >= 1))
or
// prefixing through a poor-mans templating system:
exists(DataFlow::MethodCallNode replace |
exists(StringReplaceCall replace |
replace = succ and
pred = replace.getArgument(1) and
replace.getMethodName() = "replace"
pred = replace.getRawReplacement()
)
}

View File

@@ -33,11 +33,10 @@ module Shared {
* The XSS queries do not attempt to reason about correctness or completeness of sanitizers,
* so any such replacement stops taint propagation.
*/
class MetacharEscapeSanitizer extends Sanitizer, DataFlow::MethodCallNode {
class MetacharEscapeSanitizer extends Sanitizer, StringReplaceCall {
MetacharEscapeSanitizer() {
getMethodName() = "replace" and
exists(RegExpConstant c |
c.getLiteral() = getArgument(0).getALocalSource().asExpr() and
c.getLiteral() = getRegExp().asExpr() and
c.getValue().regexpMatch("['\"&<>]")
)
}

View File

@@ -51,6 +51,7 @@ module PolynomialReDoS {
name = "split" or
name = "matchAll" or
name = "replace" or
name = "replaceAll" or
name = "search"
)
or

View File

@@ -86,6 +86,8 @@
| tst.js:2:17:2:22 | "src1" | tst.js:61:16:61:18 | o.r |
| tst.js:2:17:2:22 | "src1" | tst.js:68:16:68:22 | inner() |
| tst.js:2:17:2:22 | "src1" | tst.js:80:16:80:22 | outer() |
| tst.js:2:17:2:22 | "src1" | tst.js:87:16:87:43 | source1 ... /g, "") |
| tst.js:2:17:2:22 | "src1" | tst.js:88:16:88:46 | "foo".r ... ource1) |
| underscore.js:2:17:2:22 | "src1" | underscore.js:3:15:3:28 | _.max(source1) |
| underscore.js:5:17:5:22 | "src2" | underscore.js:6:15:6:34 | _.union([], source2) |
| underscore.js:5:17:5:22 | "src2" | underscore.js:7:15:7:32 | _.zip(source2, []) |

View File

@@ -83,4 +83,7 @@
o.notTracked = source1;
var sink22 = o.notTracked;
var sink23 = source1.replaceAll(/f/g, "");
var sink24 = "foo".replaceAll(/f/g, source1);
})();

View File

@@ -18,4 +18,10 @@
var [clean3, tainted3] = await Promise.all(["clean", Promise.resolve(source)]);
sink(clean3); // OK
sink(tainted3); // NOT OK - but only flagged by taint-tracking
var tainted4 = await Promise.race(["clean", Promise.resolve(source)]);
sink(tainted4); // NOT OK - but only flagged by taint-tracking
var tainted5 = await Promise.any(["clean", Promise.resolve(source)]);
sink(tainted5); // NOT OK - but only flagged by taint-tracking
});

View File

@@ -9,6 +9,12 @@ test_ResolvedPromiseDefinition
| flow2.js:18:33:18:79 | Promise ... urce)]) | flow2.js:18:46:18:52 | "clean" |
| flow2.js:18:33:18:79 | Promise ... urce)]) | flow2.js:18:55:18:77 | Promise ... source) |
| flow2.js:18:55:18:77 | Promise ... source) | flow2.js:18:71:18:76 | source |
| flow2.js:22:23:22:70 | Promise ... urce)]) | flow2.js:22:37:22:43 | "clean" |
| flow2.js:22:23:22:70 | Promise ... urce)]) | flow2.js:22:46:22:68 | Promise ... source) |
| flow2.js:22:46:22:68 | Promise ... source) | flow2.js:22:62:22:67 | source |
| flow2.js:25:23:25:69 | Promise ... urce)]) | flow2.js:25:36:25:42 | "clean" |
| flow2.js:25:23:25:69 | Promise ... urce)]) | flow2.js:25:45:25:67 | Promise ... source) |
| flow2.js:25:45:25:67 | Promise ... source) | flow2.js:25:61:25:66 | source |
| flow.js:4:11:4:33 | Promise ... source) | flow.js:4:27:4:32 | source |
| flow.js:20:2:20:24 | Promise ... source) | flow.js:20:18:20:23 | source |
| flow.js:22:2:22:24 | Promise ... source) | flow.js:22:18:22:23 | source |
@@ -201,6 +207,8 @@ flow
| flow2.js:2:15:2:22 | "source" | flow2.js:6:8:6:13 | arr[0] |
| flow2.js:2:15:2:22 | "source" | flow2.js:12:7:12:13 | tainted |
| flow2.js:2:15:2:22 | "source" | flow2.js:16:7:16:14 | tainted2 |
| flow2.js:2:15:2:22 | "source" | flow2.js:23:7:23:14 | tainted4 |
| flow2.js:2:15:2:22 | "source" | flow2.js:26:7:26:14 | tainted5 |
| flow.js:2:15:2:22 | "source" | flow.js:5:7:5:14 | await p1 |
| flow.js:2:15:2:22 | "source" | flow.js:8:7:8:14 | await p2 |
| flow.js:2:15:2:22 | "source" | flow.js:17:8:17:8 | e |
@@ -255,6 +263,12 @@ typetrack
| flow2.js:18:27:18:79 | await P ... urce)]) | flow2.js:18:33:18:79 | Promise ... urce)]) | load $PromiseResolveField$ |
| flow2.js:18:33:18:79 | Promise ... urce)]) | flow2.js:18:45:18:78 | ["clean ... ource)] | copy $PromiseResolveField$ |
| flow2.js:18:33:18:79 | Promise ... urce)]) | flow2.js:18:45:18:78 | ["clean ... ource)] | store $PromiseResolveField$ |
| flow2.js:22:17:22:70 | await P ... urce)]) | flow2.js:22:23:22:70 | Promise ... urce)]) | load $PromiseResolveField$ |
| flow2.js:22:23:22:70 | Promise ... urce)]) | flow2.js:22:46:22:68 | Promise ... source) | copy $PromiseResolveField$ |
| flow2.js:22:23:22:70 | Promise ... urce)]) | flow2.js:22:46:22:68 | Promise ... source) | store $PromiseResolveField$ |
| flow2.js:25:17:25:69 | await P ... urce)]) | flow2.js:25:23:25:69 | Promise ... urce)]) | load $PromiseResolveField$ |
| flow2.js:25:23:25:69 | Promise ... urce)]) | flow2.js:25:45:25:67 | Promise ... source) | copy $PromiseResolveField$ |
| flow2.js:25:23:25:69 | Promise ... urce)]) | flow2.js:25:45:25:67 | Promise ... source) | store $PromiseResolveField$ |
| flow.js:20:2:20:43 | Promise ... ink(x)) | flow.js:20:36:20:42 | sink(x) | copy $PromiseResolveField$ |
| flow.js:20:2:20:43 | Promise ... ink(x)) | flow.js:20:36:20:42 | sink(x) | store $PromiseResolveField$ |
| flow.js:20:31:20:31 | x | flow.js:20:2:20:24 | Promise ... source) | load $PromiseResolveField$ |

View File

@@ -17,6 +17,7 @@
| polynomial-redos.js:31:42:31:43 | -+ | it can start matching anywhere |
| polynomial-redos.js:32:45:32:47 | \\n* | it can start matching anywhere |
| polynomial-redos.js:33:17:33:20 | (.)* | it can start matching anywhere |
| polynomial-redos.js:48:22:48:24 | \\s* | it can start matching anywhere |
| regexplib/address.js:18:26:18:31 | [ \\w]* | it can start matching anywhere after the start of the preceeding '[ \\w]{3,}' |
| regexplib/address.js:20:144:20:147 | [ ]+ | it can start matching anywhere after the start of the preceeding '[a-zA-Z0-9 \\-.]{6,}' |
| regexplib/address.js:24:26:24:31 | [ \\w]* | it can start matching anywhere after the start of the preceeding '[ \\w]{3,}' |

View File

@@ -28,6 +28,8 @@ nodes
| polynomial-redos.js:30:2:30:8 | tainted |
| polynomial-redos.js:33:2:33:8 | tainted |
| polynomial-redos.js:33:2:33:8 | tainted |
| polynomial-redos.js:48:2:48:8 | tainted |
| polynomial-redos.js:48:2:48:8 | tainted |
edges
| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:7:2:7:8 | tainted |
| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:7:2:7:8 | tainted |
@@ -55,6 +57,8 @@ edges
| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:30:2:30:8 | tainted |
| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:33:2:33:8 | tainted |
| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:33:2:33:8 | tainted |
| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:48:2:48:8 | tainted |
| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:48:2:48:8 | tainted |
| polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:5:6:5:32 | tainted |
| polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:5:6:5:32 | tainted |
#select
@@ -72,3 +76,4 @@ edges
| polynomial-redos.js:27:77:27:83 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:27:77:27:83 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:27:14:27:22 | [A-Z]{2,} | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value |
| polynomial-redos.js:30:2:30:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:30:2:30:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:30:19:30:22 | [?]+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value |
| polynomial-redos.js:33:2:33:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:33:2:33:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:33:17:33:20 | (.)* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value |
| polynomial-redos.js:48:2:48:8 | tainted | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:48:2:48:8 | tainted | This expensive $@ use depends on $@. | polynomial-redos.js:48:22:48:24 | \\s* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value |

View File

@@ -45,5 +45,5 @@ app.use(function(req, res) {
tainted.match(/^(?:\.?[a-zA-Z_][a-zA-Z_0-9]*)+$/); // NOT OK - but not flagged
tainted.match(/^(?:\.?[a-zA-Z_][a-zA-Z_0-9]*)(?:\.[a-zA-Z_][a-zA-Z_0-9]*)*$/); // OK
tainted.replaceAll(/\s*\n\s*/g, ' '); // NOT OK
});