Uglifyjs: ufuzz failure

Created on 8 Nov 2020  路  6Comments  路  Source: mishoo/UglifyJS

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

function f0(parseInt) {
    c = c + 1;
    a = {
        3: a && a.foo,
        set 1.5(a_2) {
            {
                var expr3 = a_2 && typeof a_2.c == "function" && --_calls_ >= 0 && a_2.c();
                for (a_2 in expr3) {
                    c = 1 + c;
                    var c_2 = expr3[a_2];
                    c = c + 1;
                }
            }
            this.foo /= (((-2 ^ -2 ^ 4 << "a") !== ([ , 0 ][1] < 24..toString() && "a" < "foo")) >= (2 - "function") % ("a" << -5) >>> ("a" == this) / +0) % ((c = c + 1, 
            (null && 2) === (25 == "foo")) > (("" | -5 || 24..toString() != "a") == ((c_2 && (c_2[c = 1 + c, 
            (22, false, 4 >>> "undefined") > (-3 <= "bar" > ("object" != this))] *= "b" << ([ , 0 ].length === 2))) == ("", 
            -0)))) === (("" >> [ , 0 ][1] === 1 % {}) - (-4 >>> 38..toString()) % ("" && "number") !== ("undefined" >= undefined >= "foo" % "undefined" == ("object" << Infinity || Infinity !== 5)) != (([ , 0 ].length === 2) * {} & 22 < null | this >>> false === ([] && "c")) - ((a_2 = "c" || 3) && /[a2][^e]+$/ + undefined) * (c_2 && (c_2[(c = c + 1) + (c_2 && typeof c_2.in == "function" && --_calls_ >= 0 && c_2.in())] = (a_2 && (a_2[c = 1 + c, 
            ("c" <= null & (3 ^ NaN)) + ((c_2 -= "number" > 4) !== false < 22)] -= "foo" === undefined)) ^ (null | 22))));
        },
        set 3(Infinity_1) {
            try {
                {
                    return a++ + (typeof f1 == "function" && --_calls_ >= 0 && f1("undefined", (c = 1 + c, 
                    ((c = c + 1, "") ^ "b" != "") << ("number" >= "c") - (22 !== "bar"))));
                }
            } catch (b_1) {
                var b_1_2;
                try {
                    try {
                        c = 1 + c, ("a" & "foo") / (([ , 0 ].length === 2) >= "a") >= (([] & 0) >= "b" / null);
                    } catch (a) {
                    } finally {
                    }
                } catch (b_1) {
                    c = 1 + c, null - ([ , 0 ].length === 2) && NaN * 3 && 23..toString() != -1 ^ {} === this;
                    c = 1 + c, (undefined & -4) + (-3 && [ , 0 ][1]) + ((Infinity_1 && (Infinity_1.foo %= "bar" || null)) >>> ("object" > 5));
                }
            }
            this.in = (("number" % 5 | 0 * -3) <= (undefined & "number") >>> this - Infinity ^ (b_1_2 += [] >= [] & -1 >>> 1 & (5 < undefined) + (25 === -2))) >> ((-5 >= -1) >>> ({} ^ "c") === 5 / -3 % (0 >> 22) & (NaN >>> 25 < 24..toString() * "a") * (([ , 0 ][1] || -0) && 1 | -0)) || (((3, 
            3) ^ (38..toString() ^ [ , 0 ][1])) === (false === 24..toString() ^ (-2 ^ "c"))) >>> ((1 > -4 != (Infinity_1 && (Infinity_1.null %= 2 / "undefined"))) <= ((0 == "c") >= (b_1_2 += "foo" * -0))) >= (("undefined" == /[a2][^e]+$/ | ![]) ^ (Infinity_1 && (Infinity_1.b += [] > this && 22 == "foo"))) >>> ((4 ^ 25) === ("foo" & "b") || b_1_2 && (b_1_2[void b] &= {} % undefined & (Infinity_1 && (Infinity_1[c = 1 + c, 
            ((22 && -2) ^ undefined < []) <= (b_1_2 && (b_1_2[--b + (b_1_2 && typeof b_1_2.var == "function" && --_calls_ >= 0 && b_1_2.var(38..toString(), false))] = (this ^ Infinity) * (-5 % "c")))] += 1 < 38..toString()))));
        },
        [undefined / 3 - (25 && [ , 0 ][1]) > ("function" <= [ , 0 ][1] <= (NaN ^ false))]: 0 === 1 ? a : b,
        3: typeof a == "function" && --_calls_ >= 0 && a(4)
    };
}

var a_1 = f0(/[a2][^e]+$/);

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

function f0(parseInt) {
    c += 1, a = {
        3: a && a.foo,
        set 1.5(a_2) {
            var expr3 = a_2 && "function" == typeof a_2.c && 0 <= --_calls_ && a_2.c();
            for (a_2 in expr3) {
                c = 1 + c;
                var c_2 = expr3[a_2];
                c += 1;
            }
            this.foo /= ((4 !== (0 < 24..toString() && !0)) >= NaN >>> ("a" == this) / 0) % (c += 1, 
            (-5 == (-0 == (c_2 && (c_2[c = 1 + c, ("object" != this) < !1 < 4] *= "b" << (2 === [ , 0 ].length))))) < !1) === ((0 == 1 % {}) - (-4 >>> 38..toString()) % "" !== !1 != ((2 === [ , 0 ].length) * {} & !1 | this >>> !1 === "c") - (a_2 = "c", 
            (/[a2][^e]+$/ + void 0) * (c_2 && (c_2[(c += 1) + (c_2 && "function" == typeof c_2.in && 0 <= --_calls_ && c_2.in())] = 22 ^ (a_2 && (a_2[c = 1 + c, 
            +(!0 !== (c_2 -= !1))] -= !1))))));
        },
        set 3(Infinity_1) {
            try {
                return a++ + ("function" == typeof f1 && 0 <= --_calls_ && f1("undefined", (c = 1 + c, 
                (!0 ^ (c += 1, "")) << 0)));
            } catch (b_1) {
                var b_1_2;
                try {
                    try {
                        c = 1 + c;
                    } catch (a) {}
                } catch (b_1) {
                    c = 1 + (c = 1 + c), Infinity_1 && (Infinity_1.foo %= "bar");
                }
            }
            this.in = (0 <= 0 >>> this - 1 / 0 ^ (b_1_2 += [] <= [] & -1 >>> 1 & 0)) >> (!1 >>> ("c" ^ {}) === NaN & -0 * (0 < "a" * 24..toString())) || ((3 ^ 38..toString()) == (!1 === 24..toString() ^ -2)) >>> ((1 != (Infinity_1 && (Infinity_1.null %= NaN))) <= ((b_1_2 += NaN) <= !1)) >= (0 ^ (Infinity_1 && (Infinity_1.b += this < [] && !1))) >>> (b_1_2 && (b_1_2[void 0] &= {} % void 0 & (Infinity_1 && (Infinity_1[c = 1 + c, 
            (-2 ^ void 0 < []) <= (b_1_2 && (b_1_2[--b + (b_1_2 && "function" == typeof b_1_2.var && 0 <= --_calls_ && b_1_2.var(38..toString(), !1))] = NaN * (this ^ 1 / 0)))] += 1 < 38..toString()))));
        },
        false: b,
        3: "function" == typeof a && 0 <= --_calls_ && a(4)
    };
}

var a_1 = f0(/[a2][^e]+$/);

console.log(null, a, b, c, 1 / 0, NaN, void 0);



md5-270b037a296b868bd1b1ad91e4db2bc2



original result:
null { '3': false, '1.5': [Setter], false: 10 } 10 1 Infinity NaN undefined

uglified result:
null { '3': [Setter], '1.5': [Setter], false: 10 } 10 1 Infinity NaN undefined



md5-7f2e1011ee79ad416d20e735338ab4fc



minify(options):
{
"mangle": false
}

Suspicious compress options:
evaluate
objects
properties
side_effects
```

bug

Most helpful comment

That's pretty obscure. Only a fuzzer would find such a thing.

If it makes you feel any better, both babel and buble get it wrong too:

$ echo 'console.log({ set 1(v){}, [2]:0, 1:3 })' | node
{ '1': 3, '2': 0 }

$ echo 'console.log({ set 1(v){}, [2]:0, 1:3 })' | babel | node
{ '1': [Setter], '2': 0 }

$ echo 'console.log({ set 1(v){}, [2]:0, 1:3 })' | buble | node
{ '1': [Setter], '2': 0 }

Sometimes I find if you read the ES spec there is some rhyme or reason for the ordering. Then other times it's just an arbitrary decision based on the initial implementation of the feature.

All 6 comments

@kzc behold the beauty of ECMAScript! 馃ぃ

$ node -v
v14.13.1
$ echo console.log({ set 1(v){}, [2]:0, 1:3 }) | node
{ '1': 3, '2': 0 }

$ echo console.log({ set 1(v){}, 2:0, 1:3 }) | node
{ '1': [Setter], '2': 0 }



md5-da391a094bda2d0faf357f5b36861c5b



... so how about if I quote those "numbers" so they are definitely strings?



md5-470bd386f8f5af098de2f0ca83841fb1



```sh
$ echo console.log({ set "1"(v){}, ["2"]:0, "1":3 }) | node
{ '1': 3, '2': 0 }

$ echo console.log({ set "1"(v){}, "2":0, "1":3 }) | node
{ '1': [Setter], '2': 0 }

... nup, coz reasons.

That's pretty obscure. Only a fuzzer would find such a thing.

If it makes you feel any better, both babel and buble get it wrong too:

$ echo 'console.log({ set 1(v){}, [2]:0, 1:3 })' | node
{ '1': 3, '2': 0 }

$ echo 'console.log({ set 1(v){}, [2]:0, 1:3 })' | babel | node
{ '1': [Setter], '2': 0 }

$ echo 'console.log({ set 1(v){}, [2]:0, 1:3 })' | buble | node
{ '1': [Setter], '2': 0 }

Sometimes I find if you read the ES spec there is some rhyme or reason for the ordering. Then other times it's just an arbitrary decision based on the initial implementation of the feature.

You'd hope there'll at least be consistency...

$ node -v
v0.10.48

$ echo console.log({ set 07(v) {}, 07: 2, }); | node
{ '7': 2, '07': [Setter] }

$ echo console.log({ set 08(v) {}, 08: 2, }); | node
{ '8': 2, '08': [Setter] }
$ node -v
v0.12.18

$ echo console.log({ set 07(v) {}, 07: 2, }); | node
console.log({ set 07(v) {}, 07: 2, });
                            ^^
SyntaxError: Object literal may not have data and accessor property with the same name
    at Object.exports.runInThisContext (vm.js:73:16)

$ echo console.log({ set 08(v) {}, 08: 2, }); | node
console.log({ set 08(v) {}, 08: 2, });
                            ^^
SyntaxError: Object literal may not have data and accessor property with the same name
    at Object.exports.runInThisContext (vm.js:73:16)



md5-24b11c6715d4f3915590ad3058ce9f16



```sh
$ node -v
v6.17.1

$ echo console.log({ set 07(v) {}, 07: 2, }); | node
{ '7': [Setter] }

$ echo console.log({ set 08(v) {}, 08: 2, }); | node
{ '8': [Setter] }



md5-58d6c6daa71150838f19fd776d66a52c



```sh
$ node -v
v10.22.1

$ echo console.log({ set 07(v) {}, 07: 2, }); | node
{ '7': [Setter] }

$ echo console.log({ set 08(v) {}, 08: 2, }); | node
{ '8': [Setter] }



md5-a5032cdcb7a049a934fab1643b0edadf



```sh
$ node -v
v14.13.1

$ echo console.log({ set 07(v) {}, 07: 2, }); | node
{ '7': [Setter] }

$ echo console.log({ set 08(v) {}, 08: 2, }); | node
{ '8': 2, '08': [Setter] }

You'd hope there'll at least be consistency

Interesting. Either this is behavior is not defined by the spec, or it's an engine issue. What do other browser engines produce?

Syntax Error (duplicated setter/property name) on Internet Explorer 11

{ 7: 2 } & { 8: 2 } on Firefox 82

Error: Unexpected number '07' & '08' on Safari 5

Syntax Error (duplicated setter/property name) on Opera 12

$ nvs use chakracore
v10.13.0

$ echo console.log({ set 07(v) {}, 07: 2, }); | node
{ '7': [Setter] }

$ echo console.log({ set 08(v) {}, 08: 2, }); | node
{ '8': [Setter] }

So it appears to be undefined behavior in the spec. Not helpful for fuzzing.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Jimbly picture Jimbly  路  4Comments

neverfox picture neverfox  路  4Comments

PinkyJie picture PinkyJie  路  3Comments

lhtdesignde picture lhtdesignde  路  3Comments

chrismanley picture chrismanley  路  5Comments