From e1af1b0b51ea9f29d4ff8076d73c03ba10bfc73c Mon Sep 17 00:00:00 2001 From: anonymous Date: Tue, 31 May 2016 17:50:44 +0200 Subject: [PATCH] fix issue 16090 - popFront generates out-of-bounds array index on corrupted utf-8 strings --- std/range/primitives.d | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/std/range/primitives.d b/std/range/primitives.d index 721f115e5..e56f83118 100644 --- a/std/range/primitives.d +++ b/std/range/primitives.d @@ -2085,6 +2085,8 @@ version(unittest) void popFront(C)(ref C[] str) @trusted pure nothrow if (isNarrowString!(C[])) { + import std.algorithm : min; + assert(str.length, "Attempting to popFront() past the end of an array of " ~ C.stringof); static if (is(Unqual!C == char)) @@ -2104,13 +2106,14 @@ if (isNarrowString!(C[])) //Invalid UTF-8 msbs = 1; } - str = str[msbs .. $]; + str = str.ptr[min(msbs, str.length) .. str.length]; } } else static if (is(Unqual!C == wchar)) { immutable u = str[0]; - str = str[1 + (u >= 0xD800 && u <= 0xDBFF) .. $]; + immutable seqLen = 1 + (u >= 0xD800 && u <= 0xDBFF); + str = str.ptr[min(seqLen, str.length) .. str.length]; } else static assert(0, "Bad template constraint."); } @@ -2150,6 +2153,26 @@ if (isNarrowString!(C[])) static assert(checkCTFEW.empty); } +unittest // issue 16090 +{ + string s = "\u00E4"; + assert(s.length == 2); + s = s[0 .. 1]; + assert(s.length == 1); + s.popFront; + assert(s.empty); +} + +unittest +{ + wstring s = "\U00010000"; + assert(s.length == 2); + s = s[0 .. 1]; + assert(s.length == 1); + s.popFront; + assert(s.empty); +} + /** Implements the range interface primitive $(D popBack) for built-in arrays. Due to the fact that nonmember functions can be called with