www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 15645] New: Tuple.slice() causes memory corruption.


          Issue ID: 15645
           Summary: Tuple.slice() causes memory corruption.
           Product: D
           Version: D2
          Hardware: x86_64
               URL: http://forum.dlang.org/thread/ctpsgcekdbwmlsayonqs for
                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:

    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,
    pragma(msg, Tuple!(     bool, string)._1.offsetof - Tuple!(     bool,

This prints:


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.

Feb 04 2016