[Issue 20495] New: std.range.choose range is not safe when calling save
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Fri Jan 10 01:02:44 UTC 2020
https://issues.dlang.org/show_bug.cgi?id=20495
Issue ID: 20495
Summary: std.range.choose range is not safe when calling save
Product: D
Version: D2
Hardware: All
OS: All
Status: NEW
Keywords: safe
Severity: normal
Priority: P1
Component: phobos
Assignee: nobody at puremagic.com
Reporter: schveiguy at yahoo.com
Currently, the range passes a copy of the unused union member to the saved
version. Although this might seem innocuous, it's possible the postblit or copy
constructor uses the existing data, which is actually the contents of the other
range.
Hard to come up with an example due to how most ranges work, but:
import std.range;
struct KillableRange
{
@safe:
int *item;
ref int front() {return *item; }
bool empty() { return *item > 10; }
void popFront() { ++(*item); }
this(this)
{
assert(item is null || cast(size_t)item > 1000);
item = new int(*item);
}
KillableRange save() { return this; }
}
void main() @safe
{
auto kr = KillableRange(new int(1));
int[] x = [1,2,3,4,5]; // length is first
auto chosen = choose(true, x, kr);
auto chosen2 = chosen.save;
}
This will assert because x.length overlaps kr.item when save is called.
The correct mechanism is to use .init on the non-saved range.
Something with RefCounted as implementation would easily be a good use case to
show problems here, but it's harder to test without segfaulting.
--
More information about the Digitalmars-d-bugs
mailing list