Fix Issue 20799 - schwartzSort does not pin transformation results with indirections, leading to memory corruption

This commit is contained in:
Vladimir Panteleev 2020-05-06 09:50:27 +00:00
parent de58d71516
commit 793a78c588
No known key found for this signature in database
GPG key ID: 5004F0FAD051576D

View file

@ -2989,7 +2989,13 @@ if (isRandomAccessRange!R && hasLength!R && hasSwappableElements!R &&
bool overflow;
const nbytes = mulu(len, T.sizeof, overflow);
if (overflow) assert(false, "multiplication overflowed");
return (cast(T*) malloc(nbytes))[0 .. len];
T[] result = (cast(T*) malloc(nbytes))[0 .. len];
static if (hasIndirections!T)
{
import core.memory : GC;
GC.addRange(result.ptr, nbytes);
}
return result;
}
auto xform1 = trustedMalloc(r.length);
@ -3003,6 +3009,11 @@ if (isRandomAccessRange!R && hasLength!R && hasSwappableElements!R &&
static void trustedFree(T[] p) @trusted
{
import core.stdc.stdlib : free;
static if (hasIndirections!T)
{
import core.memory : GC;
GC.removeRange(p.ptr);
}
free(p.ptr);
}
trustedFree(xform1);
@ -3132,6 +3143,20 @@ if (isRandomAccessRange!R && hasLength!R && hasSwappableElements!R)
assert(isSorted!("a < b")(map!(entropy)(arr)));
}
// https://issues.dlang.org/show_bug.cgi?id=20799
@safe unittest
{
import std.range : iota, retro;
import std.array : array;
auto arr = 1_000_000.iota.retro.array;
arr.schwartzSort!(
n => new int(n),
(a, b) => *a < *b
);
assert(arr.isSorted());
}
// partialSort
/**
Reorders the random-access range `r` such that the range `r[0 .. mid]`