var a = 100, b = 10, c = 0;
({
undefined: {
foo: ++a
}[+a],
undefined: b++,
NaN: a--,
3: (c = c + 1) + (--b + (delete (a && (a.NaN ^= -3 << null)) || (true && "number") | -2 == -3) ? a && a.foo : (c = c + 1) + b++)
}).in;
{
var brake2 = 5;
while (a++ + {
0: --b + {
0: !b,
c: (c = c + 1) + +function bar() {
switch ((b + 1 - .1 - .1 - .1 || 9).toString()[a++ + [ (c = 1 + c, (22 << 3 & 3 - 38..toString()) < (void -1 && undefined | "bar")), (c = 1 + c,
("object" >= NaN) * (-5, "function") / ((4 || "number") / (22 <= 1))) ]]) {
case a++ + typeof ((c = c + 1) + ~((/[a2][^e]+$/ === 23..toString()) - (a && (a[(c = 1 + c,
(-1 | "bar") + 0 % "number" ^ [] > 22 !== (-4 || 5))] = 38..toString() ^ -2)) < (!"undefined" !== 4 << undefined))):
case {
3: (c = c + 1) + (a && a.NaN)
}.NaN:
c = c + 1;
break;
default:
{
var a_2 = function f0() {
}((c = 1 + c, -3 != "function" ^ 4 - 0 ^ +(-2 | -4)));
}
;
case !((c = c + 1, -2 * undefined) >= (({} || "object") & 38..toString() !== null)):
break;
}
try {
var bar = --b + {
c: (c = 1 + c, undefined / undefined ^ [] <= Infinity ^ (c = c + 1, false | -1)),
1.5: (c = 1 + c, ~3 - (2 >> 3) >> ((c = c + 1, /[a2][^e]+$/) ^ 22 < 1)),
Infinity: (c = 1 + c, ((24..toString(), 22) && 38..toString() >>> null) === ("undefined" <= [ , 0 ][1]) >>> ({} >= [ , 0 ][1])),
undefined: (c = 1 + c, {} !== -0 == undefined % 4 === ((a_2 = "undefined" && []) ^ (a_2 && (a_2[(c = 1 + c,
c = c + 1, (/[a2][^e]+$/ && -4) >>> (a_2 && (a_2.null = "number" >= 1)))] |= {} & NaN))))
}.a;
} catch (b_2) {
{
var brake10 = 5;
L68044: do {
} while (--b + (a_2 && a_2[(c = 1 + c, (false && 2) / (24..toString() % [ , 0 ][1]) / ((-5 == true) + (b_2 && (b_2.undefined += 2 > 23..toString()))))]) && --brake10 > 0);
}
return --b + {
1.5: (c = 1 + c, "bar" * undefined >= ("foo" & undefined) > (~false, "object" >= 4)),
foo: (c = 1 + c, ("foo" <= "bar") % (b_2 && (b_2.a = -0 >>> 4)) !== (c = c + 1,
38..toString()) > delete 0)
}[(c = 1 + c, ([] !== "bar") / ("function" | -1) < (([ , 0 ].length === 2) > [ , 0 ][1]) * (/[a2][^e]+$/ | 24..toString()))];
}
{
var foo_1 = (c = c + 1) + {
"": (c = 1 + c, ~(({} ^ "function") & -3 + [ , 0 ][1])),
NaN: (c = 1 + c, (-2 !== [ , 0 ][1] ^ -3 << "") >= ("number" + 2) % (-2 >= 5)),
foo: (c = 1 + c, NaN === null != (3 ^ 22) & (true - true) * (-1 & 22))
}.b;
}
}(),
1.5: ++a
},
get in() {
c = c + 1;
return (c = c + 1) + {
Infinity: (c = c + 1) + {
foo: (c = c + 1) + +function undefined_1() {
for (var brake17 = 5; (c = 1 + c, (undefined_1 += "foo" <= /[a2][^e]+$/) >= {} >>> NaN == (undefined_1 && (undefined_1[(c = 1 + c,
"bar" >> /[a2][^e]+$/ == (undefined_1 && (undefined_1[(c = 1 + c, (undefined_1 && (undefined_1.undefined = (true && "function") < "object" % -1)) == (-4 > 0 !== ({} != -3)))] += [] >> 4)) || "foo" & NaN ^ (Infinity ^ -3))] <<= 1 & -3)) < (undefined_1 >>>= 1 >> 23..toString())) && brake17 > 0; --brake17) {
c = 1 + c, ~true <= (undefined_1 && (undefined_1.var += "object" - 4)) < (undefined / [] < ("object",
24..toString()));
}
if (c = 1 + c, undefined_1 && (undefined_1[(-1 | 23..toString()) * (undefined_1 += 25 != NaN) % (("foo" != "undefined") / (25 ^ -0))] %= ("bar" > 23..toString()) % (c = c + 1,
2) && (1 < -1) - ("function", 23..toString()))) {
c = 1 + c, ((undefined_1 && (undefined_1.Infinity = 25 % /[a2][^e]+$/)) ^ (c = c + 1,
-0)) >= (22 && "foo" && -4 ^ true);
} else {
c = 1 + c, (-4 > 0) % (38..toString() >> "foo") | ({} << -2 && 5 | "number");
}
c = c + 1;
{
var brake23 = 5;
L68045: do {
c = 1 + c, undefined_1 && (undefined_1[{
foo: (c = 1 + c, undefined_1 && (undefined_1[--b + ~(((25 ^ /[a2][^e]+$/) & ([ , 0 ].length === 2 | 23..toString())) - ((22 == 3) >>> (3 !== Infinity)))] = !(-5 === "bar") & !(undefined_1 = 5 - 0))),
c: (c = 1 + c, null <= -5 >= "object" >> 1 === (c = c + 1, -2) - (NaN << null)),
in: (c = 1 + c, (-5 / "function" ^ (-3, "foo")) == (undefined_1 = NaN * null % (25 >>> 38..toString())))
}[--b + a++]] /= (undefined_1 = 3 > 5 != "" % /[a2][^e]+$/) << (undefined_1 && (undefined_1[b = a] >>= [ , 0 ][1] - 1 ^ "number" / "")));
} while ((c = 1 + c, (25 >> -2 & "bar" > 2) >>> (("bar" && [ , 0 ][1]) == (/[a2][^e]+$/ == 22))) && --brake23 > 0);
}
}(),
"-2": a++ + ({
b: (c = 1 + c, (c = c + 1, 23..toString()) - (-5 && -3) - (Infinity - "function" != /[a2][^e]+$/ < 3)),
undefined: (c = 1 + c, (-1 | "bar" | (c = c + 1, 4)) & "foo" > 3 < ([ , 0 ][1] != 0))
}[(c = c + 1) + ((25, undefined) << (-0 < [ , 0 ][1])) / -([] << 3)] || 9).toString()[--b + (a && a.a)],
1.5: true
}.a,
1.5: 1 === 1 ? a : b,
a: --b + /[abc4]/.test((--b + +function() {
c = c + 1;
switch (b++) {
case a && a.undefined:
c = 1 + c, ("" | NaN) / (a && (a.undefined = 25 ^ "function")) > (22 || 38..toString()) >>> "function" + 22;
c = 1 + c, ([ , 0 ][1] >= 22 || /[a2][^e]+$/ && "undefined") != (c = c + 1, null >>> "bar");
break;
case (c = 1 + c, ((true ^ -5) === (a = 4 && "undefined")) - ([] / "" < (undefined < 1))) ? (c = 1 + c,
-1 % 24..toString() >>> 22 / 1 <= (-1 == "foo") >> ("function" & -0)) : (c = 1 + c,
(c = c + 1, 23..toString() != ([ , 0 ].length === 2)) !== (-4 < "number" !== 23..toString() >> 1)):
c = 1 + c, a = (-2 + -2) % (NaN > true) ^ ({} == 24..toString() ^ undefined >> -2);
break;
case typeof (c = 1 + c, (delete "number" < ([] == -4)) + (-0 != "number" | 4 / 22)):
c = 1 + c, ("object" ^ "") + (4 < false) > (-NaN ^ 25 & "foo");
c = 1 + c, ((-5 < true) >>> (25 === {})) / ((a && (a.Infinity = 0 && 38..toString())) << (-2 >> NaN));
break;
default:
c = 1 + c, (c = c + 1, a && (a[(c = 1 + c, (undefined || [ , 0 ].length === 2) % (false ^ NaN) || ("" >= null) - +"object")] = "object" - NaN)) ^ false - 24..toString() >>> (0 !== -2);
c = 1 + c, 25 === 23..toString() === (-4 == "function") || (true ^ "foo") * (NaN * NaN);
}
{
c = 1 + c, (a += -5 !== 2) * (a && (a.c |= "foo" ^ 25)) === ("object" >>> 0 === ("bar" !== 22));
c = 1 + c, a && (a.b += ("", 23..toString()) + ("undefined" && -1) !== (a = 5 <= "function" & (c = c + 1,
"")));
c = 1 + c, (38..toString(), [], false >> 3) - ((22 != -4) + (2 == 25));
c = 1 + c, (true % 24..toString() !== (a && (a.null |= 2 + []))) >= (a && (a.in = ([ , 0 ][1] > undefined) << ("number" | 22)));
}
{
var b = function f1(a_1, parseInt, parseInt_2) {
}((c = 1 + c, 38..toString() / null << (true << -4) == ("function" !== "undefined" === 5 / -4)));
}
}() || b || 5).toString())
}[a && a.b];
},
var: --b + new function a_1() {
if ({
Infinity: (a_1 = (a_1 = NaN > /[a2][^e]+$/) !== -4 - 38..toString()) == "function" / null < Infinity / ([ , 0 ].length === 2),
"": --b + ++a,
"": [ a++, ("foo" < "foo" ^ ("function" ^ "bar")) >= (a_1 = ("number" || {}, -5 >> 23..toString())), --b + ((c = 1 + c,
(1 <= [ , 0 ][1]) << (5 ^ 22) >= null * 1 / ([] % -0)) || a || 3).toString() ].b,
in: [ --b + {
"": (c = 1 + c, ("object" == 2 !== "foo" + "foo") <= ((-1 ^ "") != (5 == 25))),
c: (c = 1 + c, (3 >= 1) - ("undefined" != []) <= ((-2 && []) == ("" ^ undefined))),
null: (c = 1 + c, ("function" ^ true) % (23..toString() >>> []) == (NaN != false) % ("object" > [ , 0 ][1]))
}, a_1 && a_1.c ]
}[+(((23..toString() && "function") >> ("undefined" === -4)) + ((22 >> [ , 0 ][1]) + +38..toString()))]) {
--b + {
null: (c = c + 1) + (1 === 1 ? a : b),
undefined: a++ + void function() {
c = 1 + c, ([ , 0 ][1] >= "function") >>> ("number" ^ false) | (-5 > true || "" | [ , 0 ][1]);
c = 1 + c, ("bar" >>> -2) + (23..toString() <= {}) << ([ , 0 ].length === 2 === 0,
([ , 0 ].length === 2) <= {});
c = 1 + c, (0 + undefined >= (c = c + 1, [ , 0 ][1])) * (3 < {} || 38..toString() < -1);
}(),
c: --b + {
0: (c = 1 + c, ({} - "bar") * ("undefined" <= 38..toString()) || 1 < -5 <= ([ , 0 ].length === 2 == 38..toString())),
NaN: (c = 1 + c, (a_1 = 3 << 25) << +"undefined" >> (true | "foo", "undefined",
0)),
foo: (c = 1 + c, a_1 && (a_1.undefined = 24..toString() + -4 ^ ("foo" | -5) ^ -4 >> [ , 0 ][1] >>> -3 / -1))
},
"": ++b,
1.5: b++
};
} else {}
}(),
foo: a && a.c,
a: /[abc4]/.test(((c = c + 1) + +((c = c + 1, /[a2][^e]+$/ !== -4) >> ((1 ^ 38..toString()) !== (c = c + 1,
false))) || b || 5).toString())
} && --brake2 > 0) {}
}
console.log(null, a, b, c);
$ node test.js
null 130 -30 136
$ uglifyjs test.js -c | node
null 130 -20 131
$ uglifyjs test.js -c pure_getters=0 | node
null 130 -30 136
$ cat test.js
var b = 0;
try {
(g = []) ^ (g[1e9] |= 0);
} catch (x) {
b = 1;
}
console.log(b);
$ node test.js
1
md5-8cb30cf0fc374c049a575d4dcc1dd7d6
$ bin/uglifyjs test.js -cb | node
0
md5-8cb30cf0fc374c049a575d4dcc1dd7d6
$ bin/uglifyjs test.js -cb
var b = 0;
try {
g = [], g[1e9] |= 0;
} catch (x) {
b = 1;
}
console.log(b);
What to do with this?
$ echo '(g = []) - (g[1e9] = 0)' | node -p
[stdin]:1
(g = []) - (g[1e9] = 0)
^
RangeError: Invalid string length
It's not technically a bug. When uglified with compress, the binary operator - is not used, so the huge array is not coerced into a string (to be coerced into a number) and an exception is not thrown:
$ echo '(g = []) - (g[1e9] = 0)' | bin/uglifyjs -c
g=[],g[1e9]=0;
$ echo '(g = []) - (g[1e9] = 0)' | bin/uglifyjs -c | node -p
0
So we basically fixed an out-of-memory bug for the JavaScript VM? Almost sounds like a feature right there... :smirk:
Joking aside, I'd vote for letting this one go as a false positive. Personally I'm a bit surprised this is a recoverable runtime error, but then even with Java you can technically catch OOME as well.
I'd vote for letting this one go as a false positive.
Yeah, nothing we can do about this one. Uglify can't possibly know about runtime constraints like this.
Does every fuzzed test case take an hour to simplify or am I just slow?
Does every fuzzed test case take an hour to simplify or am I just slow?
So what I do normally is this:
-b bracketize to the above do not alter any outputsuglifyjs test.js -b bracketize -co bad.jsuglifyjs test.js -b bracketize -c suspected_option=0 -o good.jsgood.js against bad.jsSo you don't reduce the test case at all? You only look for the diffs between good and bad?
Yeah, I can see that taking less time.
If there are too many sections of differences, then:
good.js to bad.jscat good.js | nodecat bad.js | nodeSo you don't reduce the test case at all? You only look for the diffs between good and bad?
I tried that before, but I find that to be quite time consuming and error-prone. So I use my current method above to narrow the code down, then I proceed to make reduced test cases up based on that knowledge.
Interesting. How much time to isolate a fuzzed test bug on average? Not including the fix.
How much time to isolate a fuzzed test bug on average?
Nowadays it takes longer because they tend to be somewhat exotic. But back when test/ufuzz.js and we were hunting around a dozen a day, it takes me ~10 minutes to narrow down each test case.
If only Skynet can parse my comments above and save us all some work...
I think LLVM has some sort of test case reducer:
http://llvm.org/docs/Bugpoint.html
http://blog.llvm.org/2015/11/reduce-your-testcases-with-bugpoint-and.html
Looks semi-automated. Difficult problem to solve.