Fix incorrect/suspicious uses of ZigString.Slice.cloneIfNeeded (#23937)

`ZigString.Slice.cloneIfNeeded` does *not* guarantee that the returned
slice will have been allocated by the provided allocator, which makes it
very easy to use this method incorrectly.

(For internal tracking: fixes ENG-21284)
This commit is contained in:
taylor.fish
2025-10-23 13:17:51 -07:00
committed by GitHub
parent fb75e077a2
commit 7bf67e78d7
8 changed files with 75 additions and 44 deletions

View File

@@ -107,7 +107,7 @@ pub const String = extern struct {
else
.unknown; // string was 16-bit; may or may not be all ascii
const owned_slice = try utf8_slice.cloneIfNeeded(allocator);
const owned_slice = try utf8_slice.cloneIfBorrowed(allocator);
// `owned_slice.allocator` is guaranteed to be `allocator`.
break :blk .{ owned_slice.mut(), ascii_status };
},
@@ -768,6 +768,16 @@ pub const String = extern struct {
return ZigString.Slice.empty;
}
/// Equivalent to calling `toUTF8WithoutRef` followed by `cloneIfBorrowed`.
pub fn toUTF8Owned(this: String, allocator: std.mem.Allocator) ZigString.Slice {
return bun.handleOom(this.toUTF8WithoutRef(allocator).cloneIfBorrowed(allocator));
}
/// The returned slice is always allocated by `allocator`.
pub fn toUTF8Bytes(this: String, allocator: std.mem.Allocator) []u8 {
return this.toUTF8Owned(allocator).mut();
}
/// use `byteSlice` to get a `[]const u8`.
pub fn toSlice(this: *String, allocator: std.mem.Allocator) SliceWithUnderlyingString {
defer this.* = .empty;