Zcoin implementation bug enabled attacker to create 548, 000 Zcoins
H. S. Teoh via Digitalmars-d
digitalmars-d at puremagic.com
Sat Mar 11 11:28:16 PST 2017
On Sat, Mar 11, 2017 at 03:03:30PM +0000, Nick Treleaven via Digitalmars-d wrote:
> On Friday, 10 March 2017 at 19:02:06 UTC, H. S. Teoh wrote:
> > A long-standing item on my todo list is to implement compile-time
> > writefln format strings using this technique.
>
> Yes, the actual checking seems straightforward - here I implemented CT
> format as an overload:
>
> import std.format : format;
>
> auto format(string fmt, A...)(A args)
> {
> static assert(__traits(compiles, {enum s = .format(fmt, A.init);}),
> "Arguments do not match format string: '" ~ fmt ~ "' with " ~ A.stringof);
> return .format(fmt, args);
> }
>
> unittest
> {
> auto s = format!"%s is %s"(5, "five");
> static assert(!__traits(compiles, {s = format!"%d"("four");}));
> }
Yes, that's the general idea of it.
But I want to go further: to eliminate unnecessary dependencies of
format() based on the contents of the format string.
More specifically, currently calling format() will instantiate a whole
bunch of stuff for typesetting *all* possible format strings, like
floating-point, array expansion, etc.. That means a simple
format("%s",s) will pull in a whole bunch of code into your executable
that may not actually be used. (And not even LTO can get rid of it,
because the code is inside if- or switch-statements, and technically is
"referenced" by the caller; the linker has no way to know it won't
actually get called.)
Not to mention, "%s" itself pulls in a whole bunch of code for dealing
with things like field width, max width, padding, etc. (i.e., to handle
things like "%10s", "%10.5s", and so on), all of which isn't actually
needed to implement plain ole "%s".
So the idea is to analyse the format string at compile-time to determine
exactly what functionality is actually used, and instantiate only that.
Think of it as a format-string mini-compiler: given a format string and
a list of argument types, compile it into the equivalent minimal D code.
E.g.:
format("abc%sdef", s)
should get compiled into:
"abc" ~ s ~ "def" // N.B.: no floating-point code, no
// width handling, etc.
and so on.
T
--
What doesn't kill me makes me stranger.
More information about the Digitalmars-d
mailing list