www.fgks.org   »   [go: up one dir, main page]

Issue 15386 - std.format.formatValue usage hangs
Summary: std.format.formatValue usage hangs
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: phobos (show other issues)
Version: D2
Hardware: All All
: P1 minor
Assignee: No Owner
URL:
Keywords: pull
: 21741 (view as issue list)
Depends on:
Blocks:
 
Reported: 2015-11-29 06:11 UTC by Doug Nickerson
Modified: 2021-03-22 02:42 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Doug Nickerson 2015-11-29 06:11:12 UTC
The set of 'internal' functions in std.format called "formatValue(...)" are not private, so assuming users should be allowed to call them, consider the following code:
import std.array, std.format;
auto w = appender!(Char[])();
auto fs = FormatSpec!Char("%.*s");
fs.writeUpToNextSpec(dor);     // dor = DummyOutputRange that eats everything
formatValue(w, 0, fs);

The '*' in the format string means an additional argument would specify the precision in this case.  When calling std.format.format() or std.format.formattedWrite() it will usually complain about 'expected int' or 'Range violation' which seems okay - at least it's better than what the code above does, which appears to hang the program indefinitely.

If the above code is just bad usage and I should use the formattedWrite interface, then should the other components of std.format be private?

On a similar note: is the format string happens to be compile-time constant, as it is in this case, shouldn't it be possible to check the variadic arguments against the string and find the error at compile time?   I suppose it would need to be a template parameter string.
Comment 1 Doug Nickerson 2015-11-29 06:24:17 UTC
Actually, letting it run longer reveals that it is not hanging but consuming over 4Gb of memory as it is generating a string of approx 2^32 '0's. lol.

I think this is using the placeholder value defined in FormatSpec for a dynamically specified precision (or width) which is near int.max.

Maybe this is the intended behavior in this (probably incorrect) use case, but it is concerning since format strings are runtime values that can change -- simply putting a '*' in there can allocate 4Gb of memory and/or cause an OutOfMemory error.
Comment 2 Ryuichi OHORI 2016-10-18 23:08:43 UTC
Not only the 'internal' ones, but also from public functions, this issue can be reproduced:

void main()
{
    import std.stdio;
    "%(%0*d%)".writefln(new int[1]);
}

I intended to specify equal width for each element of an array, put the width before new int[1] and got a runtime error. Removing the width from the arguments, I've come up with this code.
Comment 3 Berni44 2021-03-21 18:49:38 UTC
Although similar, they are different issues, so I opened a new one for the second issue:

https://issues.dlang.org/show_bug.cgi?id=21741
Comment 4 Berni44 2021-03-21 19:47:19 UTC
*** Issue 21741 has been marked as a duplicate of this issue. ***
Comment 5 Dlang Bot 2021-03-21 19:48:59 UTC
@berni44 created dlang/phobos pull request #7898 "Fix Issue 15386 - std.format.formatValue usage hangs" fixing this issue:

- Fix Issue 15386 - std.format.formatValue usage hangs

https://github.com/dlang/phobos/pull/7898
Comment 6 Dlang Bot 2021-03-22 02:42:34 UTC
dlang/phobos pull request #7898 "Fix Issue 15386 - std.format.formatValue usage hangs" was merged into master:

- c983ec88080c8baf56658fe57640e52d1834a4c5 by berni44:
  Fix Issue 15386 - std.format.formatValue usage hangs

https://github.com/dlang/phobos/pull/7898