Skip to content

Commit

Permalink
fix: EnvStr.initSlice handles zero length strings more reliably. (#9698)
Browse files Browse the repository at this point in the history
* fix intcast on ptr value of zero-length strings

* Make this better

---------

Co-authored-by: Jarred Sumner <[email protected]>
Co-authored-by: Jarred Sumner <[email protected]>
  • Loading branch information
3 people committed Mar 29, 2024
1 parent 4512a04 commit 40f61eb
Showing 1 changed file with 24 additions and 7 deletions.
31 changes: 24 additions & 7 deletions src/shell/interpreter.zig
Expand Up @@ -358,38 +358,55 @@ pub const IO = struct {
/// So environment strings can be ref counted or borrowed slices
pub const EnvStr = packed struct {
ptr: u48,
tag: Tag,
tag: Tag = .empty,
len: usize = 0,

const print = bun.Output.scoped(.EnvStr, true);

const Tag = enum(u16) {
/// no value
empty,

/// Dealloced by reference counting
refcounted,

/// Memory is managed elsewhere so don't dealloc it
slice,
};

inline fn initSlice(str: []const u8) EnvStr {
if (str.len == 0)
// Zero length strings may have invalid pointers, leading to a bad integer cast.
return .{ .tag = .empty, .ptr = 0, .len = 0 };

return .{
.ptr = @intCast(@intFromPtr(str.ptr)),
.ptr = toPtr(str.ptr),
.tag = .slice,
.len = str.len,
};
}

fn toPtr(ptr_val: *const anyopaque) u48 {
const num: [8]u8 = @bitCast(@intFromPtr(ptr_val));
return @bitCast(num[0..6].*);
}

fn initRefCounted(str: []const u8) EnvStr {
if (str.len == 0)
return .{ .tag = .empty, .ptr = 0, .len = 0 };

return .{
.ptr = @intCast(@intFromPtr(RefCountedStr.init(str))),
.ptr = toPtr(RefCountedStr.init(str)),
.tag = .refcounted,
};
}

pub fn slice(this: EnvStr) []const u8 {
if (this.asRefCounted()) |refc| {
return refc.byteSlice();
}
return this.castSlice();
return switch (this.tag) {
.empty => "",
.slice => this.castSlice(),
.refcounted => this.castRefCounted().byteSlice(),
};
}

fn ref(this: EnvStr) void {
Expand Down

0 comments on commit 40f61eb

Please sign in to comment.