The problem

This customer ran their billing, invoicing, and admin on a single in-house C application that had been written years earlier. On the first workday of 2020 it segfaulted on launch and stayed segfaulted. Nothing went out, nothing came in. The developer who originally wrote it had passed away, so there was nobody left to call.

What I did

I started where you have to start when there’s no documentation and the only signal is a segfault: reverse engineering. strace showed where the application was going just before it died. objdump gave me the disassembly to read. gdb let me step through to the actual crash and inspect state.

The pattern that emerged was familiar: a date being parsed and compared, then a fork in control flow. The year was being stored as only its last two digits, and somewhere there was a heuristic deciding which century those two digits belonged to.

Digging through the customer’s file systems I eventually found fragments of the original source for one of the supporting libraries. The relevant block was an if statement, plainly written: if the two-digit year was below 20, treat it as the 2000s, otherwise treat it as the 1900s. The comment next to it said the change had been made in 1999.

So the segfault wasn’t really about 2020 itself. The original Y2K patch had a hard ceiling at year 20, and when it tripped the parser would derive a date from the 1920s, which the rest of the code, built around assumptions about modern dates, refused to handle. It crashed.

The customer was already planning to migrate to a new application later that year, so a full rewrite of the date handling wasn’t worth doing. I bumped the threshold from 20 to 30, which bought enough runway to cover the migration, then recompiled the affected part of the library and dropped the rebuilt artifact in.

The outcome

The application started cleanly. Billing went out the door. The whole engagement, from the call to a working app, took a few hours.

Notes

The interesting thing about this case isn’t the fix, which was a one-line change. It’s the path to it. Without source code, without a developer, with a segfault on launch and a business waiting, the only way through was to learn the system from the inside out. The Y2K patch was technically correct when it was written in 1999. It just made an implicit assumption about how long it would still be in service.

Tools

C · GDB · objdump · strace · Reverse engineering