In the product end game, every change carries significant risk, episode 2

The Old New Thing (Raymond Chen) News

Summary

A historical account of a sporadic bug in Word 97 caused by a CPU erratum, resolved through binary patching to minimize risks during the release cycle.

<p>A colleague related this story of a bug that arose at the very end of the Word 97 release cycle.</p> <p>Testing had identified a ship-stopping bug in a somewhat common code path. The bad news is that the bug was sporadic. The good news is that the test team had come up with a script that could trigger the crash in the lab with fairly good reliability. The bad news is that the bug went away when you used the debugger.</p> <p>The development team was very anxious, because a bug that appears only sporadically in the lab <a title="One in a million is next Tuesday" href="https://learn.microsoft.com/en-us/archive/blogs/larryosterman/one-in-a-million-is-next-tuesday"> is going to occur regularly in the wild</a>. But how do you debug a problem that resists debugging?</p> <p>There was talk of using an in-circuit emulator (ICE), which is basically <a title="In-Circuit Emulation: A powerful hardware tool for software debugging" href="https://www.rcollins.org/ddj/Jul97/"> a separate computer that ran a CPU emulator</a>. The ICE had a cable that plugged into the target machine&#8217;s CPU socket, and that was the mechanism by which the ICE could emulate the operation of a CPU: by physically reproducing the electrical signals that a real CPU would generate. Since the CPU was emulated, you could use the ICE to set breakpoints on things that happen inside the CPU itself, like &#8220;Break when the value 42 is written to this memory location when the CPU has interrupts disabled.&#8221; (Though in this case, it was just for setting breakpoints and inspecting memory from outside the system.) To most software developers, in-circuit emulators existed only in myth, and the possibility of acquiring one and using it was met with the excitement of a five-year-old boy who learns that he might get to ride on a fire truck.</p> <p>The developers who were leading the investigation beamed with joy when they identified that most of the crashing systems came from the same manufacturer, and they were all manufactured before a specific date. At this point, it wasn&#8217;t too long before a CPU errata was found that was consistent with the manufacturing dates of the affected systems.</p> <p>Now, the compiler they were using had issued an update to avoid the offending code sequence, but the team had locked their toolset before that update became available, and upgrading the compiler <a title="Microspeak: Escrow" href="https://devblogs.microsoft.com/oldnewthing/20260217-00/?p=112067"> while in escrow</a>¹ is not a good idea, because who knows what new bugs would be introduced by switching to a new compiler.²</p> <p>The team wrote a tool to scour their binaries to look for any occurrences of a code sequence that would trigger the CPU erratum.² They found around 150 instances of the troublesome code sequence, but one of the requirements for the CPU bug was that the sequence span a page boundary, and only one of those 150 incidents crossed a page boundary.</p> <p>And their testers found it.</p> <p>To avoid introducing any new problems as a side effect of the fix, the team opted to do a binary patch to the binary to insert a <code>nop</code> into the offending code sequence. This was enough to avoid the CPU erratum without risking regression to any other code.</p> <p><b>Bonus reading</b>: <a title="In the product end game, every change carries significant risk" href="https://devblogs.microsoft.com/oldnewthing/20091104-01/?p=16143"> Related story</a>.</p> <p>¹ Supplemental reading: <a title="Microspeak elaborated: Isn’t escrow just a release candidate by another name?" href="https://devblogs.microsoft.com/oldnewthing/20260623-00/?p=112462"> Escrow vs. release candidate</a>.</p> <p>² There is a small risk that the compiler will have a bug that is triggered by the product source code, but there is a much bigger risk that that there are pre-existing bugs in the product source code that would be exposed by the new compiler. For example, an uninitialized variable bug could be masked by the fact that the old compiler&#8217;s choice of memory layout means that the previous use of the memory was for a pointer that was never null, but the new compiler lays out local variables differently, and now the previous use of the memory was for an integer that is sometimes zero.</p> <p><a title="My, what strange NOPs you have!" href="https://devblogs.microsoft.com/oldnewthing/20110112-00/?p=11773"> Sound familiar</a>?</p> <p>The post <a href="https://devblogs.microsoft.com/oldnewthing/20260826-00/?p=112649">In the product end game, every change carries significant risk, episode 2</a> appeared first on <a href="https://devblogs.microsoft.com/oldnewthing">The Old New Thing</a>.</p>
Original Article
View Cached Full Text

Cached at: 08/28/26, 03:49 AM

# In the product end game, every change carries significant risk, episode 2 - The Old New Thing Source: [https://devblogs.microsoft.com/oldnewthing/20260826-00?p=112649](https://devblogs.microsoft.com/oldnewthing/20260826-00?p=112649) A colleague related this story of a bug that arose at the very end of the Word 97 release cycle\. Testing had identified a ship\-stopping bug in a somewhat common code path\. The bad news is that the bug was sporadic\. The good news is that the test team had come up with a script that could trigger the crash in the lab with fairly good reliability\. The bad news is that the bug went away when you used the debugger\. The development team was very anxious, because a bug that appears only sporadically in the lab[is going to occur regularly in the wild](https://learn.microsoft.com/en-us/archive/blogs/larryosterman/one-in-a-million-is-next-tuesday)\. But how do you debug a problem that resists debugging? There was talk of using an in\-circuit emulator \(ICE\), which is basically[a separate computer that ran a CPU emulator](https://www.rcollins.org/ddj/Jul97/)\. The ICE had a cable that plugged into the target machine’s CPU socket, and that was the mechanism by which the ICE could emulate the operation of a CPU: by physically reproducing the electrical signals that a real CPU would generate\. Since the CPU was emulated, you could use the ICE to set breakpoints on things that happen inside the CPU itself, like “Break when the value 42 is written to this memory location when the CPU has interrupts disabled\.” \(Though in this case, it was just for setting breakpoints and inspecting memory from outside the system\.\) To most software developers, in\-circuit emulators existed only in myth, and the possibility of acquiring one and using it was met with the excitement of a five\-year\-old boy who learns that he might get to ride on a fire truck\. The developers who were leading the investigation beamed with joy when they identified that most of the crashing systems came from the same manufacturer, and they were all manufactured before a specific date\. At this point, it wasn’t too long before a CPU errata was found that was consistent with the manufacturing dates of the affected systems\. Now, the compiler they were using had issued an update to avoid the offending code sequence, but the team had locked their toolset before that update became available, and upgrading the compiler[while in escrow](https://devblogs.microsoft.com/oldnewthing/20260217-00/?p=112067)¹ is not a good idea, because who knows what new bugs would be introduced by switching to a new compiler\.² The team wrote a tool to scour their binaries to look for any occurrences of a code sequence that would trigger the CPU erratum\.² They found around 150 instances of the troublesome code sequence, but one of the requirements for the CPU bug was that the sequence span a page boundary, and only one of those 150 incidents crossed a page boundary\. And their testers found it\. To avoid introducing any new problems as a side effect of the fix, the team opted to do a binary patch to the binary to insert a`nop`into the offending code sequence\. This was enough to avoid the CPU erratum without risking regression to any other code\. **Bonus reading**:[Related story](https://devblogs.microsoft.com/oldnewthing/20091104-01/?p=16143)\. ¹ Supplemental reading:[Escrow vs\. release candidate](https://devblogs.microsoft.com/oldnewthing/20260623-00/?p=112462)\. ² There is a small risk that the compiler will have a bug that is triggered by the product source code, but there is a much bigger risk that that there are pre\-existing bugs in the product source code that would be exposed by the new compiler\. For example, an uninitialized variable bug could be masked by the fact that the old compiler’s choice of memory layout means that the previous use of the memory was for a pointer that was never null, but the new compiler lays out local variables differently, and now the previous use of the memory was for an integer that is sometimes zero\. [Sound familiar](https://devblogs.microsoft.com/oldnewthing/20110112-00/?p=11773)? ### Category ### Topics ## Author ![Raymond Chen](https://devblogs.microsoft.com/oldnewthing/wp-content/uploads/sites/38/2019/02/RaymondChen_5in-150x150.jpg) Raymond has been involved in the evolution of Windows for more than 30 years\. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie\-jeebies\. The Web site spawned a book, coincidentally also titled The Old New Thing \(Addison Wesley 2007\)\. He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information\.

Similar Articles

A Record-Breaking Patch Tuesday for June 2026

Krebs on Security

Microsoft's June 2026 Patch Tuesday sets a record with nearly 200 security fixes, including three publicly exploited zero-days. AI tools are increasingly used to find bugs, with security researchers like Nightmare Eclipse releasing exploits.

Patch Tuesday, April 2026 Edition

Krebs on Security

Microsoft's April 2026 Patch Tuesday fixes a record 167 vulnerabilities, including an actively exploited SharePoint zero-day and a publicly disclosed Windows Defender bug (BlueHammer), while Google Chrome and Adobe Reader also addressed zero-days.

You can't bug fix your way out of the vulnpocalypse

Lobsters Hottest

Alex Gaynor argues that the AI-driven 'vulnpocalypse' makes traditional bug-by-bug fixing untenable and calls for systemic security fixes, such as rewriting components in memory-safe languages.