Uglifyjs: ufuzz failure

Created on 6 Jun 2020  路  6Comments  路  Source: mishoo/UglifyJS

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

function f0(Math, NaN_1, foo) {
    function f1(a, bar_2) {
        function f2() {
            return;
        }
        var a_2 = f2();
        function f3(Infinity_1, a_2, NaN_2) {
            for (var brake4 = 5; (c = 1 + c, (Infinity_1 && (Infinity_1[c = 1 + c, (5 ^ "object") >> ("number" <= "foo") ^ (25 <= -5) >>> ("undefined" << "b")] = "number" == 25)) >> (false & [ , 0 ][1]) != (-5 << this !== -4 >>> 5)) && brake4 > 0; --brake4) {
                c = 1 + c, (a_2 && (a_2[c = 1 + c, (-5 / "a" ^ -4 % 2) !== (25 / 3 || 23..toString() << 5)] = 25 >= {})) >= true + NaN > "bar" * "" * ([ , 0 ].length === 2 !== 2);
            }
        }
        var a_2 = f3(b = a, "number");
        function f4(Infinity) {
            return c = 1 + c, 1 / -0 <= ([] == 24..toString()) > 25 % 4 / (2 <= {});
            if (c = 1 + c, c = c + 1, (c = c + 1, 0) | "foo" ^ "object") {
                c = 1 + c, -5 + "bar" == (23..toString() || this) & ([ , 0 ][1] === this) << (([ , 0 ].length === 2) <= "undefined");
            }
        }
        var NaN_1 = f4(--b + NaN_1);
    }
    var foo_2 = f1([]);
}

var a = f0(-2, typeof parseInt_1);

console.log(null, a, b, c, Infinity, NaN, undefined);
// uglified code
// (beautified)
var l = 0;

(function(o) {
    for (var i = 5; l = 1 + l, (o && (o[l = 1 + l, 5] = !1)) >> 0 != (-5 << this != -4 >>> 5) && 0 < i; --i) {
        l = 1 + (1 + l);
    }
})([]), console.log(null, void 0, -1, l = 1 + l, 1 / 0, NaN, void 0);



md5-3533a76cd2c5302f437ada69de95ec9a



original result:
null undefined NaN 23 Infinity NaN undefined

uglified result:
null undefined -1 23 Infinity NaN undefined



md5-05bb5c6d3430d9d00bc646a04c7cdb81



minify(options):
{
"compress": {
"passes": 1000000,
"unsafe": true
},
"toplevel": true
}

Suspicious compress options:
evaluate
passes
reduce_vars
unsafe
unused

Suspicious options:
toplevel
```

bug

All 6 comments

Today I learned that unary increment/decrement of arrays yield valid scalar numbers in some cases:

$ echo 'a = [3], a++, console.log(a);' | node
4

$ echo 'a = [3], --a, console.log(a);' | node
2

$ echo 'a = [], --a, console.log(a);' | node
-1

$ echo 'a = [null], a++, console.log(a);' | node
1

$ echo 'a = [undefined], a++, console.log(a);' | node
1

$ echo 'a = [3, 4], --a, console.log(a);' | node
NaN

because unary decrement and increment is syntax sugar for a = Number(a) - 1 and a = Number(a) + 1 respectively, which in turn relies on the odd valid conversion from array to number if the array is of length 0 or 1:

$ echo 'console.log(+[3], +[], +[null], +[undefined], +[3,4])' | node
3 0 0 0 NaN

I tried following the rabbit hole in the ES5.1 spec but my head exploded:

  1. https://www.ecma-international.org/ecma-262/5.1/#sec-11.4.4
  2. https://www.ecma-international.org/ecma-262/5.1/#sec-9.3
  3. https://www.ecma-international.org/ecma-262/5.1/#sec-9.1
  4. https://www.ecma-international.org/ecma-262/5.1/#sec-8.12.8

Much easier to just run the code on various browsers & platforms than reading the specifications, if not because the former don't necessarily follow the latter.

Reading the spec can give you the rationale for the strange behavior - what motivated the designers to adopt that approach in the first place. That is what I was trying to determine, but failed. The effect appears to be the culmination of a bunch of individually reasonable defaults and conversions that lead to a ridiculous result in the aggregate.

Just for completeness sake, here's AST_Hole 馃懟

$ echo 'console.log(+[,])' | node
0

But not two of them...

$ echo 'console.log(+[,,])' | node
NaN

The specification also has the problem of having to codify the legacy behavior of the original JS interpreter implementation which can't be changed for reasons of backwards compatibility. It's not likely that this particular behavior was intended as it's not terribly useful - probably just an oversight at the time.

Was this page helpful?
0 / 5 - 0 ratings