authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-09 14:56:19-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-09 14:56:19-05:00
log3b622f4494b8fd899abc20e75e46726344f2d20c
tree4110aaab9e8748020861c0ff7d4211314d079e0c
parentc4d0f97b4c3f85796c4953d6e87b5c0186616bc1
signaturelock-open Commit is signed but in an unrecognized format.

fix off-by-one error in std.unicode.utf8ToUtf16LeWithNull

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

2 files changed, 7 insertions(+), 4 deletions(-)

lib/std/mem.zig+1-1
...@@ -233,7 +233,7 @@ pub const Allocator = struct {...@@ -233,7 +233,7 @@ pub const Allocator = struct {
233 pub fn free(self: *Allocator, memory: var) void {233 pub fn free(self: *Allocator, memory: var) void {
234 const Slice = @typeInfo(@TypeOf(memory)).Pointer;234 const Slice = @typeInfo(@TypeOf(memory)).Pointer;
235 const bytes = @sliceToBytes(memory);235 const bytes = @sliceToBytes(memory);
236 const bytes_len = bytes.len + @boolToInt(Slice.sentinel != null);236 const bytes_len = bytes.len + if (Slice.sentinel != null) @sizeOf(Slice.child) else 0;
237 if (bytes_len == 0) return;237 if (bytes_len == 0) return;
238 const non_const_ptr = @intToPtr([*]u8, @ptrToInt(bytes.ptr));238 const non_const_ptr = @intToPtr([*]u8, @ptrToInt(bytes.ptr));
239 @memset(non_const_ptr, undefined, bytes_len);239 @memset(non_const_ptr, undefined, bytes_len);
lib/std/unicode.zig+6-3
...@@ -571,8 +571,9 @@ pub fn utf8ToUtf16LeWithNull(allocator: *mem.Allocator, utf8: []const u8) ![:0]u...@@ -571,8 +571,9 @@ pub fn utf8ToUtf16LeWithNull(allocator: *mem.Allocator, utf8: []const u8) ![:0]u
571 }571 }
572 }572 }
573573
574 const len = result.len;
574 try result.append(0);575 try result.append(0);
575 return result.toOwnedSlice()[0..:0];576 return result.toOwnedSlice()[0..len :0];
576}577}
577578
578/// Returns index of next character. If exact fit, returned index equals output slice length.579/// Returns index of next character. If exact fit, returned index equals output slice length.
...@@ -619,12 +620,14 @@ test "utf8ToUtf16LeWithNull" {...@@ -619,12 +620,14 @@ test "utf8ToUtf16LeWithNull" {
619 var bytes: [128]u8 = undefined;620 var bytes: [128]u8 = undefined;
620 const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator;621 const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator;
621 const utf16 = try utf8ToUtf16LeWithNull(allocator, "𐐷");622 const utf16 = try utf8ToUtf16LeWithNull(allocator, "𐐷");
622 testing.expectEqualSlices(u8, "\x01\xd8\x37\xdc\x00\x00", @sliceToBytes(utf16[0..]));623 testing.expectEqualSlices(u8, "\x01\xd8\x37\xdc", @sliceToBytes(utf16[0..]));
624 testing.expect(utf16[2] == 0);
623 }625 }
624 {626 {
625 var bytes: [128]u8 = undefined;627 var bytes: [128]u8 = undefined;
626 const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator;628 const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator;
627 const utf16 = try utf8ToUtf16LeWithNull(allocator, "\u{10FFFF}");629 const utf16 = try utf8ToUtf16LeWithNull(allocator, "\u{10FFFF}");
628 testing.expectEqualSlices(u8, "\xff\xdb\xff\xdf\x00\x00", @sliceToBytes(utf16[0..]));630 testing.expectEqualSlices(u8, "\xff\xdb\xff\xdf", @sliceToBytes(utf16[0..]));
631 testing.expect(utf16[2] == 0);
629 }632 }
630}633}