Back to 1970 — JavaScript Bug Hunt

Modelled on the iOS "1 January 1970" bug (2016): setting a 64-bit iPhone's date to the very start of the Unix epoch caused timezone offsets to push internal…

  • Language: JavaScript
  • Layer: Backend
  • Difficulty: Easy
  • Concepts: Dates, Underflow
  • Modelled on: Apple iOS · 2016
  • Visible tests: a normal interval is measured; the epoch with a large positive offset clamps to zero
  • Reward: 50 XP for a complete fix

Briefing

Modelled on the iOS "1 January 1970" bug (2016): setting a 64-bit iPhone's date to the very start of the Unix epoch caused timezone offsets to push internal timestamps below zero. Code that assumed a non-negative epoch spun forever, and affected devices bricked on the next reboot.

uptime.js computes elapsed seconds and has the same missing floor.

Fix elapsedSince so a timestamp at or before the epoch cannot produce a negative or looping result.

Bug report

BUG-1970 · Priority: Critical · Reported by: device reliability

elapsedSince(nowEpoch, thenEpoch, tzOffsetSeconds):

  • returns the number of seconds elapsed, after applying the timezone offset to the "then" value
  • must never return a negative number; clamp to 0 instead

Observed: with thenEpoch=0 and a large positive offset the result goes below zero and the retry loop that consumes it never terminates.

Logs

[time] elapsed=-39600 now=0 then=0 tz=39600
[time] boot watchdog: retry loop exceeded 100000 iterations

The code as shipped

src/time/uptime.js (editable)

// Seconds elapsed between two epoch timestamps, offset-adjusted.
exports.elapsedSince = function (nowEpoch, thenEpoch, tzOffsetSeconds) {
  var adjusted = thenEpoch + tzOffsetSeconds;
  return nowEpoch - adjusted;
};

// Retries once per elapsed second, capped by the caller.
exports.retryCount = function (nowEpoch, thenEpoch, tzOffsetSeconds) {
  var n = exports.elapsedSince(nowEpoch, thenEpoch, tzOffsetSeconds);
  var count = 0;
  while (count < n) count++;
  return count;
};

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