Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS Javascript engine parseFloat(1) returns negative number

This code will make the bug appear:

function causeBug(d) {
  var k;
  var n = parseFloat(1);
  var c = Math.abs(d);
  if (n < 0) {
    k = '-';
  } else {
    k = '+';
  }
  return k + n; 
}

$(function() {
  for (var i = 0; i <= 2000; ++i) {
      $('body').append(i + ': ' + causeBug(2) + '<br>');
  }
});

It is visible in this fiddle: http://jsfiddle.net/H2SEN/16/ (view in Mobile Safari, scroll down and at some point you will see parseFloat(1) < 0). The negative has been spotted anywhere from the 73rd iteration to over 1500.

Note some of the seemingly unnecessary code like for example the unused parameter d and the unused variable var c = Math.abs(d); are actually necessary for the error to occur. This is also true for the usage of n in the return statement, and the parseFloat call (although parseInt also causes it).

Bug only reproduced on real iPhone 4s (7.0.6) and two iPod Touch (7.1 beta). Not in iPads or iOS Simulator, or any desktop browser. The bug will not occur if you have remote debugging enabled and a Safari console open on your computer.

I am fairly confident this is the exact cause for this unanswered question: Strange JavaScript behaviour on mobile Safari iOS 6

Any insight into potential causes of this bug would be greatly appreciated.

like image 363
captainclam Avatar asked Mar 03 '14 06:03

captainclam


1 Answers

JIT issue perhaps? I found the implementation of Math.abs in the JavascriptCore source which I'm guessing is different from Nitro (ios js engine) or is perhaps marked as JIT executable.

Value MathFuncImp::call(ExecState *exec, Object &/*thisObj*/, const List &args)
{
  double arg = args[0].toNumber(exec);
  double arg2 = args[1].toNumber(exec);
  double result;

  switch (id) {
  case MathObjectImp::Abs:
    result = ( arg < 0 || arg == -0) ? (-arg) : arg;
    break;

This can be implemented directly in javascript. So you can replace your Math.abs calls with

result = ( arg < 0 || arg == -0) ? (-arg) : arg;

This will resolve the issue and be cross browser compatible.

Submitted Apple Bug: 16209709

Does anyone know how this kind of bug occurs or a better way to describe it?

Bit Flip? Memory Collision? Overflow of some sort?

like image 98
startswithaj Avatar answered Oct 04 '22 11:10

startswithaj