From 2be035584f31131ebd3e2123b19f457c326d070d Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Mon, 13 Jun 2016 18:05:18 -0700 Subject: [PATCH] fix some unsafe behavior in std.format --- std/format.d | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/std/format.d b/std/format.d index 923dbf4e0d2..b4c22c299fa 100644 --- a/std/format.d +++ b/std/format.d @@ -988,7 +988,7 @@ struct FormatSpec(Char) const widthOrArgIndex = parse!uint(tmp); enforceFmt(tmp.length, text("Incorrect format specifier %", trailing[i .. $])); - i = tmp.ptr - trailing.ptr; + i = arrayPtrDiff(tmp, trailing); if (tmp.startsWith('$')) { // index of the form %n$ @@ -1008,7 +1008,7 @@ struct FormatSpec(Char) { indexEnd = parse!(typeof(indexEnd))(tmp); } - i = tmp.ptr - trailing.ptr; + i = arrayPtrDiff(tmp, trailing); enforceFmt(trailing[i++] == '$', "$ expected"); } @@ -1044,13 +1044,13 @@ struct FormatSpec(Char) precision = 0; auto tmp = trailing[i .. $]; parse!int(tmp); // skip digits - i = tmp.ptr - trailing.ptr; + i = arrayPtrDiff(tmp, trailing); } else if (isDigit(trailing[i])) { auto tmp = trailing[i .. $]; precision = parse!int(tmp); - i = tmp.ptr - trailing.ptr; + i = arrayPtrDiff(tmp, trailing); } else { @@ -6549,3 +6549,14 @@ unittest assert(sformat(buf[], "%s %s %s", "c"c, "w"w, "d"d) == "c w d"); }); } + +/***************************** + * The .ptr is unsafe because it could be dereferenced and the length of the array may be 0. + * Returns: + * the difference between the starts of the arrays + */ +@trusted private pure nothrow @nogc + ptrdiff_t arrayPtrDiff(const void[] array1, const void[] array2) +{ + return array1.ptr - array2.ptr; +}