When 65536 Read as Zero — JavaScript Bug Hunt

Modelled on the Excel 2007 display bug (September 2007): typing =85077.1 showed 100000 instead of 65535.

  • Language: JavaScript
  • Layer: Frontend
  • Difficulty: Medium
  • Concepts: Rendering, Overflow
  • Modelled on: Microsoft Excel · 2007
  • Visible tests: ordinary values display normally; a value just below 65536 shows 65536
  • Reward: 50 XP for a complete fix

Briefing

Modelled on the Excel 2007 display bug (September 2007): typing =850*77.1 showed 100000 instead of 65535. The value in the cell was right; the code that turned certain floating-point results lying a hair below 65535 or 65536 into text for the grid printed the wrong digits. Microsoft confirmed the problem was confined to how a handful of values were displayed and shipped a fix within weeks.

This project reconstructs a formatter with the same kind of fault in the same place: a fast path for near-integer values that memoises digit strings in a 16-bit slot (cell16.js). Its range check looks at the value before it is rounded.

Fix display so every near-integer value shows the integer it rounds to.

Bug report

BUG-XL-65535 · Priority: High · Reported by: a customer's quarterly report

display(x) returns the text the grid shows for a numeric cell:

  • if x is within 1e-9 of an integer n, show String(n) (display(850 * 77.1) -> "65535", display(65535.99999999999) -> "65536")
  • otherwise show String(Math.round(x * 100) / 100) (3.14159 -> "3.14")
  • cell16.render may be used as a fast path, but only for integers n with 0 <= n <= cell16.MAX (65535); everything else goes through general()

Observed: values just below 65536 display as "0".

Logs

[grid] B7 value=65535.99999999999 text="0"
[grid] B8 value=65536 text="65536"

The code as shipped

src/grid/format.js (editable)

var cell16 = require("./cell16");
var EPS = 1e-9;

// Text shown in the grid for a numeric cell value.
exports.display = function (x) {
  if (x >= 0 && x < cell16.MAX + 1) {
    var whole = Math.floor(x);
    var frac = x - whole;
    if (frac < EPS) return cell16.render(whole);
    if (1 - frac < EPS) return cell16.render(whole + 1);
  }
  return exports.general(x);
};

exports.general = function (x) {
  var n = Math.round(x);
  if (Math.abs(x - n) < EPS) return String(n);
  return String(Math.round(x * 100) / 100);
};

Read-only context: src/grid/cell16.js.

Open the hunt to edit the files, run the visible tests and submit against the hidden ones. More JavaScript bug hunts.