From 3b622f4494b8fd899abc20e75e46726344f2d20c Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 9 Feb 2020 14:56:19 -0500 Subject: [PATCH] fix off-by-one error in std.unicode.utf8ToUtf16LeWithNull MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit and fix larger-than-one-byte sentinels when being freed Thank you to João Pedro for identifying both problems and providing example code to solve them. closes #4413 --- lib/std/mem.zig | 2 +- lib/std/unicode.zig | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/std/mem.zig b/lib/std/mem.zig index 46f23c84f..8f4987e0c 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -233,7 +233,7 @@ pub const Allocator = struct { pub fn free(self: *Allocator, memory: var) void { const Slice = @typeInfo(@TypeOf(memory)).Pointer; const bytes = @sliceToBytes(memory); - const bytes_len = bytes.len + @boolToInt(Slice.sentinel != null); + const bytes_len = bytes.len + if (Slice.sentinel != null) @sizeOf(Slice.child) else 0; if (bytes_len == 0) return; const non_const_ptr = @intToPtr([*]u8, @ptrToInt(bytes.ptr)); @memset(non_const_ptr, undefined, bytes_len); diff --git a/lib/std/unicode.zig b/lib/std/unicode.zig index 77783c3ed..da0dbc3cb 100644 --- a/lib/std/unicode.zig +++ b/lib/std/unicode.zig @@ -571,8 +571,9 @@ pub fn utf8ToUtf16LeWithNull(allocator: *mem.Allocator, utf8: []const u8) ![:0]u } } + const len = result.len; try result.append(0); - return result.toOwnedSlice()[0..:0]; + return result.toOwnedSlice()[0..len :0]; } /// Returns index of next character. If exact fit, returned index equals output slice length. @@ -619,12 +620,14 @@ test "utf8ToUtf16LeWithNull" { var bytes: [128]u8 = undefined; const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator; const utf16 = try utf8ToUtf16LeWithNull(allocator, "𐐷"); - testing.expectEqualSlices(u8, "\x01\xd8\x37\xdc\x00\x00", @sliceToBytes(utf16[0..])); + testing.expectEqualSlices(u8, "\x01\xd8\x37\xdc", @sliceToBytes(utf16[0..])); + testing.expect(utf16[2] == 0); } { var bytes: [128]u8 = undefined; const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator; const utf16 = try utf8ToUtf16LeWithNull(allocator, "\u{10FFFF}"); - testing.expectEqualSlices(u8, "\xff\xdb\xff\xdf\x00\x00", @sliceToBytes(utf16[0..])); + testing.expectEqualSlices(u8, "\xff\xdb\xff\xdf", @sliceToBytes(utf16[0..])); + testing.expect(utf16[2] == 0); } }