phobos
phobos copied to clipboard
std.format rejects valid format string with position before width
The format string specification in https://dlang.org/library/std/format.html specifies that in a FormatSpecifier, the Position should come before Width. (See the Parameters rule.)
A format string with Position that comes after Width is therefore invalid.
There are two bugs in the std.format implementation:
- A valid format string, in which the
Positioncomes before theWidth, is rejected: It produces an exception. - An invalid format string, in which the
Positioncomes after theWidth, is accepted. (This is similar to issue #10711.)
How to reproduce:
Here is a program foo.d that format 3 strings: 2 valid ones and then, if the argument is valid, a third valid one, or otherwise an invalid one.
import std.stdio;
import std.format;
void main (string[] args)
{
writeln (format ("%*1$d %s", 7, 23, "abc"));
writeln (format ("%*2$d %4$s", 0, 7, 23, "abc"));
if (args[1] == "valid")
writeln (format ("%2$*1$d %3$s", 7, 23, "abc"));
else
writeln (format ("%*1$2$d %3$s", 7, 23, "abc"));
}
Run this program with dmd 2.110.
Demonstrate the first bug:
$ dmd foo.d && ./foo valid
Expected output:
23 abc
23 abc
23 abc
Actual output:
23 abc
23 abc
std.conv.ConvException@/usr/include/dmd/phobos/std/conv.d(2533): Unexpected '$' when converting from type const(char)[] to type int
----------------
??:? pure @safe int std.conv.parse!(int, const(char)[], 0).parse(scope ref const(char)[]) [0x57900591785f]
??:? pure scope @safe void std.format.spec.FormatSpec!(char).FormatSpec.fillUp() [0x5790059142dd]
??:? pure scope @safe bool std.format.spec.FormatSpec!(char).FormatSpec.writeUpToNextSpec!(std.array.Appender!(immutable(char)[]).Appender).writeUpToNextSpec(ref std.array.Appender!(immutable(char)[]).Appender) [0x579005915964]
??:? pure @safe uint std.format.write.formattedWrite!(std.array.Appender!(immutable(char)[]).Appender, char, int, int, immutable(char)[]).formattedWrite(ref std.array.Appender!(immutable(char)[]).Appender, scope const(char[]), int, int, immutable(char)[]) [0x579005913030]
??:? pure @safe immutable(char)[] std.format.format!(char, int, int, immutable(char)[]).format(in char[], int, int, immutable(char)[]) [0x579005912aa7]
??:? _Dmain [0x5790059129da]
Demonstrate the second bug:
$ dmd foo.d && ./foo invalid
Expected output:
23 abc
23 abc
Exception
Actual output:
23 abc
23 abc
23 abc