February 04, 2016 [Issue 15645] New: Tuple.slice() causes memory corruption. | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=15645 Issue ID: 15645 Summary: Tuple.slice() causes memory corruption. Product: D Version: D2 Hardware: x86_64 URL: http://forum.dlang.org/thread/ctpsgcekdbwmlsayonqs@for um.dlang.org OS: Linux Status: NEW Severity: major Priority: P1 Component: phobos Assignee: nobody@puremagic.com Reporter: Marco.Leise@gmx.de Good thing we have @trusted to mark suspicious memory operations that are actually safe. When it covers a bug that @safe would have caught though, it leaves a bad taste... First let's look at the implementation: @property ref Tuple!(sliceSpecs!(from, to)) slice(size_t from, size_t to)() @trusted if (from <= to && to <= Types.length) { return *cast(typeof(return)*) &(field[from]); } To return a slice into the tuple, a pointer to the new first is reinterpreted as the new tuple type. This mirrors the effect of slicing an array, just that tuples are actually structs and that causes a serious problem. Consider we slice off the first element of the following tuple and compare the relative offsets of the 2nd and 3rd field respectively: pragma(msg, Tuple!(int, bool, string)._2.offsetof - Tuple!(int, bool, string)._1.offsetof); pragma(msg, Tuple!( bool, string)._1.offsetof - Tuple!( bool, string)._0.offsetof); This prints: 4LU 8LU So the relative offset of the string part moved which causes memory corruption when slice() reinterprets pointers. More visually the layout on amd64 is: 0 4 8 Tuple!(int, bool, string): int boolstring 0 4 8 Tuple!(bool, string): bool string The memory adresses of the boolean field match, but the string moves due to its alignment constraints. -- |
Copyright © 1999-2021 by the D Language Foundation