babel / babel/minify

Broken minified code due to incorrect local variable renaming

Open
#875 5 comments 0 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
4.4k
Forks
217
PR merge metrics
No merged PRs in 30d

Description

**Describe the bug**

In some cases when lots of local variables are used, a local variable can be renamed to a name shared by a function parameter, even when that function parameter is also used in the local variable's scope. This means an identifier that used to refer to the function parameter now refers to the local variable instead.

**To Reproduce**

This is based on a sharpen filter where we discovered the problem. I've reduced it as much as possible while demonstrating the issue, but it is difficult to reduce this any further - it seems to depend on the number of variables used. For example if you remove `r` it does not reproduce any more.

```js
function Sharpen(width, height, weights)
{
for (let y = height - 1; y >= 0; --y)
{
for (let x = width - 1; x >= 0; --x)
{
let sy = y;
let sx = x;
let dstOff = (y * width + x) * 4;
let r = 0;
let g = 0;
let b = 0;
let a = 0;

for (let cy = 0; cy < 3; cy++)
{
for (let cx = 0; cx < 3; cx++)
{
let scy = sy + cy - 1;
let scx = sx + cx - 1;

if (scy >= 0 && scy < height && scx >= 0 && scx < width)
{
let wt = weights[cy * 3 + cx];

r += wt;
g += wt;
b += wt;
a += wt;
}
}
}

console.log(r, g, b, dstOff);
}
}
}
```

**Actual Output**

```js
function Sharpen(c, a, b) {
for (let d = a - 1; 0 <= d; --d) for (let e = c - 1; 0 <= e; --e) {
let f = d,
h = e,
i = 4 * (d * c + e),
j = 0,
k = 0,
g = 0,
l = 0;

for (let a = 0; 3 > a; a++) for (let b = 0; 3 > b; b++) {
let d = f + a - 1,
e = h + b - 1;

if (0 <= d && d < a && 0 <= e && e < c) {
let c = b[3 * a + b]; // <-- ERROR

j += c, k += c, g += c, l += c;
}
}

console.log(j, k, g, i);
}
}
```

**Expected Output**
The line:
`let c = b[3 * a + b];`
was originally:
`let wt = weights[cy * 3 + cx];`
Both `weights` (a function parameter) and `cx` (a local loop variable) have been renamed to `b`, even though they are both used in the same scope. The minified code has the same effect as if the original code had been written `let wt = cx[cy * 3 + cx]`, which is obviously broken.

**Configuration**

Node.js 10.0.0
babel-core 6.26
babel-minify 0.4.3

This does not reproduce in the online REPL, but I have no idea which version that is using.

**Possible solution**

Disabling either babel-plugin-minify-mangle-names or babel-plugin-minify-simplify seems to avoid the problem, but neither is desirable for production minification. Alternatively you can make shotgun changes to the function until it compiles OK again, but it will inevitably crop up somewhere else again later down the line.

**Additional context**

In a large JavaScript application, this problem appears to be cropping up often enough to regularly break our production app in different and unexpected places, which is a serious problem for us.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.