The Week Number That Went Back to 1999 — Java Bug Hunt

Modelled on the GPS week-number rollover of 6 April 2019: the legacy GPS navigation message carries the week number in 10 bits, so it wraps to zero every…

  • Language: Java
  • Layer: Backend
  • Difficulty: Medium
  • Concepts: Time, Overflow
  • Modelled on: GPS week rollover · 2019
  • Visible tests: a week late in the build era resolves; week 0 after the 2019 rollover is week 2048
  • Reward: 50 XP for a complete fix

Briefing

Modelled on the GPS week-number rollover of 6 April 2019: the legacy GPS navigation message carries the week number in 10 bits, so it wraps to zero every 1024 weeks (about 19.6 years). The first wrap was in August 1999; at the second, receivers that assumed a fixed rollover era — or had no rollover handling at all — suddenly reported dates 1024 weeks in the past, and some systems that depended on them failed.

This project is a reconstruction. GpsWeek.resolve turns the broadcast 10-bit week into a full week number by adding the era the firmware was built in, as a fixed constant.

Fix resolve so the full week is found relative to the firmware's build week and keeps working across any number of future rollovers.

Bug report

BUG-WNRO · Priority: High · Reported by: field support

GpsWeek.resolve(broadcastWeek):

  • broadcastWeek outside 0..1023 throws IllegalArgumentException
  • otherwise returns the SMALLEST full week w such that w % 1024 == broadcastWeek and w >= GpsConstants.BUILD_WEEK (a receiver can never be running before it was built)

GpsWeek.dayNumber(broadcastWeek, dayOfWeek) = resolve(broadcastWeek) * 7 + dayOfWeek.

Observed: after the April 2019 rollover the broadcast week reads 0 and the receiver resolves it to week 1024 — August 1999.

Logs

[gps] wn10=1023 -> week 2047 (2019-03-31)
[gps] wn10=0 -> week 1024 (1999-08-22)
[nav] timestamp moved back 7168 days, rejecting fix

The code as shipped

src/gps/GpsWeek.java (editable)

class GpsWeek {
    static int resolve(int broadcastWeek) {
        if (broadcastWeek < 0 || broadcastWeek >= GpsConstants.ROLLOVER) {
            throw new IllegalArgumentException("week out of range: " + broadcastWeek);
        }
        return GpsConstants.ERA_AT_BUILD * GpsConstants.ROLLOVER + broadcastWeek;
    }

    static int dayNumber(int broadcastWeek, int dayOfWeek) {
        return resolve(broadcastWeek) * 7 + dayOfWeek;
    }
}

Read-only context: src/gps/GpsConstants.java.

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