Uglifyjs: Bug triggered by `keep_fargs=false`

Created on 17 Jun 2017  路  27Comments  路  Source: mishoo/UglifyJS

Similar to #2107 - ouch indeed.

// original code
// (beautified)
var a = 100, b = 10, c = 0;

{
    var b_2 = function f0(a_2, a_2, b) {
        +("" / -2 % ~3 > (a_2 = 0 % "") % ([] * Infinity));
        {
            return;
            (c = c + 1) + {
                c: a++ + typeof parseInt,
                1.5: a++ + a--
            }[a++ + [ b <<= a, --b + [].length, (c = c + 1) + [ --b + (b >>>= a), (c = c + 1) + --b, , a++ + [ (c = 1 + c, 
            (NaN % 23..toString() | 38..toString() % Infinity) + ((a_2 |= 1 !== []) - (a_2 && (a_2[(c = 1 + c, 
            ([] ^ -1) << (a_2 && (a_2.c /= null === /[a2][^e]+$/)) > (/[a2][^e]+$/, -5) >> (Infinity >> "number"))] += 25 | -5)))) ][(([ , 0 ].length === 2) >> "object" ^ null << 25) - (null & "undefined" || -2 >> "bar")], b + 1 - .1 - .1 - .1 ].c, a++ + (b = a) ].var];
        }
    }([ b++, ((c = c + 1) + (b = a) || 2).toString()[a++ + a++], typeof foo_2 != "symbol", --b + {
        "": [ [ , {
            Infinity: (c = 1 + c, b_2 && (b_2.undefined ^= ({} === "bar") * (5 < ([ , 0 ].length === 2))) && 4 > -0 & 1 !== -0),
            0: (c = 1 + c, c = c + 1, NaN + -2 + [ , 0 ][1] % [ , 0 ][1]),
            length: (c = 1 + c, (-0 % -5 !== (b_2 && (b_2.var = [] !== 3))) < /[a2][^e]+$/ % -3 * (null || 1))
        }.in ][/[abc4]/.test(((c = c + 1) + (b += a) || b || 5).toString())], a++ + /[abc4]/.test(((b += a) || b || 5).toString()), typeof bar_1 !== "symbol", ,  ].Infinity
    }[(a++ + "" || 6).toString()[--b + function() {
        {
            {
            }
            {
                var brake6 = 5;
                do {
                    c = 1 + c, (5 >> 3, -4 <= [ , 0 ][1]) - (b_2 && (b_2.undefined = 2 < -1 || "foo" === undefined));
                } while ((c = 1 + c, (0 >>> [ , 0 ][1]) - 23..toString() % 1 >= ((-2, "number") != {} * "function")) && --brake6 > 0);
            }
            {
                var expr8 = (c = 1 + c, (undefined <= "object") >> 0 / 3 <= (1 != "bar", "bar" ^ 3));
                L127602: for (var key8 in expr8) {
                    c = 1 + c;
                    var bar_2 = expr8[key8];
                    c = 1 + c, b_2 && (b_2.a = ([] === 4 !== "number" <= -5) >= (void -0, c = c + 1, 
                    []));
                }
            }
            return;
        }
        {
            var brake12 = 5;
            do {
                {}
            } while ((b += a) && --brake12 > 0);
        }
    }()]], typeof void function a_1() {
        {
            var NaN_1 = function f1(a_1) {
                var undefined = (c = 1 + c, void (-3 || "bar") * (c = c + 1, true * 25)), parseInt = (c = 1 + c, 
                (-5 ^ -5 && -3 >> ([ , 0 ].length === 2)) + (24..toString() < 5 ^ (1 | "object")));
            }((b_2 && (b_2.foo += -2 ^ 23..toString())) >>> ("function" >= 1) === (NaN_1 && (NaN_1.b += ([] >= -0) % (c = c + 1, 
            24..toString()))));
        }
        {
            var brake17 = 5;
            L127603: do {
                [ (c = 1 + c, (delete -3 ^ "number" >>> NaN) / ((b_2 = -1 * "object") >= (Infinity ^ 25))), (c = 1 + c, 
                ((/[a2][^e]+$/ ^ 3) !== 22 >> 38..toString()) <= (1 <= "function") % (/[a2][^e]+$/ === Infinity)), (c = 1 + c, 
                ("undefined" - []) * ("undefined" && 23..toString()) - ~(22 > "object")), (c = 1 + c, 
                b_2 && (b_2.in |= (1 <= null, "bar", -4) << (c = c + 1, []) * ~4)) ].null;
            } while (a++ && --brake17 > 0);
        }
    }() ]);
}

{
    var brake20 = 5;
    while ([ (c = c + 1) + new function() {
        this[3] = (((b_2 += -0 << 2 <= 23..toString() % -1) >>> (b_2 && (b_2.a = Infinity >> 3 > Infinity * "number")) !== ((b_2 && (b_2.foo /= ([ , 0 ].length === 2) > -0), 
        22 != -2) == ("number" == false) + (5 && -0))) >= ((b_2 && (b_2[-5 > "undefined" < 5 * {} < ("function" ^ "" | 0 >>> [ , 0 ][1])] += (([ , 0 ].length === 2) - -2 + (4 <= 38..toString())) * (([ , 0 ].length === 2) % 38..toString() >>> (/[a2][^e]+$/ & 23..toString())))) <= ((-0 >> null !== [ , 0 ][1] >>> undefined) >= (b_2 && (b_2.null = 4 == "" !== -1 >= {})))) | (((undefined & "undefined") >>> (/[a2][^e]+$/ != -5)) - ((c = c + 1, 
        24..toString()) + ("function" + "foo")) & (true ^ null) >>> ({} >= false) >> ((5, 
        38..toString()) !== (NaN | "foo"))) / (((23..toString() * -2 ^ ("" | "number")) >>> (3 <= "number", 
        23..toString() + "foo")) % ((null < 5) * (true != -4) | (b_2 |= 0 * NaN) >>> (0, 
        0)))) / (((c = c + 1, (Infinity | "foo") === (b_2 *= 24..toString() ^ -2) | (23..toString() ^ -0 && NaN <= "")) === ((b_2 && (b_2[(c = c + 1) + /[abc4]/.test((a++ + (b = a) || b || 5).toString())] = ({} == false, 
        true != undefined) % (/[a2][^e]+$/ + undefined >> ("bar" > ([ , 0 ].length === 2))))) & !((0 && 24..toString()) < ([ , 0 ].length === 2 ^ {})))) >= (((b_2 ^= ("object", 
        null) != 23..toString() + null) === (b_2 && (b_2.undefined += 5 === "undefined" === ([ , 0 ].length === 2) >= -2))) <= ((b_2 && (b_2.NaN = "number" || NaN)) + 38..toString() / ([ , 0 ].length === 2) ^ (undefined ^ true) !== (NaN == false))) << (((+"undefined" && false % Infinity) < (/[a2][^e]+$/ - false || 38..toString() ^ 1)) >> (("undefined" != 38..toString()) << 2 % {} >= (b_2 && (b_2.NaN += -3 >> 4 >> (23..toString() ^ 5)))))) < ((b_2 && (b_2[[]] += (((false != []) + (Infinity === -3) !== ("" != 25 | NaN <= "bar")) << (("undefined" > "object") >> (-0 ^ -2) || (b_2 += 1 - 5, 
        23..toString() && 38..toString())), (c = c + 1, true) % (b_2 && (b_2.null += (1, 
        -5))) + (b_2 && (b_2.null ^= ("number" > -5) * ("function" !== ([ , 0 ].length === 2)))) ^ ((5, 
        "function") << -1 * 24..toString()) + (22 >>> "" || -3 + [])) || +((c = c + 1, 24..toString() > NaN) == (3 ^ 0) % (-2 >> true)) == (("object" ^ 2 ^ (-2 | [ , 0 ].length === 2), 
        (24..toString() >> Infinity) * (b_2 && (b_2.foo = {} >>> 24..toString()))) === ("function" < ([ , 0 ].length === 2) ^ [ , 0 ][1] + 3) >= (("object" == "number") > 5 - "object")))) !== (c = c + 1, 
        b_2 && (b_2[{
            b: a++ + -((5 > NaN >= 23..toString() + "foo") / ((1 > false) % (NaN & 24..toString()))),
            length: (c = c + 1) + /[abc4]/.test(((c = 1 + c, (5 < 5 | (3 | "foo")) - (("function" === 0) >> (null == NaN))) || b || 5).toString()),
            undefined: b = a,
            a: (c = c + 1) + [ (c = 1 + c, b_2 && (b_2[a++ + b--] /= ((0 | "") > "number" >>> "number") / ([ , 0 ][1] !== 3 & (b_2 && (b_2.var = -5 <= Infinity))))), ,  ]
        }] += (-1 % "undefined" <= {} - [ , 0 ][1]) << (-3, -4) - (c = c + 1, true) << ((b_2 && (b_2[a++ + ((c = 1 + c, 
        c = c + 1, b_2 && (b_2.Infinity /= 0 < -3 ^ true % 3)) || a || 3).toString()] = (Infinity <= NaN) / (false && "object"))) | (5 ^ "foo") != {} + 25))) << ((b_2 && (b_2[(c = c + 1) + a--] = (b_2 -= 1 == /[a2][^e]+$/) > (false || [ , 0 ].length === 2) & (-3 != 25) >> (3 && "number") & ({} === [] | (b_2 && (b_2[(c = 1 + c, 
        (4 << 1) / (c = c + 1, NaN) >= ((23..toString() ^ 4) === [ , 0 ][1] * null))] /= -0 != 5)) || (5 | 24..toString()) + "undefined" * -1))) === ((24..toString() + -1 | 22 < false) >= (b_2 && (b_2.c = (Infinity <= -3) >>> ([ , 0 ][1] >>> undefined))) && (3 > "bar") % ("function" > 22) / ("" > "foo" > ("bar" !== 5)))));
        this[[ 0 === 1 ? a : b, a++ + {
            undefined: void (b_2 && (b_2[[ , 0 ].length === 2] = 23..toString() >>> false >> ([] !== "function") & ([ , 0 ][1] !== Infinity && "foo" == 1)))
        }.in, (c = c + 1) + ((a++ + a++ || 9).toString()[--b + ~(((-4 ^ "bar") <= -0 + 24..toString()) - ((24..toString() == 1) + (38..toString() + Infinity)))] || a || 3).toString(), --b + (1 === 1 ? a : b), b_2 && b_2[!b ? {
            NaN: typeof bar_2 != "special",
            "\t": --b + ((b_2 <<= true ^ null) % (24..toString(), 25) || (NaN > "number") / (b_2 && (b_2.Infinity = 1 || -2))),
            "-2": --b
        }.NaN : [].c] ]] = (((b_2 && (b_2.null = -2 >= 2 < 1 - 38..toString() == (null << "bar" || -5))) + (((b_2 && (b_2[(c = 1 + c, 
        ([ , 0 ][1] ^ Infinity || -0 != 2) < ((2, "foo") | -3 - 1))] *= false | 2)) >= ([ , 0 ].length === 2 & [ , 0 ][1])) - (-4 >> -1 == "" >> 5))) % (("function" % -4 - (false | Infinity)) * ((c = c + 1, 
        38..toString()) ^ 2 - undefined) ^ (c = c + 1, 25 % true) != (b_2 && (b_2.in = 24..toString() == ([ , 0 ].length === 2))) >>> undefined % true) / (((-5 & 24..toString()) % ("number" << "object") & (-0 && 4) !== (NaN & [ , 0 ][1]) || delete {} === (5 && 3) !== ("foo" || "undefined") << -0 - 25) != (b_2 = ((b_2 && (b_2.in += null - "undefined")) ^ (-2, 
        {})) == !(38..toString() | 23..toString())) * (([ , 0 ][1] * 4 < -2 << -3) >>> (("number" ^ 22) < 0 >> "bar"))) > (b_2 && (b_2[!function b() {
            {
                var brake21 = 5;
                while ((c = c + 1) + ((c = 1 + c, (b_2 && (b_2.Infinity += 5 !== 23..toString() === ("object" && 1))) === 0 >> ([ , 0 ].length === 2) <= ([] ^ "object")) || 8).toString()[(c = 1 + c, 
                ~((-1 || -2) >>> (25 ^ -0)))] && --brake21 > 0) {
                }
            }
            try {
                {
                    var brake24 = 5;
                    do {
                        c = 1 + c, ([ , 0 ][1] >= -0 & "object" / {}) / (-0 - 5 > (c = c + 1, /[a2][^e]+$/));
                    } while ((c = 1 + c, (c = c + 1, /[a2][^e]+$/ % /[a2][^e]+$/) <= ("function" > 24..toString() >= (b_2 && (b_2.undefined += undefined <= 3)))) && --brake24 > 0);
                }
            } catch (b) {
                c = 1 + c, (3 >= -2 && {} >>> 38..toString()) % ((b_2 && (b_2.null = -1 < 24..toString())) / (-5 ^ 22));
                c = 1 + c, ({} + Infinity || 24..toString() * 0) | void -2 != (-1 | "undefined");
            }
            {
                return b += a;
            }
        }()] += ((4 | "function") === (-3 === -3)) % ("bar" / 5 >>> (-0 ^ 25)) + ((3 << null || "" != null) + (c = c + 1, 
        b_2 >>>= -3 == 3)) | delete (b_2 && (b_2.in += "function" < 2)) >>> (("number" != "number") >= ("", 
        23..toString())) !== ((b_2 && (b_2[(c = 1 + c, (undefined >> 24..toString() !== (-5 & "foo")) << -(38..toString() >> 3))] += -5 << -2)) - ({} == 0) & (c = c + 1, 
        Infinity == "foo")))) % ((b_2 && (b_2[function parseInt_1() {
            L127604: for (var brake29 = 5; (c = 1 + c, ((/[a2][^e]+$/, 2) <= (-0, /[a2][^e]+$/)) >> (-0 === 24..toString()) - ("function" > {})) && brake29 > 0; --brake29) {
                c = 1 + c, (23..toString() & 2 | /[a2][^e]+$/ ^ "foo") !== 3 > -1 <= (-3 <= "undefined");
            }
        }] += (c = c + 1, (-1 & -3) !== true <= 23..toString()) % ((-2 <= "function" == -2 >= -4) <= (b_2 += [] || true) >>> (-3 != -0)))) ^ ("undefined" >= "number" < (3 ^ -2) ^ (c = c + 1, 
        24..toString()) >>> (undefined | [ , 0 ].length === 2)) >= (0 + 4 ^ true != 25 | (b_2 && (b_2.NaN >>>= "bar" <= -0) || "function" >>> "foo")))) / (((3 << 4 << (b_2 && (b_2[(c = 1 + c, 
        (c = c + 1, 4 === "number") <= (c = c + 1, 22 >= "foo"))] += true >= "number")), 
        b_2 && (b_2.undefined >>= null + 23..toString() >> (-5 == Infinity))) >> (("foo" >= false & {} << ([ , 0 ].length === 2)) >>> (-0 != "undefined", 
        undefined !== "foo")) ^ ((b_2 && (b_2.foo = (b_2 && (b_2[(c = 1 + c, void (/[a2][^e]+$/ !== []) >>> ("undefined" / 3 ^ [ , 0 ].length === 2 == "number"))] = [ , 0 ][1] || "object")) | 4 << -3)) - (b_2 && (b_2.undefined >>>= (38..toString() || "object") ^ 5 & 24..toString())) | (2 ^ 2) + (24..toString() >>> "number") === ~(b_2 && (b_2.c <<= NaN & -3))) && (([ , 0 ][1] & 1) >= (23..toString() == 0) <= (/[a2][^e]+$/ > "function") - (b_2 && (b_2[(c = 1 + c, 
        (("number" || []) ^ (b_2 = 3 !== {})) - (false * [ , 0 ][1] == /[a2][^e]+$/ / 38..toString()))] -= ([ , 0 ].length === 2) + "")), 
        void 3 >> 3 % -5 <= (3 != NaN && 1 >> "")) >> ((null != /[a2][^e]+$/) - ("number" << 23..toString()) + ("bar" - "number" <= -2 / "")) % ((1 ^ 24..toString()) >> (-0 == NaN) & (c = c + 1, 
        [] % 5))) | (b_2 = ((2 ^ NaN && [] >= []) >>> (Infinity === "" !== 0 % NaN) && (1 & -3 || b_2 && (b_2[(c = 1 + c, 
        (c = c + 1, undefined) > (-2 >= ([ , 0 ].length === 2)) && ([] != undefined && (b_2 && (b_2[(c = 1 + c, 
        b_2 += (c = c + 1, true ^ 38..toString()) * (void "undefined" !== "" <= 38..toString()))] = NaN === "bar"))))] = NaN <= 3)) / (NaN >= 5 || [ , 0 ][1] | false) && true % {} % (0 & -5) + ((25 & 23..toString()) >> delete "function") >= (("undefined" % null || "object" * [ , 0 ][1]) <= (NaN > undefined) << (b_2 = 0 + null)), 
        -((c = c + 1, c = c + 1, NaN >> undefined) !== !(b_2 && (b_2.Infinity |= Infinity - /[a2][^e]+$/), 
        38..toString() > "object")))));
        this[(c = c + 1) + b++] += (b_2 += ((-2 == [ , 0 ][1] & /[a2][^e]+$/ != true, -0 <= 3 > (null || "function")) == (-(-2 < []) | (-"object", 
        -5 - null))) / (c = c + 1, +("number" | 38..toString()) >= ([], -0) % (false * 0)) >= (c = c + 1, 
        (c = c + 1, (38..toString() | "undefined") >= (5 & 5)) === ([] - -0 === (-3 !== -1) !== !4 <= undefined / [ , 0 ][1]))) << ((c = c + 1, 
        -{} ^ 4 >> "foo") > ((23..toString(), true) & -0 + 25 || 38..toString() % undefined ^ 22 != -4) == (b_2 && (b_2[--b + +(delete (b_2 && (b_2.undefined >>>= "number" > "number")) % (0 !== 23..toString() === !38..toString()))] /= (("bar" | 24..toString()) >>> (-5 ^ 24..toString()) && (b_2 && (b_2.a = "foo" == 2)) === (b_2 && (b_2.foo >>>= {} >= -5))) != ((b_2 && (b_2.null += -2 * /[a2][^e]+$/) || 24..toString() === -2) & (5 >> [ , 0 ][1] && "function" | null)))) & (((b_2 && (b_2[(c = 1 + c, 
        ("foo" < "number" || "bar" >= null) ^ (null <= "object") >> (true << [ , 0 ][1]))] = (-5, 
        ""))) != (0 ^ 2)) >= ((-2 || [ , 0 ][1]) | (b_2 && (b_2[(c = 1 + c, delete (b_2 += -4 === {} || -[]))] = "function" >> -0))), 
        2 * -1 === "foo" >= -2, 5 * NaN >= void 38..toString()) >> (((b_2 && (b_2[b_2 && b_2.Infinity] = delete 0 >= ("function" != 3))) ^ "number" % -5 << (-1 ^ -3)) >= ((c = c + 1, 
        2) == (b_2 = false || NaN)) % (c = c + 1, "foo" & -1))) != -((((c = c + 1, -2) * ("function" ^ -3), 
        -3 ^ -5 ^ "number" >>> -3) < (-1 / 0 == (c = c + 1, /[a2][^e]+$/)) / ((3 >= /[a2][^e]+$/) - (2 + "foo")), 
        (((b_2 = 24..toString() ^ -1) && (b_2 += "function" || 38..toString())) > (!"function" > (NaN | "function"))) - ((4 ^ 0) / (true, 
        undefined) ^ (([ , 0 ].length === 2) >>> 1 ^ undefined & 0))) < ((b_2 && (b_2.a = (0 < undefined === -2 >> 23..toString()) + (("object" ^ Infinity) == null >= 23..toString()))) < (c = c + 1, 
        "foo" << -0 ^ !true) < ((-4 ^ 1) < (b_2 && (b_2.var = 1 + "function")) > Infinity / "number" + (3 << "bar") & (c = c + 1, 
        b_2 && (b_2[--b] = [ , 0 ].length === 2 | "object" && "function" ^ 1)))));
    }() ][--b + {
        b: --b + (b_2 && b_2[a++ + (b_2 && b_2.NaN)]),
        0: 1 === 1 ? a : b,
        NaN: b--
    }.b] && --brake20 > 0) {
        L127605: {
            if ((c = c + 1) + [ a++ + (b_2 && b_2[a++ + [ delete b ].in]), ,  ][--b + +function() {
                {
                    var parseInt_1 = function f2() {
                        for (var brake34 = 5; (c = 1 + c, (true >= 22) - ([ , 0 ].length === 2 ^ "number") === (24..toString() | 3) >= (25 ^ 4)) && brake34 > 0; --brake34) {
                            c = 1 + c, b_2 && (b_2[(c = c + 1) + -0] = b_2 && (b_2.Infinity -= -0 + Infinity << (1 && 24..toString())) || (-3 >> {}) % ("object" > 1));
                        }
                    }(a++ + (0 === 1 ? a : b));
                }
                {
                    var brake37 = 5;
                    while ((-4 - -4) % (-5 ^ -0) < (-5 - -3 & (1 && 3)) && --brake37 > 0) {}
                }
                b--;
            }()]) {
                a++ + 23..toString();
            } else {
                var brake41 = 5;
                L127606: while (--b + (typeof Math_1 == "boolean") && --brake41 > 0) {}
            }
        }
    }
}

console.log(null, a, b, c);

```js
// uglified code
// (beautified)
for (var a = 100, b = 10, c = 0, b_2 = (b++, ((c += 1) + (b = a) || 2).toString()[a++ + a++],
--b, c = 1 + c, b_2 && (b_2.undefined ^= ("bar" === {}) * (5 < (2 === [ , 0 ].length))),
c = 1 + c, c += 1, c = 1 + (c += 1), b_2 && (b_2.var = 3 !== []), /[abc4]/.test(((c += 1) + (b += a) || b || 5).toString()),
a++, /[abc4]/.test(((b += a) || b || 5).toString()), (a++ + "" || 6).toString()[--b + function() {
var t = 5;
do {
c = 1 + c, b_2 && (b_2.undefined = !1);
} while (c = 1 + c, (0 >>> [ , 0 ][1]) - 23..toString() % 1 >= ("number" != "function" * {}) && --t > 0);
var n = (c = 1 + c, !0);
for (var b in n) {
c = 1 + (c = 1 + c), b_2 && (b_2.a = (4 === [] != 0) >= (c += 1, []));
}
}()], void function() {
var t = (b_2 && (b_2.foo += -2 ^ 23..toString()), t && (t.b += ([] >= -0) % (c += 1,
24..toString())), c = 1 + c, c += 1, c = 1 + c, void 24..toString()), n = 5;
do {
b_2 = NaN, c = 1 + (c = 1 + c), 38..toString(), c = 1 + c, 23..toString(), c = 1 + c,
b_2 && (b_2.in |= -4 << -5 * (c += 1, []));
} while (a++ && --n > 0);
}()), brake20 = 5; [ (c += 1) + new function() {
this[3] = (((b_2 += 0 <= 23..toString() % -1) >>> (b_2 && (b_2.a = !1)) !== (0 == (b_2 && (b_2.foo /= (2 === [ , 0 ].length) > -0),
!0))) >= ((b_2 && (b_2[!1 < 5 * {} < (0 | 0 >>> [ , 0 ][1])] += ((2 === [ , 0 ].length) - -2 + (4 <= 38..toString())) * ((2 === [ , 0 ].length) % 38..toString() >>> (/[a2][^e]+$/ & 23..toString())))) <= ((0 != [ , 0 ][1] >>> void 0) >= (b_2 && (b_2.null = 0 != -1 >= {})))) | (0 - (c += 1,
24..toString() + "functionfoo") & 1 >>> ({} >= !1) >> (0 !== 38..toString())) / (((-2 * 23..toString() ^ 0) >>> 23..toString() + "foo") % (1 | (b_2 |= NaN) >>> 0))) / (c += 1,
((0 == (b_2 *= -2 ^ 24..toString()) | (-0 ^ 23..toString() && !1)) == ((b_2 && (b_2[(c += 1) + /[abc4]/.test((a++ + (b = a) || b || 5).toString())] = !0 % (/[a2][^e]+$/ + void 0 >> ("bar" > (2 === [ , 0 ].length))))) & !(0 < (2 === [ , 0 ].length ^ {})))) >= (((b_2 ^= null != 23..toString() + null) === (b_2 && (b_2.undefined += 0 == (2 === [ , 0 ].length) >= -2))) <= ((b_2 && (b_2.NaN = "number")) + 38..toString() / (2 === [ , 0 ].length) ^ !0)) << ((NaN < (1 ^ 38..toString())) >> (("undefined" != 38..toString()) << 2 % {} >= (b_2 && (b_2.NaN += -1 >> (5 ^ 23..toString())))))) < ((b_2 && (b_2[[]] += (b_2 += -4,
23..toString() && 38..toString(), c += 1, !0 % (b_2 && (b_2.null += -5)) + (b_2 && (b_2.null ^= !1 * ("function" !== (2 === [ , 0 ].length)))) ^ 22 + ("function" << -1 * 24..toString()) || +(0 == (c += 1,
24..toString() > NaN)) == ((24..toString() >> 1 / 0) * (b_2 && (b_2.foo = {} >>> 24..toString())) === ("function" < (2 === [ , 0 ].length) ^ [ , 0 ][1] + 3) >= !1)))) !== (c += 1,
(b_2 && (b_2[{
b: a++ + -(!1 >= 23..toString() + "foo") / (!0 % (NaN & 24..toString())),
length: (c += 1) + /[abc4]/.test((c = 1 + c, 3).toString()),
undefined: b = a,
a: (c += 1) + [ (c = 1 + c, b_2 && (b_2[a++ + b--] /= !1 / (3 !== [ , 0 ][1] & (b_2 && (b_2.var = !0))))), , ]
}] += (NaN <= {} - [ , 0 ][1]) << -4 - (c += 1, !0) << ((b_2 && (b_2[a++ + (c = 1 + c,
c += 1, b_2 && (b_2.Infinity /= 1) || a || 3).toString()] = NaN)) | 5 != {} + 25))) << ((b_2 && (b_2[(c += 1) + a--] = (b_2 -= !1) > (2 === [ , 0 ].length) & 1 & ({} === [] | (b_2 && (b_2[(c = 1 + c,
8 / (c += 1, NaN) >= ((4 ^ 23..toString()) == null * [ , 0 ][1]))] /= !0)) || (5 | 24..toString()) + NaN))) === ((24..toString() + -1 | !1) >= (b_2 && (b_2.c = !1 >>> ([ , 0 ][1] >>> void 0))) && NaN)))),
this[[ b, a++ + {
undefined: void (b_2 && (b_2[2 === [ , 0 ].length] = 23..toString() >>> !1 >> ("function" !== []) & ([ , 0 ][1] !== 1 / 0 && !1)))
}.in, (c += 1) + ((a++ + a++ || 9).toString()[--b + ~((-4 <= -0 + 24..toString()) - ((1 == 24..toString()) + (38..toString() + 1 / 0)))] || a || 3).toString(), --b + a, b_2 && b_2[b ? [].c : {
NaN: "special" != typeof bar_2,
"\t": --b + ((b_2 <<= 1) % (24..toString(), 25) || !1 / (b_2 && (b_2.Infinity = 1))),
"-2": --b
}.NaN] ]] = (((b_2 && (b_2.null = !1 < 1 - 38..toString() == -5)) + (((b_2 && (b_2[(c = 1 + c,
([ , 0 ][1] ^ 1 / 0 || !0) < -4)] *= 2)) >= (2 === [ , 0 ].length & [ , 0 ][1])) - !1)) % (NaN * (NaN ^ (c += 1,
38..toString())) ^ (c += 1, 0 != (b_2 && (b_2.in = 24..toString() == (2 === [ , 0 ].length))) >>> NaN)) / (((-5 & 24..toString()) % 0 & -0 != (NaN & [ , 0 ][1]) || !0) != (b_2 = ((b_2 && (b_2.in += NaN)) ^ {}) == !(38..toString() | 23..toString())) * ((4 * [ , 0 ][1] < -2 << -3) >>> !1)) > (b_2 && (b_2[!function t() {
for (var n = 5; (c += 1) + (c = 1 + c, (b_2 && (b_2.Infinity += 5 !== 23..toString() === 1)) === 0 >> (2 === [ , 0 ].length) <= ("object" ^ []) || 8).toString()[(c = 1 + c,
-128)] && --n > 0; ) {}
try {
var b = 5;
do {
c = 1 + c, c += 1;
} while (c = 1 + c, c += 1, NaN <= ("function" > 24..toString() >= (b_2 && (b_2.undefined += !1))) && --b > 0);
} catch (t) {
c = 1 + c, 38..toString(), b_2 && (b_2.null = -1 < 24..toString()), c = 1 + c, {} + 1 / 0 || 24..toString();
}
return t += a;
}()] += NaN + (3 + (c += 1, b_2 >>>= !1)) | (b_2 && (b_2.in += !1), !0 >>> (!1 >= 23..toString()) != ((b_2 && (b_2[(c = 1 + c,
(void 0 >> 24..toString() != 0) << -(38..toString() >> 3))] += -5 << -2)) - (0 == {}) & (c += 1,
!1))))) % ((b_2 && (b_2[function() {
for (var t = 5; c = 1 + c, !1 >> (-0 === 24..toString()) - ("function" > {}) && t > 0; --t) {
c = 1 + c, 23..toString();
}
}] += (c += 1, (-3 !== !0 <= 23..toString()) % (!1 <= (b_2 += [] || !0) >>> !0)))) ^ (!1 ^ (c += 1,
24..toString() >>> (void 0 | 2 === [ , 0 ].length))) >= (5 | (b_2 && (b_2.NaN >>>= !1) || 0)))) / (b_2 && (b_2[(c = 1 + c,
c += 1, !1 <= (c += 1, !1))] += !1), ((b_2 && (b_2.undefined >>= null + 23..toString() >> !1)) >> ((!1 & {} << (2 === [ , 0 ].length)) >>> !0) ^ ((b_2 && (b_2.foo = (b_2 && (b_2[(c = 1 + c,
void 0 >>> (NaN ^ 2 === [ , 0 ].length == "number"))] = [ , 0 ][1] || "object")) | 4 << -3)) - (b_2 && (b_2.undefined >>>= (38..toString() || "object") ^ 5 & 24..toString())) | 0 + (24..toString() >>> "number") == ~(b_2 && (b_2.c <<= 0))) && (23..toString(),
b_2 && (b_2[(c = 1 + c, ("number" ^ (b_2 = 3 !== {})) - (!1 * [ , 0 ][1] == /[a2][^e]+$/ / 38..toString()))] -= (2 === [ , 0 ].length) + ""),
!0 >> (!0 - ("number" << 23..toString()) + !1) % ((1 ^ 24..toString()) >> !1 & (c += 1,
[] % 5)))) | (([] >= []) >>> !0 && 1 / (!1 | [ , 0 ][1]) && (23..toString(), b_2 = 0),
c += 1, c += 1, b_2 = -(0 !== (b_2 && (b_2.Infinity |= NaN), !(38..toString() > "object"))))),
this[(c += 1) + b++] += (b_2 += (0 == (-5 | -(-2 < []))) / (c += 1, +("number" | 38..toString()) >= NaN) >= (c += 1,
c += 1, ("undefined" | 38..toString()) >= 5 == ([] - -0 === !0 != !1 <= void 0 / [ , 0 ][1]))) << (c += 1,
(4 ^ -{}) > (25 & (23..toString(), !0) || 38..toString() % void 0 ^ !0) == (b_2 && (b_2[--b + (b_2 && (b_2.undefined >>>= !1),
1 % (0 !== 23..toString() == !38..toString()))] /= (("bar" | 24..toString()) >>> (-5 ^ 24..toString()) && (b_2 && (b_2.a = !1)) === (b_2 && (b_2.foo >>>= {} >= -5))) != ((b_2 && (b_2.null += NaN) || -2 === 24..toString()) & (5 >> [ , 0 ][1] && 0)))) & (b_2 && (b_2[(c = 1 + c,
!0 ^ !1 >> (!0 << [ , 0 ][1]))] = ""), b_2 && (b_2[(c = 1 + c, b_2 += -4 === {} || -[],
!0)] = 0), (NaN >= void 38..toString()) >> ((0 ^ (b_2 && (b_2[b_2 && b_2.Infinity] = !0))) >= (c += 1,
(2 == (b_2 = NaN)) % (c += 1, 0))))) != (c += 1, c += 1, -((((b_2 = -1 ^ 24..toString()) && (b_2 += "function")) > !1) - (0 ^ (2 === [ , 0 ].length) >>> 1) < ((b_2 && (b_2.a = (!1 === -2 >> 23..toString()) + (0 == null >= 23..toString()))) < (c += 1,
0) < (-3 < (b_2 && (b_2.var = "1function")) > NaN & (c += 1, b_2 && (b_2[--b] = 2 === [ , 0 ].length | "object" && 1))))));
}() ][--b + {
b: --b + (b_2 && b_2[a++ + (b_2 && b_2.NaN)]),
0: a,
NaN: b--
}.b] && --brake20 > 0; ) {
if ((c += 1) + [ a++ + (b_2 && b_2[a++ + [ delete b ].in]), , ][--b + +function() {
!function() {
for (var t = 5; c = 1 + c, !1 - (2 === [ , 0 ].length ^ "number") === (3 | 24..toString()) >= 29 && t > 0; --t) {
c = 1 + c, b_2 && (b_2[(c += 1) + -0] = b_2 && (b_2.Infinity -= 1 / 0 << 24..toString()) || (-3 >> {}) % !1);
}
}(a++);
for (var t = 5; --t > 0; ) {}
b--;
}()]) {
a++, 23..toString();
} else {
for (var brake41 = 5; --b + ("boolean" == typeof Math_1) && --brake41 > 0; ) {}
}
}

console.log(null, a, b, c);

```js
original result:
null 115 103 84

uglified result:
null 115 103 85

minify(options):
{
  "compress": {
    "keep_fargs": false,
    "passes": 3
  }
}

Suspicious compress options:
  collapse_vars
  dead_code
  if_return
  inline
  pure_getters
  side_effects
  unused
bug

All 27 comments

Reduced test case:

$ type test.js
var c = 0;

!function(a_2) {
    a_2 = 0;
}([ {
    0: c = c + 1,
    length: c = 1 + c
}, typeof void function a_1() {
    var NaN_1 = function f1(a_1) {
    }(NaN_1 && (NaN_1.b += (c = c + 1, 0)));
}() ]);

console.log(c);

$ type test.js | node
2

$ uglifyjs test.js -c | node
2

$ uglifyjs test.js -c keep_fargs=0 | node
3

With #2116 applied:

$ cat 2114.js 
var c = 0;

!function(a_2) {
    a_2 = 0;
}([ {
    0: c = c + 1,
    length: c = 1 + c
}, typeof void function a_1() {
    var NaN_1 = function f1(a_1) {
    }(NaN_1 && (NaN_1.b += (c = c + 1, 0)));
}() ]);

console.log(c);
$ bin/uglifyjs 2114.js -c passes=3 -b
var c = 0;

c = 1 + (c += 1), function() {
    var NaN_1 = void (NaN_1 && (NaN_1.b += (c += 1, 0)));
}(), console.log(c);

Notice that reduce_vars did not eliminate the statement
var NaN_1 = void (NaN_1 && (NaN_1.b += (c += 1, 0)));

I recognize it's nonsensical to have a declaration initialization to refer to itself before it has a value, but reduce_vars does know that NaN_1 is undefined at that point - does it not?

reduce_vars hasn't become self-aware... I mean, it registers NaN_1 as having void (NaN_1 && (NaN_1.b += (c += 1, 0))) without discerning between where those NaN_1 are placed.

But you raised a good point - adding it to my TODO list :wink:

reduce_vars hasn't become self-aware

It hasn't?!!

I'm waiting for reduce_vars to create bug reports on itself - and resolve them.

Correction - NaN_1 will get marked as unsafe for substitution right after being assigned the value node from above, as it will immediately descend() into its value and run into its own AST_SymbolRef:
https://github.com/mishoo/UglifyJS2/blob/0a0f4f55912fed32b09c93a2a1efa19edce24e28/lib/compress.js#L320-L321

and resolve them.

This is the vital part of the equation.

I feel like I should be a responsible netizen and figure out the culprit in this, but I also feel rather lazy...

$ node test.js
null NaN NaN 190

$ cat test.js | node
null NaN NaN 132
// original code
// (beautified)
var a = 100, b = 10, c = 0;

try {
    switch (3) {
      case b += a:
        {
            var undefined_1 = function f0() {
                if (--b + /[abc4]/.test(((c = c + 1) + function() {
                    if (c = 1 + c, -4 % "foo" >>> 2 + "object" & [] * false <= (-4 > "foo")) {
                        c = 1 + c, (-2 & "undefined") / (23..toString() >= "") - (false << -4 >> (38..toString() > {}));
                    }
                }() || b || 5).toString())) {
                    for (var brake7 = 5; a++ + (+b ? a++ + +function() {
                        c = 1 + c, ((NaN && "foo") - (c = c + 1, [])) * (/[a2][^e]+$/ ^ 22 ^ (c = c + 1, 
                        [ , 0 ][1]));
                        c = 1 + c, (3 * {} === ("object" ^ "number")) <= ((1 & -0) === false >> -3);
                        c = 1 + c, (a = undefined > -0 && (a && (a[(c = 1 + c, {} * "bar" == (-0 && "foo") ^ (3 == 25 && (-5 || [ , 0 ][1])))] += ([ , 0 ].length === 2) / false))) != ([ , 0 ].length === 2 ^ true) + (c = c + 1, 
                        24..toString());
                    }() : --b + /[abc4]/.test((a++ + [ (c = 1 + c, 38..toString() + -0 - (25 >> -3) <= (5 >>> -1 >= 22 / null)), (c = 1 + c, 
                    (a.NaN = 0 << 22 >>> (-4 >= 3)) ^ (a && (a.a = true < [] > -2 + "undefined"))), (c = 1 + c, 
                    (c = c + 1, -2 <= -0) == (a && (a[(c = c + 1) + ++b] |= NaN / 2 >= (5 > "undefined")))) ][(c = 1 + c, 
                    (-5 >= -4 === (23..toString() !== true)) < (-0 || 3) + (Infinity, "bar"))] || b || 5).toString())) && brake7 > 0; --brake7) {
                        if (a++ + a--) {
                            var expr12 = NaN_1 && NaN_1.c;
                            for (var key12 in expr12) {
                                c = 1 + c;
                                var NaN_1 = expr12[key12];
                                try {
                                    c = 1 + c, (-5 >> 24..toString() << ("number" & {})) - ((-1 > 24..toString()) << (c = c + 1, 
                                    []));
                                } catch (a) {
                                } finally {
                                }
                            }
                        } else {
                            switch ((c = c + 1) + (NaN_1 && NaN_1.var)) {
                              case --b + --b:
                                c = c + 1;
                                {
                                    var a_2 = function f1(b_1, c, a_1) {
                                    }((c = 1 + c, (+"bar" ^ true >>> -0) != (c = c + 1, null) - (a_2 && (a_2.a = 5 >> 5))));
                                }
                                break;

                              default:
                              case --b + {
                                    length: a_2 && a_2.Infinity
                                }.NaN:
                                {
                                    var b = function f2(b_2, NaN, a) {
                                    }((c = 1 + c, ("object" + -2 == -2 < /[a2][^e]+$/) >> (null < "function") / (c = c + 1, 
                                    0)));
                                }
                                {
                                    return;
                                    a++ + +(!(-4 % 22) >> (("" === -1) >= (-3 !== -0)));
                                }
                                break;

                              case a++ + !a:
                                {
                                    var brake20 = 5;
                                    L89960: while ((b += a) && --brake20 > 0) {
                                        var brake21 = 5;
                                        L89961: do {
                                            c = 1 + c, (Infinity && -1) < (-2 ^ undefined), false % "bar" + (a_2 <<= -0 - 0);
                                        } while ((c = 1 + c, (22, 5) % (2 + -0) * (undefined % 5 % ("", false))) && --brake21 > 0);
                                    }
                                }
                                break;
                            }
                        }
                    }
                }
                switch (1 === 1 ? a : b) {
                  case --b + !function() {
                        c = c + 1;
                        var a_2_1 = !((Infinity && Infinity) === (-0 !== "") ^ (NaN_1 && (NaN_1[(c = 1 + c, 
                        ((NaN_1 += -5 || false) && ("foo", -1)) >> ((true ^ 2) != (true ^ undefined)))] = "" & NaN)) === -0 >= "foo");
                        {
                            var Infinity_2 = function f3(a_2_1) {
                            }((c = 1 + c, (("" ^ -5) < (a_2_1 && (a_2_1[(c = 1 + c, (true * "number" ^ (22, 
                            -2)) / (NaN_1 = 4 > true !== (1 ^ 5)))] = "undefined" >> "undefined"))) >>> ((5 || 22) < (Infinity_2 = (3, 
                            -0)))));
                        }
                        var Infinity_2_2 = a++ + {
                            Infinity: (c = 1 + c, Infinity_2_2 && (Infinity_2_2[(c = c + 1) + [ (c = 1 + c, 
                            ([ , 0 ].length === 2 !== null && 3 !== 24..toString()) < (NaN_2 && (NaN_2.NaN >>= (-2 >>> 2) / (a_2_1 = "undefined" >= null)))), (c = 1 + c, 
                            (38..toString() !== 1 ^ -4 & "number") > (void "" ^ + -0)) ][(c = 1 + c, Infinity_2 && (Infinity_2.null %= (-0 >>> []) % (Infinity * 38..toString()) - (-0 !== "bar") % +38..toString()))]] = (NaN_2 && (NaN_2.Infinity += 4 ^ false)) != -0 >= {}) && 22 - null === (NaN_2 = 22 - -1)),
                            length: (c = 1 + c, ([ , 0 ][1] < -2 ^ ([ , 0 ].length === 2) > []) >>> (-5 % "object" < (NaN_1 && (NaN_1.null = -0 >= {}))))
                        }, NaN_2 = (([ , 0 ][1] | 24..toString()) - (-2 ^ undefined)) * ((-2 & 22) > -1 + "undefined");
                    }():
                    var a_1 = "foo";

                  case a++ + [].length:
                    if ((c = c + 1) + {}[a++ + (1 === 1 ? a : b)]) {
                        L89962: for (var brake30 = 5; a++ + [ (c = 1 + c, a_2 && (a_2[--b + (("foo" >= true) * (3 || -2) < void (([ , 0 ].length === 2) > -4))] += (-2 >= 23..toString()) >> (24..toString() != -2) >>> ((NaN_1 && (NaN_1[(c = 1 + c, 
                        (a_2 && (a_2.b <<= (22 | -0) ^ ([ , 0 ].length === 2 ^ -2))) >= (a_1 += (NaN_1 && (NaN_1[(c = 1 + c, 
                        2 - -1 < (0 | 3), -4 % ([ , 0 ].length === 2) + -5 * null)] = ([ , 0 ].length === 2) * "undefined")) != 2 < 5))] += /[a2][^e]+$/ >= 0)) ^ -5 << -0))), (c = 1 + c, 
                        (NaN_1 && (NaN_1[a++ + --a] ^= (24..toString() == undefined) >> (([ , 0 ].length === 2) >= 2))) === (-5 | Infinity) >= (([ , 0 ].length === 2) >= 25)), (c = 1 + c, 
                        (NaN && -0, null < -5) & (a_2 = 4 >> -0 ^ "number" !== "undefined")), (c = 1 + c, 
                        ~(23..toString() + "foo" === false >= -1)), (c = 1 + c, (("foo" != true) > (24..toString() == 4)) / (24..toString() > -0 | "object" / -2)) ][(c = 1 + c, 
                        (/[a2][^e]+$/ + 3 ^ -5 % -1) >> (false | -5) - (25 > 38..toString()))] && brake30 > 0; --brake30) {
                            c = c + 1;
                        }
                    }
                    (c = c + 1) + ((true / -2 || NaN ^ true) && (NaN_1 && (NaN_1[(c = 1 + c, ((23..toString() >= ([ , 0 ].length === 2)) >> (undefined !== undefined)) - ((38..toString() || 38..toString()) < (a_1 && (a_1[(c = 1 + c, 
                    ("number" * 0 >= ([ , 0 ].length === 2 ^ 25)) % ([ , 0 ][1] >>> ([ , 0 ].length === 2) ^ ~23..toString()))] = 2 - 3))))] <<= "foo" << "number")) == (24..toString() ^ 2));
                    break;

                  default:
                  case !((NaN_1 = (0 ^ 5) >>> (24..toString() >> 5)) % (-2 >= [ , 0 ][1] > (1 || -0))):
                    switch (a++ + typeof c_1) {
                      case a_2 && (a_2.null = ("undefined" << "undefined" === (a_1 = 0 >>> /[a2][^e]+$/)) - (/[a2][^e]+$/ != undefined != (a_2[(c = 1 + c, 
                        3 * "" != 38..toString() > 24..toString(), (5 === {}) < (24..toString() !== {}))] = 25 * 25))):
                        break;

                      case [].var:
                        c = 1 + c, [ , 0 ][1] < 0 !== {} + "" !== (-2 / Infinity === true + 4);
                        break;

                      case 1 === 1 ? a : b:
                        for (var brake35 = 5; (c = 1 + c, ("object" | 0) === "undefined" * 24..toString(), 
                        -4 >= "bar" ^ (c = c + 1, [ , 0 ].length === 2)) && brake35 > 0; --brake35) {
                            c = 1 + c, -(NaN_1 && (NaN_1.foo += null ^ 24..toString()) && (NaN_1 && (NaN_1.NaN = -3 <= [])));
                        }
                        return;
                        break;

                      case 0 === 1 ? a : b:
                        var b_2 = (c = 1 + c, (-2 ^ "") > "bar" + 4 != (NaN_1 && (NaN_1[a_2 ^= (void "number" > (-2 !== {}), 
                        (5 != "number") << ("undefined" !== -0))] = -4 >> [] & (c = c + 1, -1))));
                        break;
                    }
                    return;
                    break;
                }
            }(a++ + ((-1 + -1 ^ (-3 | 24..toString())) !== (0 || Infinity) * (-5 * 4)));
        }
        break;

      default:
        (c = c + 1) + {
            0: --b + {
                in: (c = c + 1) + (0 === 1 ? a : b),
                null: --b + ((4 || []) | 1 ^ 38..toString()) % (undefined_1 = (undefined_1 && (undefined_1[(c = 1 + c, 
                (-2 || "function") >= false * 0 || (undefined_1 && (undefined_1.in = 2 != /[a2][^e]+$/)) ^ (0 ^ -5))] = false < 24..toString())) !== (-0 ^ 22))
            }.a,
            in: typeof parseInt_1 === "boolean"
        };
        {
            var NaN = function f4(bar_2, b, b) {
                {
                    var brake42 = 5;
                    L89963: do {
                        switch (0 === 1 ? a : b) {
                          case c = c + 1, ([ , 0 ].length === 2 & NaN) == "undefined" % 1:
                            switch (a++ + (bar_2 && bar_2[(c = 1 + c, (24..toString() / 23..toString() & (0 && {})) !== (undefined_1 && (undefined_1[a++] += (-1 != -4) <= ("number" != -0))))])) {
                              default:
                              case a++ + (1 === 1 ? a : b):
                                c = 1 + c, bar_2 = (2 >= 3 | -4 & Infinity) % (-5 > 38..toString() !== (bar_2 += /[a2][^e]+$/ >>> "undefined"));
                                break;

                              case +function undefined_1_2() {
                                }():
                                c = 1 + c, (undefined_1 && (undefined_1[(c = 1 + c, +"undefined" >= ([ , 0 ][1] == 1) >= (!1 === Infinity / 24..toString()))] += 2 ^ 0)) >>> (/[a2][^e]+$/ && "") | ([ , 0 ][1] & 2) === "number" * NaN;
                                break;

                              case b += a:
                                c = 1 + c, (/[a2][^e]+$/ == ([ , 0 ].length === 2)) > (5 && 38..toString()) ^ (null << 25, 
                                ([ , 0 ].length === 2) % [ , 0 ][1]);
                                break;
                            }
                            var b_2 = (c = c + 1) + function() {
                            }();

                          case a++ + (--b + 5 || a || 3).toString():
                            break;

                          case {
                                in: (c = c + 1) + {
                                    length: (c = 1 + c, (23..toString(), 5) <= ("object" <= 3) < (c = c + 1, -2) << (5 ^ Infinity)),
                                    0: (c = 1 + c, ~(c = c + 1, "number") << (-2 >= -5 !== (-0, /[a2][^e]+$/))),
                                    0: (c = 1 + c, (bar_2 && (bar_2.c = 25 / 38..toString())) == -3 && ([ , 0 ][1] / 38..toString(), 
                                    3 << 22)),
                                    null: (c = 1 + c, (25 === 25) >>> "function" / Infinity && (-0 > null) << (([ , 0 ].length === 2) >= 38..toString())),
                                    in: (c = 1 + c, -3 / -5 - (undefined_1 && (undefined_1.c %= null * 25)) >> (/[a2][^e]+$/ / -5 != (5 && "")))
                                }[(c = 1 + c, 24..toString() * Infinity / (25 << 22) != 38..toString() >> 0 > (b_2 && (b_2[(c = 1 + c, 
                                (Infinity > "function" != (-4 ^ true)) <= ((bar_2 += "function" ^ "object") && 5 & undefined))] = 25 < Infinity)))],
                                3: (c = c + 1) + delete a,
                                c: --b + (c = 1 + c, ([ , 0 ].length === 2 || {}) >>> (38..toString() === "undefined") | 38..toString() <= "foo" ^ 22 > "foo"),
                                Infinity: typeof NaN_1 == "symbol"
                            }:
                            {
                                return;
                                (c = c + 1) + (bar_2 && (bar_2.b = (/[a2][^e]+$/ !== true) - 2 / Infinity) || ((c = c + 1, 
                                4) || /[a2][^e]+$/ % [ , 0 ][1]));
                            }

                          default:
                            c = c + 1;
                        }
                    } while (--b + --b && --brake42 > 0);
                }
                {
                    var a_2 = function f5(undefined_1, b_2) {
                        function f6(NaN, parseInt_2, a_2) {
                            c = 1 + c, (parseInt_2[/[abc4]/.test(((c = 1 + c, undefined + "object" < (NaN & "object") | (c = c + 1, 
                            "number" !== 0)) || b || 5).toString())] -= (b_2 && (b_2.in = null >> "undefined")) | (bar_2 && (bar_2[(c = 1 + c, 
                            "bar" > -3 >= (-4 | "number") != ((a_2 = 5 ^ {}) & 1 >>> Infinity))] = null >>> undefined))) - (bar_2 && (bar_2.Infinity += 5 >> -0 >= (bar_2 && (bar_2.in = 2 === 22))));
                            c = 1 + c, delete (-3 << -2 || -5 ^ -0);
                        }
                        var b_2 = f6(null, NaN);
                        function f7(bar_2_1) {
                            c = 1 + c, bar_2_1 = 24..toString() + undefined > (-5 ^ undefined) == (38..toString() >= 2 === (undefined_1 && (undefined_1.b = 4 >= NaN)));
                            c = 1 + c, 38..toString() >= /[a2][^e]+$/ > (bar_2_1 >>>= null * 4) ^ "" >> "object" & 0 < true;
                        }
                        var Math = f7("object");
                        function f8(Math, undefined_2) {
                            c = 1 + c, (undefined_1.null = [ , 0 ][1] !== "bar") << (5 ^ -0) && ("undefined" & Infinity) % (c = c + 1, 
                            23..toString());
                            c = 1 + c, (bar_2 && (bar_2[--b + new function a_1() {
                                this.a = -3 && -2;
                                this[(c = 1 + c, -3 == -1 || Infinity & "bar" || (undefined_1 = -3 >>> 23..toString()) % ("number" > ([ , 0 ].length === 2)))] >>>= 0 === [ , 0 ][1];
                                this[(c = 1 + c, ((b_2 && (b_2[(c = 1 + c, -0 === -5 ^ (b_2 && (b_2[(c = 1 + c, 
                                ((Infinity == 0) >>> (3 >= 25)) - (null % 23..toString() <= (a_1 && (a_1[(c = 1 + c, 
                                ("object" <= "number" >= (-1 > -0)) >>> (4 % "bar" ^ [] > ([ , 0 ].length === 2)))] += -4 & "undefined"))))] = 5 >= 0)) | ("foo" !== {}) - (([ , 0 ].length === 2) >>> null))] <<= -1 - -2)) - (c = c + 1, 
                                "object")) % (NaN <= {} != (undefined !== false)))] = Infinity * -3;
                            }()] = (bar_2 && (bar_2.NaN *= 4 != 25)) * ([] + 38..toString()))) / (undefined_1 && (undefined_1[(c = c + 1) + (b <<= a)] += (undefined_1 = -2 * -5) ^ (undefined_1 && (undefined_1.foo += 22 / -0))));
                        }
                        var bar = f8(2);
                        function f9() {
                        }
                        var b = f9("object");
                    }((c = c + 1) + (1 === 1 ? a : b));
                }
            }(--b + -b);
        }

      case a++ + !a:
      case typeof (1 === 1 ? a : b):
    }
} catch (b_1) {
    {
        {
            var brake59 = 5;
            do {
                {
                    var Math = function f10() {
                        function f11(parseInt_1, undefined_2, c_2) {
                        }
                        var bar_2 = f11("bar", [ , 0 ][1], {});
                        function f12() {
                            c = 1 + c, ((bar_2 = 38..toString() < 24..toString()) && true >>> 0) ^ NaN / [ , 0 ][1] < 22 >> -0;
                            c = 1 + c, ((25 == Infinity) >> (2 <= false)) * (-5 | 1 || "object" / -3);
                        }
                        var b_2 = f12();
                        function f13(b_1, arguments_2, b) {
                            c = 1 + c, ("" * [], "function" >> {}) != (-4 >= -5) - ({} + 5);
                            c = 1 + c, (-1, null) !== "number" * 23..toString() ^ (false >= "bar" || 22 > 5);
                        }
                        var a_1 = f13("foo", 23..toString());
                        function f14() {
                            c = 1 + c, (38..toString() && null && "" % -1) == (b_1 && (b_1[(c = 1 + c, delete "undefined" >> (-4 && [ , 0 ].length === 2) == (c = c + 1, 
                            NaN ^ false))] = "foo" - "bar")) % (NaN <= "foo");
                            c = 1 + c, (-5 & 23..toString()) >>> ("function" !== /[a2][^e]+$/) | (bar_2 && (bar_2.null %= (bar_2 && (bar_2[(c = 1 + c, 
                            (25 === false) % (24..toString() ^ -4) ^ (0 ^ 25) !== -0 < "bar")] += 22 <= [])) == (-5 ^ "number")));
                        }
                        var a_1 = f14("function");
                    }(new function() {
                        this.b >>= ((true < 23..toString()) - (22 < 22) ^ (38..toString() & "object") + (2 > -0)) != ((undefined_1 = (22 | true) >>> 23..toString() - true) || (c = c + 1, 
                        4) == (5 == 1));
                        L89964: {}
                        c = c + 1;
                        -(4 << false << (NaN | "undefined") === (-1 === NaN) <= -4 >> 23..toString());
                        {
                            var brake70 = 5;
                            do {
                                var b_2 = (c = 1 + c, ([] ^ 25 ^ -3 != false) <= (c = c + 1, "bar" < 23..toString())), b = (c = 1 + c, 
                                (b_1 |= void 22 == 5 <= [ , 0 ][1]) / (b_1 && (b_1[(([] | undefined) << (false !== [ , 0 ][1]), 
                                ("" != -0) > ("object" == false))] = false & -0 | -4 > "object")));
                            } while (+function b() {
                            }() && --brake70 > 0);
                        }
                    }());
                }
            } while ({} && --brake59 > 0);
        }
    }
    if (--b) {
        var brake73 = 5;
        do {
            (c = c + 1) + !((null >> 23..toString() || undefined_1 && (undefined_1.Infinity = 22 >> 0)) - ((undefined_1 = Infinity >> Infinity) + (-4 || Infinity)));
        } while ((c = c + 1) + (b = a) && --brake73 > 0);
    }
} finally {
    {
        var brake75 = 5;
        do {
            {
                var brake76 = 5;
                do {
                    {
                        var a = function f15(bar_2, foo_2) {
                            ({
                                length: b++,
                                a: b += a,
                                c: --b + !b,
                                foo: --b + (b += a),
                                "": b--
                            }).foo;
                            --b + [].NaN;
                        }((c = c + 1) + (typeof foo != "crap"));
                    }
                } while ((undefined_1 && (undefined_1.c = 4 ^ "foo")) - (NaN != 1) != "number" << ([ , 0 ].length === 2) >> (1 > -4) && --brake76 > 0);
            }
        } while (a++ && --brake75 > 0);
    }
    {
        var expr80 = --b + typeof ((c = c + 1) + ((3 & 25) << (NaN !== -2) <= (-4 <= Infinity) / (false, 
        NaN)));
        L89965: for (var key80 in expr80) {
            c = 1 + c;
            var a_2 = expr80[key80];
            if (a++ + void a) {
                var c = function f16(a_1, b_1, parseInt_2) {
                    L89966: for (var brake83 = 5; --b && brake83 > 0; --brake83) {
                        return --b + (2 || 8).toString()[{
                            Infinity: (c = 1 + c, ("function" ^ 5) >>> ("undefined" << 23..toString()) & ([] && "undefined") == "foo" <= -2),
                            a: (c = 1 + c, (a_2 += 1 << -5 >>> ([ , 0 ].length === 2) * "object") !== (undefined | 2) >>> (false << 38..toString())),
                            a: (c = 1 + c, b_1 && (b_1[[ (c = 1 + c, (/[a2][^e]+$/, []) % (1 >>> "function") == (2 < /[a2][^e]+$/) << (5 <= [])), (c = 1 + c, 
                            [ , 0 ][1] - "object" > 5 / 1 ^ ("object" >> "function") / (-0 == /[a2][^e]+$/)), (c = 1 + c, 
                            a_1 |= ("function" === "foo", "object" ^ /[a2][^e]+$/) % (c = c + 1, 23..toString() % -1)) ]] = ("foo" ^ -5 || 1 + 2) >>> (b_1 += "" >> "number" << ([ , 0 ][1] || Infinity))))
                        }.NaN];
                    }
                    try {
                        {
                            var bar_1 = function f17() {
                                c = 1 + c, c = c + 1, (a_2 && (a_2.c %= Infinity << "bar")) != {} > "function";
                                c = 1 + c, delete ("object" < "object", "function", true);
                            }((-5 * 25 == (Infinity == null)) <= 2 >>> [ , 0 ][1] >>> ~-0);
                        }
                    } finally {
                        for (var brake89 = 5; (0 === 1 ? a : b) && brake89 > 0; --brake89) {
                            L89967: {
                            }
                        }
                        {
                            c = 1 + c, 23..toString() * 1 / (4, "object") << (b_1 && (b_1.b = (undefined_1 += -2 !== "") || [ , 0 ].length === 2 & {}));
                            c = 1 + c, (-5 >= "undefined") << ("function" !== 25) < (2 ^ 1) % -2;
                            c = 1 + c, !((24..toString(), 5) <= "bar" - 25);
                        }
                    }
                }((a_2 ^= 3 << 38..toString()) % (25 * "number") > (23..toString() - []) % ([ , 0 ].length === 2 !== ([ , 0 ].length === 2)));
            } else {
                var Infinity = function f18(Math_1, b) {
                    {
                        var expr96 = (c = c + 1) + (a_1 && a_1.a);
                        L89968: for (var key96 in expr96) {
                            c = 1 + c;
                            var a_1 = expr96[key96];
                            {
                                var brake97 = 5;
                                L89969: while (typeof foo_1 == "boolean" && --brake97 > 0) {
                                    var b = function f19(b_1, a_1) {
                                    }((c = 1 + c, ((/[a2][^e]+$/ ^ 38..toString()) << -4 * undefined) * ({} % undefined ^ ("undefined" | false))));
                                }
                            }
                        }
                    }
                }((c = c + 1) + [ --b + function arguments_1() {
                    {
                        var expr100 = (c = 1 + c, ((c = c + 1, "number") != (false && [ , 0 ][1])) >>> (1 >= 2 >= (24..toString() >= 0)));
                        for (var key100 in expr100) {
                            c = 1 + c, -(([ , 0 ].length === 2) < -3 === (a_2 && (a_2[(c = 1 + c, (/[a2][^e]+$/ < ([ , 0 ].length === 2)) / (24..toString() - null) << "object" % 4 % (23..toString() || [ , 0 ][1]))] -= undefined % {})));
                        }
                    }
                }(), --b + b--, (c = c + 1) + ((2 ^ "function") >>> ("foo" ^ undefined)) * ("" << 38..toString() < 38..toString() >> 22), (c = c + 1) + !function b_2() {
                    {
                    }
                    var a_2 = (c = 1 + c, ("" & "undefined") << (25 & 3) <= ("bar" << "number") - (-4 === 0)), undefined_1 = (c = 1 + c, 
                    (0 << 3) / ("bar" * "foo") >= (NaN <= 38..toString() && [] & 22));
                    {
                        var brake104 = 5;
                        while ((c = 1 + c, c = c + 1, (5 < "function") >>> [ , 0 ][1] * null) && --brake104 > 0) {
                            c = 1 + c, ((c = c + 1, -2) || "foo" / "bar") ^ (c = c + 1, 3) % (Infinity >= false);
                        }
                    }
                }() ]);
            }
        }
    }
}

--b + typeof ((c = c + 1) + +b);

console.log(null, a, b, c);



md5-e8397544b9ab875041660be18be18540



```js
original result:
null NaN NaN 190

uglified result:
null NaN NaN 132

minify(options):
{
  "compress": {
    "keep_fargs": false,
    "passes": 3
  }
}

Suspicious compress options:
  collapse_vars
  evaluate
  inline
  passes
  reduce_vars
  sequences
  unused

OT: as I was collecting these failed test cases and found this one, one of the false positives was blowing up node itself with an exception thrown from Stream.cork() about Math.floor() being absent.

And then I look at the test case and it's like:

var a = ..., b = ..., c = ...;

function f0() { ... }
var Math = f0();

console.log(...);

... yeah, that would blow that up :sweat_smile:

Regarding the last fuzz test case discovered: https://github.com/mishoo/UglifyJS2/issues/2114#issuecomment-309218600

Suspicious compress options:
collapse_vars
...
inline

It would appear to be shallow copy related based on those suspicious compress options.

As we know, collapse_vars has an assumption that it's the owner of the single-use variable's value. If it were to be changed to deep copy that variable value AST rather than steal and null it, it might avoid this class of errors. But then again, the deep copy probably would likely introduce another class of errors.

Regarding the last fuzz test case discovered: #2114 (comment)

I'm fairly sure it's a false positive:

$ node test.js
null NaN NaN 190

$ cat test.js | node
null NaN NaN 132

Note that uglify-js isn't involved at all to produce the same difference of results above.

Note that uglify-js isn't involved at all to produce the same difference of results above.

You beat me to it - just discovered the same thing.

$ cat bug2.js 
var a = 100, b = 10, c = 0;

try {
    c = c + 1;
    var NaN = function n(e, t, t) {
        var i = function n(i, a) {
            function b(n, i, b) {
                c = 1 + c, (i[/[abc4]/.test(((c = 1 + c, undefined + "object" < (n & "object") | (c = c + 1, 
                "number" !== 0)) || t || 5).toString())] -= (a && (a.in = null >> "undefined")) | (e && (e[(c = 1 + c, 
                "bar" > -3 >= (-4 | "number") != ((b = 5 ^ {}) & 1 >>> Infinity))] = null >>> undefined))) - (e && (e.Infinity += 5 >> -0 >= (e && (e.in = 2 === 22))));
                c = 1 + c, delete (-3 << -2 || -5 ^ -0);
            }
            var a = b(null, NaN);
        }((c = c + 1) + (1 === 1 ? a : t));
    }(--b + -b);
} catch (c) {}

--b + typeof ((c = c + 1) + +b);

console.log(null, a, b, c);
$ node bug2.js 
null 100 8 6

$ cat bug2.js | node
null 100 8 7

That node FUZZ.js vs cat FUZZ.js | node test ought to be the very first test we perform.

That node FUZZ.js vs cat FUZZ.js | node test ought to be the very first test we perform.

If by "we" you mean you and I, yes - that's the first thing I run through to filter out false positives.

Back when I was younger, though, I had the energy and curiosity to work out why Node.js would be affected. :disappointed:

... jokes aside, this is quite a bit more rare than those [Function: 1000001] vs [Function: 1000002] stuff, and it's not exactly difficult to discover and discard.

You beat me to it - just discovered the same thing.

Sorry for burying that at the very top of https://github.com/mishoo/UglifyJS2/issues/2114#issuecomment-309218600 :ghost:

Just by coincidence... similar to https://github.com/mishoo/UglifyJS2/issues/2114#issuecomment-309217559

    var NaN = function n(e, t, t) {
          ... init uses NaN ...
    }();

@alexlamsl If you ever implement this new reduce_vars feature, emitting a warning for this obvious coding error would be nice.

Edit: "obvious coding error" in this case refers to "have a declaration initialization to refer to itself before it has a value", not overriding NaN - which is also terrible.

If by "we" you mean you and I, yes - that's the first thing I run through to filter out false positives.

Sorry for burying that at the very top of #2114 (comment)

Groan - how did I miss that?

If you ever implement this new reduce_vars feature, emitting a warning for this obvious coding error would be nice.

I think this falls under the TODO of multi-segment reduce_vars:

if (a) {
    var key = 1;
    x(key);
} else {
    var key = 2;
    y(key);
}

I've encountered this coding pattern, many of them as switch-cases, in the wild presumbly because it's more human readable.

I think this falls under the TODO of multi-segment reduce_vars:

There's a step in between that I'm failing to see. It's a different situation in my view - it's not in the var decl init. key in both branches is defined by the time it calls x(key) or y(key).

That node FUZZ.js vs cat FUZZ.js | node test ought to be the very first test we perform.

Could that test on the original code be automated as part of test/ufuzz.js so no time is wasted analyzing it?

Edit: after the uglify vs. original test run fails of course - to not waste CPU.

There's a step in between that I'm failing to see.

reduce_vars already treats uninitialised var as being assigned undefined:
https://github.com/mishoo/UglifyJS2/blob/0a0f4f55912fed32b09c93a2a1efa19edce24e28/lib/compress.js#L491

So as we dwell into the initialisation value in the multi-segment case, it should Just Work :tm:

Could that test on the original code be automated as part of test/ufuzz.js so no time is wasted analyzing it?

Sure, it's just a couple of child_process.execSync() with the slight complication of having to write out to a file first.

There's a step in between that I'm failing to see.

reduce_vars already treats uninitialised var as being assigned undefined:

That part I assumed, but I still can't bridge the gap between a case with a var assigned something and later used in another statement versus a case with a var referencing itself in its own init.

What the ufuzz iteration count now, by the way?

I still can't bridge the gap between a case with a var assigned something and later used in another statement versus a case with a var referencing itself in its own init.

When we walk() to an instance of AST_VarDef, the AST_SymbolVar is marked, then the init value is processed - much the same way as if the init value is on the next line as a separate AST_Statement.

So these two cases have same transversal order:

var a = x();

versus

var a;
x();

(Obviously the resulting assigned value to a would be different in those two cases.)

What the ufuzz iteration count now, by the way?

1.14MFuzz

When we walk() to an instance of AST_VarDef, the AST_SymbolVar is marked, then the init value is processed - much the same way as if the init value is on the next line as a separate AST_Statement.

That's the missing piece.

If that's the case, why not separate all var declarations from their inits prior to reduce_vars?

$ echo 'function bar(){ var a = a && foo(); }' | bin/uglifyjs -c
function bar(){var a=a&&foo()}

$ echo 'function bar(){ var a; a && foo(); }' | bin/uglifyjs -c
function bar(){}

Correction: last command was not equivalent. Should have been:

$ echo 'function bar(){ var a; a = a && foo(); }' | bin/uglifyjs -c
function bar(){var a;a=a&&foo()}

which doesn't help.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

GrosSacASac picture GrosSacASac  路  3Comments

kzc picture kzc  路  5Comments

PinkyJie picture PinkyJie  路  3Comments

neverfox picture neverfox  路  4Comments

chrismanley picture chrismanley  路  5Comments