Remove ZigString.Slice.clone(...) (#21410)

### What does this PR do?

Removes `ZigString.Slice.clone(...)` and replaces all of its usages with
`.cloneIfNeeded(...)` which is what it did anyway (why did this alias
exist in the first place?)

Anyone reading code that sees `.clone(...)` would expect it to clone the
underlying string. This makes it _extremely_ easy to write code which
looks okay but actually results in a use-after-free:

```zig
const out: []const u8 = out: {
    const string = bun.String.cloneUTF8("hello friends!");
    defer string.deref();
    const utf8_slice = string.toUTF8(bun.default_allocator);
    defer utf8_slice.deinit();

    // doesn't actually clone
    const cloned = utf8_slice.clone(bun.default_allocator) catch bun.outOfMemory();
    break :out cloned.slice();
};

std.debug.print("Use after free: {s}!\n", .{out});
```
(This is a simplification of an actual example from the codebase)
This commit is contained in:
Zack Radisic
2025-07-27 16:54:39 -07:00
committed by GitHub
parent 3315ade0e9
commit f2e487b1e6
7 changed files with 17 additions and 39 deletions

View File

@@ -89,7 +89,7 @@ pub const String = extern struct {
}
}
return .{ @constCast((try utf8_slice.clone(allocator)).slice()), true };
return .{ @constCast((try utf8_slice.cloneIfNeeded(allocator)).slice()), true };
},
.StaticZigString => return .{ try this.value.StaticZigString.toOwnedSlice(allocator), false },
else => return .{ &[_]u8{}, false },