The call Caret Escaping Bug in IBM's cmd and Microsoft's cmd.

You've come to this page because you've asked a question similar to the following:
What's the gen on the CALL caret escaping bug in Microsoft's CMD and IBM's CMD ?

This is the Frequently Given Answer to that question.


The call Caret Escaping Bug is a bug in the call commands that are built into Microsoft's cmd and IBM's cmd. They do not perform the correct inverse of the transformation that the command interpreters' parsers perform when handling the escaping of metacharacters in a command line.

The way that the parsers in Microsoft's cmd and IBM's cmd treat carets (and, indeed, other metacharacters) within quoted portions of the command line is not documented, of course. However, it is discernable through experimentation.

The way that the call command is supposed to handle metacharacters on its command tail is also not documented. However, it is readily apparent, from the fact that Microsoft's and IBM's cmd even attempt to perform a transformation, that the intention is that call does not cause escape character processing to be performed twice.

Systems affected

The bug is present in all versions of Microsoft's cmd for Windows NT, and in IBM's cmd for OS/2.

This bug is not present in any version of command. No version of command, be it Microsoft's command, IBM's command, Digital Research's command, or FreeCOM, supports the escaping of metacharacters.

This bug is not present in JP Software's various command interpreters. 4DOS, 4OS2, 4NT, TCWIN16, TCWIN32, and TCOS2 all support the escaping of metacharacters, albeit operating differently to the way that Microsoft's and IBM's cmds operate, but all of their built-in call commands perform the inverse transformation correctly.

This bug is not present in the 32-bit cmd for OS/2. The 32-bit cmd also handles the escaping of metacharacters differently to the way that Microsoft's and IBM's cmds handle it. But, likewise, its built-in call command performs the appropriate inverse transformation correctly.


The severity of this bug is not easily quantifiable.

This bug causes a command to be passed a command tail different to the one that the user actually specified in the original command line. The severity of this depends from what command is actually being invoked, and what the effect of extra caret characters in the command tail of that command will be.

How to replicate the bug

Execute the command

(The echo command used here is chosen merely for the sake of example, and is not germane to the nature of the bug.)

The correct output that Microsoft's cmd and IBM's cmd should generate, given their (undocumented) rules about the handling of carets in quoted portions of the command line, is

^A "^^A"
however the output that they actually generate is
^A "^^^^A"
with twice as many caret characters in the quoted portion as there should be.


There are no access controls or privileges that relate directly to this bug.

A program that attempted to sanitise an argument string supplied from an external source, by escaping any embedded metacharacters, for passing to a command via the command interpreter, would cause unexpected results if the string contained caret characters and the program was invoking the call command. However, this scenario is unlikely to occur in practice.

What is actually going wrong

When one issues the command

the call command of course "sees" the command tail after escape character processing has been performed on it by the command interpreter, so it sees
ECHO ^A "^^A"
as its command tail. However, the call command effectively resubmits the command tail that it receives back to the command interpreter as a new command line to be executed. So it must escape any carets in its input in order to prevent their being processed as metacharacters, since metacharacter processing has already been done once. call, therefore, prepends escape characters in front of any carets before resubmitting its command tail for execution.

Unfortunately, what call is doing, to ensure that what results once the parser has had a second go at processing the command line is the same as what call originally received, doesn't exactly match the processing that the command line parser actually does. call is not performing the exact inverse of the transformation that the command interpreter performs. The parsers of Microsoft's and IBM's cmds only recognise caret as a metacharacter outside of those parts of the command line that are contained between pairs of quotation marks. But call is escaping carets everywhere that they occur, irrespective of quotation marks.

The result of this is that if a caret is surrounded by a pair of quotation marks in the command tail to call, two carets will occur at that point in the command tail of the command that is eventually executed. In other words: call constructs the string

ECHO ^^A "^^^^A"
to pass back to the command interpreter, by escaping all carets in the command tail that it received; which becomes
ECHO ^A "^^^^A"
after metacharacter processing by the command interpreter; resulting in the ECHO command seeing, and echoing, the command tail
^A "^^^^A"

In order to correctly perform the inverse of the transformation performed by the command interpreter, the call command should actually have constructed the string

ECHO ^^A "^^A"
to pass back to the command interpreter, by escaping only those carets that are not quoted by pairs of quotation marks.

Local fix

There is no known local fix for this bug. Given the analysis, it does not appear likely that a local fix is possible.

Temporary fix

As yet, IBM has not released a temporary fix for this bug, and Microsoft has issued no hotfix for this bug.

Service fix

As yet, IBM has issued no fix pack and Microsoft has issued no service pack that includes a fix for this bug.

(There will not be further service packs for Windows NT 4. This is a permanent bug in Windows NT 4.)

© Copyright 2002 Jonathan de Boyne Pollard. "Moral" rights asserted.
Permission is hereby granted to copy and to distribute this web page in its original, unmodified form as long as its last modification datestamp is preserved.