Internal error during SetupPhase

The link /help command should display a brief description of how to get help on running the linker’s various sub-programs:

LINK /Link for help on Linker
LINK /Lib for help on Library Manager
LINK /Dump for help on Dumper
LINK /Edit for help on Editor
LINK /Help for help on Helper

Problem

In the LINK.EXE version inspected for this report, namely 7.00.9466, the link /help command faults. The error message is

LINK : fatal error LNK1000: Internal error during SetupPhase 

followed by a dump of exception codes and CPU context.

The link /help command may be undocumented and is anyway far from important, but it must count as some wonder that nobody at Microsoft bothered to run this simple command some time and report the embarrassing outcome.

Cause

The cause of the problem will be familiar to many C programmers: a function in the printf family is called with arguments that mismatch the format specifiers. In a function that is plausibly called something like HelperMain in Microsoft’s source files, each line of text is produced with code similar to

wprintf (L"%S /%.*s for help on %S\n", szLink, cchSwitch, szProgram);

where szLink is the upper-case file-name portion of whatever name LINK.EXE had when run, szProgram is the title of a sub-program such as “Linker” or “Library Manager” and cchSwitch is the number of characters to take from the start of this title for use as the corresponding command-line switch. Compare the expectations of the format control string with the arguments that are actually given to the function:

Expected Argument Actual Argument
a string of single-byte characters a string of single-byte characters
a count of characters a count of characters
a string of wide characters a string of single-byte characters
a string of single-byte characters no argument

While the wide-character function is given string arguments that all use single-byte characters, all the type specifiers ought to use an upper-case S. While three string arguments are expected, three ought be given. Both defects would be remedied with code such as

wprintf (L"%S /%.*S for help on %S\n", szLink, cchSwitch, szProgram, szProgram);

Applicable Versions

The bug is seen in version 7.00.9466 from Microsoft Visual Studio 2002. It is not intended here to determine when the bug was introduced or to track when Microsoft fixes it.

That said, a quick inspection of an old version tells something of how the bug came to exist. In version 3.00.5270 (from Visual C++ 4.0), which does not have the fault, the corresponding code is

printf ("%s /%.*s for help on %s\n", szLink, cchSwitch, szProgram, szProgram);

Someone at Microsoft evidently tried to port this code to call a wide-character function in the style of wprintf while keeping the single-byte strings. The natural port is the remedy proposed above, viz., of changing the %s specifiers to %S. Yet somehow, Microsoft converted only two of the three %s specifiers and lost one argument from the function call.

This problem is not seen for LINK.EXE version 8.00.50727.42 from Microsoft Visual Studio 2005.