diff --git a/std/internal/cstring.d b/std/internal/cstring.d index 718305bd2..a61ee81cc 100644 --- a/std/internal/cstring.d +++ b/std/internal/cstring.d @@ -145,7 +145,10 @@ if (isSomeChar!To && (isInputRange!From || isSomeString!From) && { if (i + 1 == p.length) { - heapBuffer = trustedRealloc(p, strLength, heapBuffer is null); + if (heapBuffer is null) + heapBuffer = trustedReallocStack(p, strLength); + else + heapBuffer = trustedRealloc(heapBuffer); p = heapBuffer; } p[i++] = c; @@ -269,38 +272,41 @@ private: static TempCStringBuffer trustedVoidInit() { TempCStringBuffer res = void; return res; } } -private To[] trustedRealloc(To)(scope To[] buf, size_t strLength, bool bufIsOnStack) +private To[] trustedRealloc(To)(return scope To[] buf) + @trusted @nogc pure nothrow +{ + pragma(inline, false); // because it's rarely called + import std.internal.memory : enforceRealloc; + + const size_t newlen = buf.length * 3 / 2; + if (buf.length >= size_t.max / (2 * To.sizeof)) + { + version (D_Exceptions) + { + import core.exception : onOutOfMemoryError; + onOutOfMemoryError(); + } + else + { + assert(0, "Memory allocation failed"); + } + } + auto ptr = cast(To*) enforceRealloc(buf.ptr, newlen * To.sizeof); + return ptr[0 .. newlen]; + +} + +private To[] trustedReallocStack(To)(scope To[] buf, size_t strLength) @trusted @nogc pure nothrow { pragma(inline, false); // because it's rarely called - import std.internal.memory : enforceMalloc, enforceRealloc; + import std.internal.memory : enforceMalloc; size_t newlen = buf.length * 3 / 2; - - if (bufIsOnStack) - { - if (newlen <= strLength) - newlen = strLength + 1; // +1 for terminating 0 - auto ptr = cast(To*) enforceMalloc(newlen * To.sizeof); - ptr[0 .. buf.length] = buf[]; - return ptr[0 .. newlen]; - } - else - { - if (buf.length >= size_t.max / (2 * To.sizeof)) - { - version (D_Exceptions) - { - import core.exception : onOutOfMemoryError; - onOutOfMemoryError(); - } - else - { - assert(0, "Memory allocation failed"); - } - } - auto ptr = cast(To*) enforceRealloc(buf.ptr, newlen * To.sizeof); - return ptr[0 .. newlen]; - } + if (newlen <= strLength) + newlen = strLength + 1; // +1 for terminating 0 + auto ptr = cast(To*) enforceMalloc(newlen * To.sizeof); + ptr[0 .. buf.length] = buf[]; + return ptr[0 .. newlen]; } diff --git a/std/internal/memory.d b/std/internal/memory.d index a8b677d4b..991cd685b 100644 --- a/std/internal/memory.d +++ b/std/internal/memory.d @@ -42,7 +42,7 @@ void* enforceCalloc()(size_t nmemb, size_t size) @nogc nothrow pure @safe } // ditto -void* enforceRealloc()(void* ptr, size_t size) @nogc nothrow pure @system +void* enforceRealloc()(return scope void* ptr, size_t size) @nogc nothrow pure @system { auto result = fakePureRealloc(ptr, size); if (!result) mixin(allocationFailed); @@ -54,5 +54,5 @@ extern (C) @nogc nothrow pure private { pragma(mangle, "malloc") void* fakePureMalloc(size_t) @safe; pragma(mangle, "calloc") void* fakePureCalloc(size_t nmemb, size_t size) @safe; - pragma(mangle, "realloc") void* fakePureRealloc(void* ptr, size_t size) @system; + pragma(mangle, "realloc") void* fakePureRealloc(return scope void* ptr, size_t size) @system; } diff --git a/std/uni/package.d b/std/uni/package.d index b52ba78d7..318bcb32a 100644 --- a/std/uni/package.d +++ b/std/uni/package.d @@ -1819,7 +1819,7 @@ alias sharSwitchLowerBound = sharMethod!switchUniformLowerBound; return ptr[0 .. size]; } - static T[] realloc(T)(scope T[] arr, size_t size) @trusted + static T[] realloc(T)(return scope T[] arr, size_t size) @trusted { import std.internal.memory : enforceRealloc; if (!size)