任何人都可以确认这个iOS 10 beta 3 Safari bug吗?

时间:2016-07-19 07:15:41

标签: javascript ios safari

在iOS 10 beta 2和beta 3(在iPhone 6上运行)上运行时,我们的JavaScript应用程序以非常奇怪的方式失败。查看日志时,我可以看到数组在意外的地方包含NaN和0x00。我设法制作了一个可以非常可靠地重现行为的测试程序。

我已经向Apple填写了一个错误报告,但没有收到回复,所以我有点担心这是否会被修复。所以作为第一件事,我想听听是否有人可以重现它并且至少确认存在错误(而不仅仅是我的误解等等)。我自己很确定这一点,但总是很安全!也可能是其他人遇到过它并找到了解决方法,或者如果某些WebKit开发人员遇到它,他们可能会提供帮助。

测试程序显示错误 这是测试程序。问题不会每次都发生,但页面中的JavaScript代码可以检测到它何时发生,并将一直刷新页面直到它发生。在不受影响的浏览器上,这意味着页面将保持刷新。在受影响的浏览器上(例如iOS 10 beta 2上的Safari和iPhone 6上运行的beta 3),刷新将在一些迭代(通常为5-10)和显示错误后停止。

该程序通过创建一个大小为8192的uint8array来运行(似乎较小的数组大小会导致错误更加罕见)。它将用虚拟值填充此数组,然后调用“toStr”,它首先分配一个新的plain数组,然后将uint8array的内容复制到plain数组,沿途缩小每个元素。执行此操作时,它会构建一个包含原始值和复制值的字符串。当错误发生时,目标数组中的元素变成NaN,由于它通过构造仅包含整数,因此不应该发生。 doTest()函数测试结果字符串中是否包含这样的NaN值,表明发生了错误。

请注意,在每次刷新过程中,程序运行20次迭代,此时它也是随机的,哪次迭代失败。但是,我观察到如果在前20次迭代中没有发生错误,那么即使一次运行无限次迭代,也不可能在此页面加载中发生错误,这就是我添加的原因重新加载页面逻辑。

请注意,程序逻辑本身是完全确定的,因此每次运行应该是相同的,其他浏览器也是如此。通过从doTest()函数中的log()语句中删除注释,可以看到更多细节,以便打印出数组。

请注意,如果函数“narrow”被内联而不是单独的函数,问题似乎消失了(即使这两个程序当然应该在语义上等效)。此外,如果忽略从“state>> 8”的转换,错误似乎也消失了,因此确切的数组值是重要的,或者这种重写会以某种方式影响JIT的运行方式。因此,在测试问题时使用确切的程序结构至关重要。

<html>
<head>
<title>Array test page</title>
<script>
    log = function(s) {
        var ta = document.getElementById("ta");
        ta.value += s + "\n";
    }

    function narrow(x_0) {
        return x_0 << 24 >> 24;
    }

    function toStr(i8bytes) {
        var bytes, i, str;
        bytes = new Array(i8bytes.length);
        str = '';
        for (i = 0; i < 16; i++) {
            bytes[i] = narrow(i8bytes[i]);
            str += '*** (' + i8bytes[i] + ' - ' + bytes[i] + ')';
        }
        return str;
    }

    function doTest() {
        var sz = 8192;
        state = 0;
        var i;

        var fnd = false;
        for (i = 0; i < 20; i++) {
            var arr = new ArrayBuffer(sz);
            var i8bytes = new Uint8Array(arr, 0, sz);
            for (j = 0; j < i8bytes.length; j++) {
                state = state + 1;
                var v = state >> 8;
                i8bytes[j] = narrow(v);
            }
            var str = toStr(i8bytes);
            // log(str); <-- REMOVE COMMENT to show results
            if (str.indexOf("NaN") !== -1) {
                log("Found NaN at iteration" + i);
                log(str);
                fnd = true;
                break;
            }
        }
        return fnd;

    }
    function start() {
        log("Starting: " + new Date());
        if (!doTest()) {
            location.reload(true); // <--- REMOVE THIS LINE TO PREVENT RELOAD 
        }
    };
</script>
</head>
<body onload="start()">
<h1>Array test page</h1>
<p>Note that on a non-affected browser this page will reload indefinitely. On an affected browser, it
will stop reloading once the problem is detected.
<p>
<textarea id="ta" rows="10" cols="40"></textarea>
</body>
</html>

0 个答案:

没有答案