diff --git a/src/bun_core/lib.rs b/src/bun_core/lib.rs index c5b8d48c6220..15551ae5ee62 100644 --- a/src/bun_core/lib.rs +++ b/src/bun_core/lib.rs @@ -1607,6 +1607,10 @@ pub(crate) mod strings_impl { break; } Some(i) => { + debug_assert!( + rest[i] >= 0x80, + "first_non_ascii_usize pointed at an ASCII byte" + ); list.extend_from_slice(&rest[..i]); rest = &rest[i..]; while let Some(&c) = rest.first() { diff --git a/src/runtime/bin_entry/mod.rs b/src/runtime/bin_entry/mod.rs index 098d8c73ceaa..44dac7781e91 100644 --- a/src/runtime/bin_entry/mod.rs +++ b/src/runtime/bin_entry/mod.rs @@ -157,6 +157,10 @@ pub(crate) unsafe extern "C" fn main(argc: c_int, argv: *const *const c_char) -> // 1. Crash handler first so anything below gets a usable trace. bun_crash_handler::init(); + // Before the first string conversion: simdutf's CPUID dispatch may have + // picked a stub that returns 0 for every call. + bun_simdutf_sys::simdutf::init(); + use_mimalloc_in_dependencies(); // SIGPIPE/SIGXFSZ → SIG_IGN. diff --git a/src/simdutf_sys/bun-simdutf.cpp b/src/simdutf_sys/bun-simdutf.cpp index 6afd6862ddc1..7c912eb76f12 100644 --- a/src/simdutf_sys/bun-simdutf.cpp +++ b/src/simdutf_sys/bun-simdutf.cpp @@ -7,6 +7,24 @@ typedef struct SIMDUTFResult { extern "C" { +// When CPUID advertises none of the compiled-in kernels (QEMU's default CPU +// model hides SSE4.2 that the host executes), simdutf installs a stub whose +// every method returns 0 / false. WTF builds simdutf without the scalar +// fallback, so pick the last kernel in the priority-ordered list: on x64 that +// is westmere, the same -march=nehalem baseline the whole binary runs. +void simdutf__init() +{ + if (simdutf::get_active_implementation()->name() != "unsupported") + return; + + const simdutf::implementation* least_demanding = nullptr; + for (const simdutf::implementation* impl : simdutf::get_available_implementations()) + least_demanding = impl; + + if (least_demanding) + simdutf::get_active_implementation() = least_demanding; +} + bool simdutf__validate_utf8(const char* buf, size_t len) { return simdutf::validate_utf8(buf, len); diff --git a/src/simdutf_sys/simdutf.rs b/src/simdutf_sys/simdutf.rs index 47be59bcb46d..74ec55a5eae1 100644 --- a/src/simdutf_sys/simdutf.rs +++ b/src/simdutf_sys/simdutf.rs @@ -31,6 +31,7 @@ impl Status { } unsafe extern "C" { + safe fn simdutf__init(); pub(crate) fn simdutf__validate_utf8(buf: *const u8, len: usize) -> bool; pub(crate) fn simdutf__validate_utf8_with_errors(buf: *const u8, len: usize) -> SIMDUTFResult; pub fn simdutf__validate_ascii(buf: *const u8, len: usize) -> bool; @@ -60,6 +61,12 @@ unsafe extern "C" { pub fn simdutf__utf8_length_from_latin1(input: *const u8, length: usize) -> usize; } +/// Replaces simdutf's "unsupported" stub (every call returns 0 / false) with a +/// compiled-in kernel. Call once at process start, before any thread. +pub fn init() { + simdutf__init(); +} + pub mod validate { use super::*; diff --git a/test/regression/issue/41361.test.ts b/test/regression/issue/41361.test.ts new file mode 100644 index 000000000000..751fd8e6fbe3 --- /dev/null +++ b/test/regression/issue/41361.test.ts @@ -0,0 +1,26 @@ +import { expect, test } from "bun:test"; +import { bunEnv, bunExe, tempDir } from "harness"; + +// simdutf picks its SIMD kernel by CPUID at first use. When no compiled-in +// kernel matches (QEMU's default CPU model hides SSE4.2), it installs a stub +// whose every call returns 0 or false. SIMDUTF_FORCE_IMPLEMENTATION with an +// unknown name installs the same stub on any machine. Bun used to spin forever +// in a Latin-1 to UTF-8 loop on the first ASCII string longer than 32 bytes, +// which is the entry point path, before it opened the entry file. +test("bun starts when simdutf finds no supported kernel", async () => { + using dir = tempDir("simdutf-no-supported-kernel", { + "entry-file-with-a-name-longer-than-thirty-two-bytes.mjs": `console.log("ok");`, + }); + await using proc = Bun.spawn({ + cmd: [bunExe(), `${dir}/entry-file-with-a-name-longer-than-thirty-two-bytes.mjs`], + env: { ...bunEnv, SIMDUTF_FORCE_IMPLEMENTATION: "bogus" }, + cwd: String(dir), + stdout: "pipe", + stderr: "pipe", + }); + const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]); + expect(stdout).toBe("ok\n"); + expect(stderr).toBe(""); + expect(proc.signalCode).toBeNull(); + expect(exitCode).toBe(0); +});