aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2023-01-20 00:05:48 -0800
committerGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2023-01-20 00:05:48 -0800
commit7d7b5350147e16bee0c173eef995b6abe6250932 (patch)
tree16cca18a9347dfafe0abf22e78621ec5deef56cb
parenta98b1751a643037a7b340ae7a42b04849a5491d0 (diff)
downloadbun-7d7b5350147e16bee0c173eef995b6abe6250932.tar.gz
bun-7d7b5350147e16bee0c173eef995b6abe6250932.tar.zst
bun-7d7b5350147e16bee0c173eef995b6abe6250932.zip
Fix assertion failure with boringssl messages
-rw-r--r--src/bun.js/api/bun.zig2
-rw-r--r--src/bun.zig130
-rw-r--r--src/darwin_c.zig5
3 files changed, 132 insertions, 5 deletions
diff --git a/src/bun.js/api/bun.zig b/src/bun.js/api/bun.zig
index 5b4035256..6b5612c18 100644
--- a/src/bun.js/api/bun.zig
+++ b/src/bun.js/api/bun.zig
@@ -1552,7 +1552,7 @@ pub const Crypto = struct {
_ = BoringSSL.ERR_error_string_n(err_code, message_buf, message_buf.len);
- const error_message: []const u8 = bun.span(std.meta.assumeSentinel(&outbuf, 0));
+ const error_message: []const u8 = bun.sliceTo(outbuf[0..], 0);
if (error_message.len == "BoringSSL error: ".len) {
return ZigString.static("Unknown BoringSSL error").toErrorInstance(globalThis);
}
diff --git a/src/bun.zig b/src/bun.zig
index b6c0e2c4a..cf3ea67a5 100644
--- a/src/bun.zig
+++ b/src/bun.zig
@@ -252,8 +252,14 @@ pub fn len(value: anytype) usize {
.Array => |info| info.len,
.Vector => |info| info.len,
.Pointer => |info| switch (info.size) {
- .One => switch (@typeInfo(info.child)) {
- .Array => value.len,
+ .One => switch (@as(@import("builtin").TypeInfo, @typeInfo(info.child))) {
+ .Array => |array| brk: {
+ if (array.sentinel != null) {
+ @compileError("use bun.sliceTo");
+ }
+
+ break :brk array.len;
+ },
else => @compileError("invalid type given to std.mem.len"),
},
.Many => {
@@ -807,3 +813,123 @@ pub fn getFdPath(fd: std.os.fd_t, buf: *[@This().MAX_PATH_BYTES]u8) ![]u8 {
return err;
};
}
+
+fn lenSliceTo(ptr: anytype, comptime end: meta.Elem(@TypeOf(ptr))) usize {
+ switch (@typeInfo(@TypeOf(ptr))) {
+ .Pointer => |ptr_info| switch (ptr_info.size) {
+ .One => switch (@typeInfo(ptr_info.child)) {
+ .Array => |array_info| {
+ if (array_info.sentinel) |sentinel_ptr| {
+ const sentinel = @ptrCast(*align(1) const array_info.child, sentinel_ptr).*;
+ if (sentinel == end) {
+ return indexOfSentinel(array_info.child, end, ptr);
+ }
+ }
+ return std.mem.indexOfScalar(array_info.child, ptr, end) orelse array_info.len;
+ },
+ else => {},
+ },
+ .Many => if (ptr_info.sentinel) |sentinel_ptr| {
+ const sentinel = @ptrCast(*align(1) const ptr_info.child, sentinel_ptr).*;
+ // We may be looking for something other than the sentinel,
+ // but iterating past the sentinel would be a bug so we need
+ // to check for both.
+ var i: usize = 0;
+ while (ptr[i] != end and ptr[i] != sentinel) i += 1;
+ return i;
+ },
+ .C => {
+ std.debug.assert(ptr != null);
+ return indexOfSentinel(ptr_info.child, end, ptr);
+ },
+ .Slice => {
+ if (ptr_info.sentinel) |sentinel_ptr| {
+ const sentinel = @ptrCast(*align(1) const ptr_info.child, sentinel_ptr).*;
+ if (sentinel == end) {
+ return indexOfSentinel(ptr_info.child, sentinel, ptr);
+ }
+ }
+ return std.mem.indexOfScalar(ptr_info.child, ptr, end) orelse ptr.len;
+ },
+ },
+ else => {},
+ }
+ @compileError("invalid type given to std.mem.sliceTo: " ++ @typeName(@TypeOf(ptr)));
+}
+
+/// Helper for the return type of sliceTo()
+fn SliceTo(comptime T: type, comptime end: meta.Elem(T)) type {
+ switch (@typeInfo(T)) {
+ .Optional => |optional_info| {
+ return ?SliceTo(optional_info.child, end);
+ },
+ .Pointer => |ptr_info| {
+ var new_ptr_info = ptr_info;
+ new_ptr_info.size = .Slice;
+ switch (ptr_info.size) {
+ .One => switch (@typeInfo(ptr_info.child)) {
+ .Array => |array_info| {
+ new_ptr_info.child = array_info.child;
+ // The return type must only be sentinel terminated if we are guaranteed
+ // to find the value searched for, which is only the case if it matches
+ // the sentinel of the type passed.
+ if (array_info.sentinel) |sentinel_ptr| {
+ const sentinel = @ptrCast(*align(1) const array_info.child, sentinel_ptr).*;
+ if (end == sentinel) {
+ new_ptr_info.sentinel = &end;
+ } else {
+ new_ptr_info.sentinel = null;
+ }
+ }
+ },
+ else => {},
+ },
+ .Many, .Slice => {
+ // The return type must only be sentinel terminated if we are guaranteed
+ // to find the value searched for, which is only the case if it matches
+ // the sentinel of the type passed.
+ if (ptr_info.sentinel) |sentinel_ptr| {
+ const sentinel = @ptrCast(*align(1) const ptr_info.child, sentinel_ptr).*;
+ if (end == sentinel) {
+ new_ptr_info.sentinel = &end;
+ } else {
+ new_ptr_info.sentinel = null;
+ }
+ }
+ },
+ .C => {
+ new_ptr_info.sentinel = &end;
+ // C pointers are always allowzero, but we don't want the return type to be.
+ std.debug.assert(new_ptr_info.is_allowzero);
+ new_ptr_info.is_allowzero = false;
+ },
+ }
+ return @Type(.{ .Pointer = new_ptr_info });
+ },
+ else => {},
+ }
+ @compileError("invalid type given to std.mem.sliceTo: " ++ @typeName(T));
+}
+
+/// Takes an array, a pointer to an array, a sentinel-terminated pointer, or a slice and
+/// iterates searching for the first occurrence of `end`, returning the scanned slice.
+/// If `end` is not found, the full length of the array/slice/sentinel terminated pointer is returned.
+/// If the pointer type is sentinel terminated and `end` matches that terminator, the
+/// resulting slice is also sentinel terminated.
+/// Pointer properties such as mutability and alignment are preserved.
+/// C pointers are assumed to be non-null.
+pub fn sliceTo(ptr: anytype, comptime end: meta.Elem(@TypeOf(ptr))) SliceTo(@TypeOf(ptr), end) {
+ if (@typeInfo(@TypeOf(ptr)) == .Optional) {
+ const non_null = ptr orelse return null;
+ return sliceTo(non_null, end);
+ }
+ const Result = SliceTo(@TypeOf(ptr), end);
+ const length = lenSliceTo(ptr, end);
+ const ptr_info = @typeInfo(Result).Pointer;
+ if (ptr_info.sentinel) |s_ptr| {
+ const s = @ptrCast(*align(1) const ptr_info.child, s_ptr).*;
+ return ptr[0..length :s];
+ } else {
+ return ptr[0..length];
+ }
+}
diff --git a/src/darwin_c.zig b/src/darwin_c.zig
index 5fe343bc0..474e3374f 100644
--- a/src/darwin_c.zig
+++ b/src/darwin_c.zig
@@ -1,4 +1,5 @@
const std = @import("std");
+const bun = @import("bun");
const builtin = @import("builtin");
const os = std.os;
const mem = std.mem;
@@ -568,7 +569,7 @@ pub fn get_version(buf: []u8) []const u8 {
0,
) == -1) return "unknown";
- return std.mem.span(std.meta.assumeSentinel(buf.ptr, 0));
+ return bun.sliceTo(buf, 0);
}
pub fn get_release(buf: []u8) []const u8 {
@@ -584,7 +585,7 @@ pub fn get_release(buf: []u8) []const u8 {
0,
) == -1) return "unknown";
- return std.mem.span(std.meta.assumeSentinel(buf.ptr, 0));
+ return bun.sliceTo(buf, 0);
}
const IO_CTL_RELATED = struct {