Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CTFE format(): str[index] is used before initialized #10369

Open
dlangBugzillaToGithub opened this issue Mar 28, 2019 · 3 comments
Open

CTFE format(): str[index] is used before initialized #10369

dlangBugzillaToGithub opened this issue Mar 28, 2019 · 3 comments

Comments

@dlangBugzillaToGithub
Copy link

elpenguino+D reported this on 2019-03-28T23:58:40Z

Transfered from https://issues.dlang.org/show_bug.cgi?id=19769

CC List

Description

trying to format the result of a const asCapitalized(string) at compile-time causes a used-before-initialized error in std.utf.decode(), as demonstrated below:

```
import std.uni;
import std.format;
static immutable x = format("%s", cast(const)"test".asCapitalized);
```

results in this error:

```
/dlang/dmd/linux/bin64/../../src/phobos/std/utf.d(1132): Error: str[index] is used before initialized
/dlang/dmd/linux/bin64/../../src/phobos/std/uni.d(9143):        originally uninitialized here
/dlang/dmd/linux/bin64/../../src/phobos/std/format.d(3457):        called from here: decode(str, i)
/dlang/dmd/linux/bin64/../../src/phobos/std/format.d(4233):        called from here: formatElement(w, e, f)
/dlang/dmd/linux/bin64/../../src/phobos/std/format.d(1854):        called from here: formatValueImpl(w, val, f)
/dlang/dmd/linux/bin64/../../src/phobos/std/format.d(3552):        called from here: formatValue(w, val, f)
/dlang/dmd/linux/bin64/../../src/phobos/std/format.d(4233):        called from here: formatElement(w, e, f)
/dlang/dmd/linux/bin64/../../src/phobos/std/format.d(1854):        called from here: formatValueImpl(w, val, f)
/dlang/dmd/linux/bin64/../../src/phobos/std/format.d(575):        called from here: formatValue(w, _param_2, spec)
/dlang/dmd/linux/bin64/../../src/phobos/std/format.d(6403):        called from here: formattedWrite(w, fmt, _param_1)
onlineapp.d(3):        called from here: format("%s", asCapitalized("test"))
```
@dlangBugzillaToGithub
Copy link
Author

bugzilla (@WalterBright) commented on 2019-12-05T14:58:35Z

The problem here is, that asCapitalized returns a struct (ToCapitalizerImpl, which is a range), but the overload of formatValueImpl for structs (instead of ranges or the more expected strings) is choosen for printing. This wrong formatValueImpl tries to print all members of the struct, including the uninitialized ones.

@dlangBugzillaToGithub
Copy link
Author

bugzilla (@WalterBright) commented on 2019-12-05T16:20:06Z

My former comment is a little bit misleading. It's the correct formatValueImpl, which is called, but inside this function the static if, checking for an InputRange, is not executed. This is, because after the cast to const, we have a `const(ToCapitalizerImpl)` which is not anymore recoginzed as an InputRange (i.e. isInputRange fails).

The reason is, that empty, front and popFront would need to be const for a const object, but they cannot be const, because they change the object.

IMHO, this is an invalid bug. The result of "test".asCapitalized is an InputRange and not a string as probably was intended. So, the correct call (if that cast(const) is really needed) would be:

import std.uni;
import std.format;
import std.array;
static immutable x = format("%s", cast(const)"test".asCapitalized.array);

Having said this: The errormessage is confusing. Maybe, the struct part of formatValueImpl should check if a member is initialized, before trying to access it... Therefore I leave this open.

New test example:

```
import std.format;

struct Foo
{
    int a = void;
}

static x = format("%s", Foo());
```

@dlangBugzillaToGithub
Copy link
Author

acehreli commented on 2019-12-05T20:53:17Z

Similar:

import std.string;

struct S {
  int i = void;
}

void main() {
  auto s = S(42);
  auto f = format!"%s"(s);
}

Error: cannot read uninitialized variable `i` in CTFE

@LightBender LightBender removed the P3 label Dec 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants