From d7dc5f3f876a41e84572b12a2d793fdbedafb3cf Mon Sep 17 00:00:00 2001 From: robobun Date: Tue, 28 Apr 2026 23:12:48 +0000 Subject: [PATCH 1/8] sql(mysql): bounds-check params in bind() when values array is mutated MySQLQuery.bind() allocates a params buffer sized to the signature that was captured when the statement was first prepared, then iterates a fresh QueryBindingIterator over the user-supplied values array. If the array is mutated between signature generation and binding (e.g. via an index getter that pushes, or between prepare and execute), the second iteration can be longer than the first, causing an out-of-bounds read of execute.param_types and an out-of-bounds heap write into params. PostgresRequest.writeBind already guards this case; MySQL did not. Fail with ERR_MYSQL_WRONG_NUMBER_OF_PARAMETERS_PROVIDED when the iterator yields a different count than the statement expects, instead of writing past the allocation (or leaving trailing slots uninitialized in the shrink case). --- src/sql/mysql/MySQLQuery.zig | 13 +++++++ test/js/sql/sql-mysql-bind-oob.fixture.ts | 44 +++++++++++++++++++++++ test/js/sql/sql-mysql.test.ts | 32 ++++++++++++++++- 3 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 test/js/sql/sql-mysql-bind-oob.fixture.ts diff --git a/src/sql/mysql/MySQLQuery.zig b/src/sql/mysql/MySQLQuery.zig index 563701df5d7..32cf0f2e174 100644 --- a/src/sql/mysql/MySQLQuery.zig +++ b/src/sql/mysql/MySQLQuery.zig @@ -24,6 +24,13 @@ fn bind(this: *MySQLQuery, execute: *PreparedStatement.Execute, globalObject: *J bun.default_allocator.free(params); } while (try iter.next()) |js_value| { + if (i >= params.len) { + // The binding array yielded more values than the prepared statement + // expects. This can happen when the user-supplied array is mutated (e.g. + // from an index getter) between signature generation and binding. Fail + // loudly instead of writing past the end of `params`/`param_types`. + return error.WrongNumberOfParametersProvided; + } const param = execute.param_types[i]; params[i] = try Value.fromJS( js_value, @@ -38,6 +45,12 @@ fn bind(this: *MySQLQuery, execute: *PreparedStatement.Execute, globalObject: *J return error.InvalidQueryBinding; } + if (i != params.len) { + // Fewer values than the prepared statement expects; the remaining slots + // would be uninitialized. + return error.WrongNumberOfParametersProvided; + } + this.#status = .binding; execute.params = params; } diff --git a/test/js/sql/sql-mysql-bind-oob.fixture.ts b/test/js/sql/sql-mysql-bind-oob.fixture.ts new file mode 100644 index 00000000000..d5567e162a3 --- /dev/null +++ b/test/js/sql/sql-mysql-bind-oob.fixture.ts @@ -0,0 +1,44 @@ +// Reproducer for an out-of-bounds write in MySQLQuery.bind(). +// +// Signature.generate() and bind() each create a fresh iterator over the +// user-supplied params array. If an index getter mutates the array so that +// the second iteration is longer than the first, bind() would index past the +// `params` / `param_types` buffers it sized based on the first iteration. +// +// Without the bounds check this panics in debug builds (index out of bounds) +// and is a silent heap overflow in release builds. + +import { SQL } from "bun"; + +const url = process.env.MYSQL_URL; +if (!url) throw new Error("MYSQL_URL is required"); + +const tls = process.env.CA_PATH ? { ca: Bun.file(process.env.CA_PATH) } : undefined; +const sql = new SQL({ url, tls, max: 1 }); + +try { + // Prime the prepared-statement cache so the next call with the same + // signature goes straight to bindAndExecute without re-preparing. + await sql.unsafe("select ? as x", [1]); + + const values: number[] = [1]; + let fired = 0; + Object.defineProperty(values, "0", { + enumerable: true, + configurable: true, + get() { + if (fired++ === 0) { + for (let i = 0; i < 100; i++) values.push(1); + } + return 1; + }, + }); + + const result = await sql.unsafe("select ? as x", values).then( + rows => ({ ok: true, rows }), + err => ({ ok: false, code: err?.code, message: String(err?.message ?? err) }), + ); + console.log(JSON.stringify(result)); +} finally { + await sql.close(); +} diff --git a/test/js/sql/sql-mysql.test.ts b/test/js/sql/sql-mysql.test.ts index 0228dcf82d4..3708f57f9d5 100644 --- a/test/js/sql/sql-mysql.test.ts +++ b/test/js/sql/sql-mysql.test.ts @@ -1,6 +1,6 @@ import { SQL, randomUUIDv7 } from "bun"; import { beforeAll, describe, expect, mock, test } from "bun:test"; -import { bunEnv, bunRun, describeWithContainer, isDockerEnabled, tempDirWithFiles } from "harness"; +import { bunEnv, bunExe, bunRun, describeWithContainer, isDockerEnabled, tempDirWithFiles } from "harness"; import net from "net"; import path from "path"; const dir = tempDirWithFiles("sql-test", { @@ -817,6 +817,36 @@ if (isDockerEnabled()) { expect(await sql.unsafe("select 1 as x")).toEqual([{ x: 1 }]); }); + test("unsafe does not OOB when the params array grows during binding", async () => { + // Signature generation and binding each iterate the user-supplied params + // array. If an index getter mutates the array so that the second + // iteration is longer than the first, bind() must not read/write past + // the param buffer it allocated based on the first iteration's length. + // Run in a subprocess so a crash doesn't take down the rest of the suite. + await using proc = Bun.spawn({ + cmd: [bunExe(), path.join(import.meta.dir, "sql-mysql-bind-oob.fixture.ts")], + env: { + ...bunEnv, + MYSQL_URL: String(getOptions().url), + CA_PATH: image.name === "MySQL with TLS" ? path.join(import.meta.dir, "mysql-tls", "ssl", "ca.pem") : "", + }, + stdout: "pipe", + stderr: "pipe", + }); + const [stdout, stderr, exitCode] = await Promise.all([ + proc.stdout.text(), + proc.stderr.text(), + proc.exited, + ]); + expect(stderr).toBe(""); + expect(JSON.parse(stdout.trim())).toEqual({ + ok: false, + code: "ERR_MYSQL_WRONG_NUMBER_OF_PARAMETERS_PROVIDED", + message: expect.any(String), + }); + expect(exitCode).toBe(0); + }); + test("simple query with multiple statements", async () => { await using sql = new SQL({ ...getOptions(), max: 1 }); const result = await sql`select 1 as x;select 2 as x`.simple(); From 15256769ea084811e38dd46b4b80a004ae6592b2 Mon Sep 17 00:00:00 2001 From: robobun Date: Wed, 29 Apr 2026 01:07:54 +0000 Subject: [PATCH 2/8] sql(mysql): bind before writing packet header so bind errors don't desync MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bindAndExecute previously called writer.start(0) (which appends a 4-byte placeholder header to the connection's write buffer) before bind(). If bind() failed — now reachable via the new param-count guard, but already reachable via Value.fromJS / iterator errors — those bytes were left in the buffer and prefixed the next query on the pooled connection, causing a protocol desync (server responds 1047 Unknown command). bind() never touches the writer, so run it first. Also defer clearing need_to_send_params until after bind() succeeds so a failed bind doesn't skip param types on the next execution. The regression fixture now also asserts the connection remains usable after the rejected bind. --- src/sql/mysql/MySQLQuery.zig | 7 +++++-- test/js/sql/sql-mysql-bind-oob.fixture.ts | 7 ++++++- test/js/sql/sql-mysql.test.ts | 10 +++++++--- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/sql/mysql/MySQLQuery.zig b/src/sql/mysql/MySQLQuery.zig index 32cf0f2e174..d8ed4fadd40 100644 --- a/src/sql/mysql/MySQLQuery.zig +++ b/src/sql/mysql/MySQLQuery.zig @@ -60,16 +60,19 @@ fn bindAndExecute(this: *MySQLQuery, writer: anytype, statement: *MySQLStatement if (statement.signature.fields.len != statement.params.len) { return error.WrongNumberOfParametersProvided; } - var packet = try writer.start(0); var execute = PreparedStatement.Execute{ .statement_id = statement.statement_id, .param_types = statement.signature.fields, .new_params_bind_flag = statement.execution_flags.need_to_send_params, .iteration_count = 1, }; - statement.execution_flags.need_to_send_params = false; defer execute.deinit(); + // Bind before touching the writer so a bind failure (user-triggerable via JS + // getters / param-count mismatch) doesn't leave a partial packet header in + // the connection's write buffer. try this.bind(&execute, globalObject, binding_value, columns_value); + statement.execution_flags.need_to_send_params = false; + var packet = try writer.start(0); try execute.write(writer); try packet.end(); this.#status = .running; diff --git a/test/js/sql/sql-mysql-bind-oob.fixture.ts b/test/js/sql/sql-mysql-bind-oob.fixture.ts index d5567e162a3..5dc59a4df48 100644 --- a/test/js/sql/sql-mysql-bind-oob.fixture.ts +++ b/test/js/sql/sql-mysql-bind-oob.fixture.ts @@ -38,7 +38,12 @@ try { rows => ({ ok: true, rows }), err => ({ ok: false, code: err?.code, message: String(err?.message ?? err) }), ); - console.log(JSON.stringify(result)); + + // The connection must still be usable after the bind failure; a partial + // packet header left in the write buffer would desync the protocol here. + const after = await sql.unsafe("select ? as x", [2]); + + console.log(JSON.stringify({ result, after })); } finally { await sql.close(); } diff --git a/test/js/sql/sql-mysql.test.ts b/test/js/sql/sql-mysql.test.ts index 3708f57f9d5..caeb6a342c6 100644 --- a/test/js/sql/sql-mysql.test.ts +++ b/test/js/sql/sql-mysql.test.ts @@ -840,9 +840,13 @@ if (isDockerEnabled()) { ]); expect(stderr).toBe(""); expect(JSON.parse(stdout.trim())).toEqual({ - ok: false, - code: "ERR_MYSQL_WRONG_NUMBER_OF_PARAMETERS_PROVIDED", - message: expect.any(String), + result: { + ok: false, + code: "ERR_MYSQL_WRONG_NUMBER_OF_PARAMETERS_PROVIDED", + message: expect.any(String), + }, + // Connection must remain usable after the bind failure. + after: [{ x: 2 }], }); expect(exitCode).toBe(0); }); From f133e381a9a7e1e19be41f52610983b6453366b9 Mon Sep 17 00:00:00 2001 From: robobun Date: Wed, 29 Apr 2026 01:46:56 +0000 Subject: [PATCH 3/8] sql(mysql): clear need_to_send_params only after packet fully written --- src/sql/mysql/MySQLQuery.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sql/mysql/MySQLQuery.zig b/src/sql/mysql/MySQLQuery.zig index d8ed4fadd40..fd657fb5b49 100644 --- a/src/sql/mysql/MySQLQuery.zig +++ b/src/sql/mysql/MySQLQuery.zig @@ -71,10 +71,10 @@ fn bindAndExecute(this: *MySQLQuery, writer: anytype, statement: *MySQLStatement // getters / param-count mismatch) doesn't leave a partial packet header in // the connection's write buffer. try this.bind(&execute, globalObject, binding_value, columns_value); - statement.execution_flags.need_to_send_params = false; var packet = try writer.start(0); try execute.write(writer); try packet.end(); + statement.execution_flags.need_to_send_params = false; this.#status = .running; } From 6156bc3f0bf41adc0ed1fb20dee59a28bc65afe7 Mon Sep 17 00:00:00 2001 From: robobun Date: Wed, 29 Apr 2026 01:50:05 +0000 Subject: [PATCH 4/8] test(mysql): filter ASAN startup warning from subprocess stderr --- test/js/sql/sql-mysql.test.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/js/sql/sql-mysql.test.ts b/test/js/sql/sql-mysql.test.ts index caeb6a342c6..6087d6ca824 100644 --- a/test/js/sql/sql-mysql.test.ts +++ b/test/js/sql/sql-mysql.test.ts @@ -838,7 +838,11 @@ if (isDockerEnabled()) { proc.stderr.text(), proc.exited, ]); - expect(stderr).toBe(""); + const filteredStderr = stderr + .split(/\r?\n/) + .filter(l => l && !l.startsWith("WARNING: ASAN interferes")) + .join("\n"); + expect(filteredStderr).toBe(""); expect(JSON.parse(stdout.trim())).toEqual({ result: { ok: false, From 8fd83e8633145661d0015ccf9c56143cd190c266 Mon Sep 17 00:00:00 2001 From: robobun Date: Wed, 29 Apr 2026 02:26:33 +0000 Subject: [PATCH 5/8] test(mysql): move bind-OOB regression to standalone test file The test needs a MySQL server but sql-mysql.test.ts is fully docker-gated; in environments without a docker daemon it runs 0 tests. Move the regression to its own file that uses describeWithContainer when docker is available and otherwise falls back to MYSQL_URL / a local 127.0.0.1:3306 instance (distinguishing 'couldn't connect' from 'connected then crashed' via a CONNECTED marker printed after the priming query). --- test/js/sql/sql-mysql-bind-oob.fixture.ts | 3 + test/js/sql/sql-mysql-bind-oob.test.ts | 79 +++++++++++++++++++++++ test/js/sql/sql-mysql.test.ts | 40 +----------- 3 files changed, 83 insertions(+), 39 deletions(-) create mode 100644 test/js/sql/sql-mysql-bind-oob.test.ts diff --git a/test/js/sql/sql-mysql-bind-oob.fixture.ts b/test/js/sql/sql-mysql-bind-oob.fixture.ts index 5dc59a4df48..f8038386584 100644 --- a/test/js/sql/sql-mysql-bind-oob.fixture.ts +++ b/test/js/sql/sql-mysql-bind-oob.fixture.ts @@ -20,6 +20,9 @@ try { // Prime the prepared-statement cache so the next call with the same // signature goes straight to bindAndExecute without re-preparing. await sql.unsafe("select ? as x", [1]); + // Marker so the test harness can distinguish "couldn't connect" from + // "connected then crashed" when no docker-managed MySQL is available. + console.log("CONNECTED"); const values: number[] = [1]; let fired = 0; diff --git a/test/js/sql/sql-mysql-bind-oob.test.ts b/test/js/sql/sql-mysql-bind-oob.test.ts new file mode 100644 index 00000000000..ba329351fa7 --- /dev/null +++ b/test/js/sql/sql-mysql-bind-oob.test.ts @@ -0,0 +1,79 @@ +import { test, expect, describe } from "bun:test"; +import { bunEnv, bunExe, describeWithContainer, isDockerEnabled } from "harness"; +import path from "path"; + +// Regression: MySQLQuery.bind() allocates `params` sized to the prepared +// statement's signature and then iterates a *fresh* iterator over the user's +// values array. If that array grew between signature generation and bind +// (e.g. via an index getter with side effects), bind() would walk off the +// end of the allocation. With the fix it rejects with +// ERR_MYSQL_WRONG_NUMBER_OF_PARAMETERS_PROVIDED and the connection stays +// usable. + +const fixture = path.join(import.meta.dir, "sql-mysql-bind-oob.fixture.ts"); + +async function runFixture(url: string, caPath = "") { + await using proc = Bun.spawn({ + cmd: [bunExe(), fixture], + env: { ...bunEnv, MYSQL_URL: url, CA_PATH: caPath }, + stdout: "pipe", + stderr: "pipe", + }); + const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]); + return { stdout, stderr, exitCode }; +} + +function assertFixtureOutput(stdout: string, stderr: string, exitCode: number) { + const filteredStderr = stderr + .split(/\r?\n/) + .filter(l => l && !l.startsWith("WARNING: ASAN interferes")) + .join("\n"); + expect(filteredStderr).toBe(""); + const lines = stdout.trim().split(/\r?\n/); + expect(lines[0]).toBe("CONNECTED"); + expect(JSON.parse(lines[1] ?? "null")).toEqual({ + result: { + ok: false, + code: "ERR_MYSQL_WRONG_NUMBER_OF_PARAMETERS_PROVIDED", + message: expect.any(String), + }, + after: [{ x: 2 }], + }); + expect(exitCode).toBe(0); +} + +if (isDockerEnabled()) { + // CI: run against the docker-compose MySQL service. + describeWithContainer("mysql", { image: "mysql_plain" }, container => { + test("bind() does not OOB when the params array grows during binding", async () => { + await container.ready; + const url = `mysql://root@${container.host}:${container.port}/bun_sql_test`; + const { stdout, stderr, exitCode } = await runFixture(url); + assertFixtureOutput(stdout, stderr, exitCode); + }); + }); +} else { + // No docker daemon (e.g. local/sandboxed environments). If a MySQL server + // is reachable at MYSQL_URL or the conventional local address, exercise the + // fixture there so the regression is still covered. + const url = process.env.MYSQL_URL || "mysql://bun@127.0.0.1:3306/bun_sql_test"; + + describe("mysql (local)", () => { + test( + "bind() does not OOB when the params array grows during binding", + async () => { + const { stdout, stderr, exitCode } = await runFixture(url); + // The fixture prints "CONNECTED" after the priming query succeeds. If + // it never got that far, there's no MySQL to talk to in this + // environment; the docker-gated branch above (and sql-mysql.test.ts) + // provide the CI coverage. + if (!stdout.startsWith("CONNECTED")) { + console.warn("sql-mysql-bind-oob: no MySQL reachable at " + url + "; skipping assertions"); + return; + } + assertFixtureOutput(stdout, stderr, exitCode); + }, + 30_000, + ); + }); +} diff --git a/test/js/sql/sql-mysql.test.ts b/test/js/sql/sql-mysql.test.ts index 6087d6ca824..0228dcf82d4 100644 --- a/test/js/sql/sql-mysql.test.ts +++ b/test/js/sql/sql-mysql.test.ts @@ -1,6 +1,6 @@ import { SQL, randomUUIDv7 } from "bun"; import { beforeAll, describe, expect, mock, test } from "bun:test"; -import { bunEnv, bunExe, bunRun, describeWithContainer, isDockerEnabled, tempDirWithFiles } from "harness"; +import { bunEnv, bunRun, describeWithContainer, isDockerEnabled, tempDirWithFiles } from "harness"; import net from "net"; import path from "path"; const dir = tempDirWithFiles("sql-test", { @@ -817,44 +817,6 @@ if (isDockerEnabled()) { expect(await sql.unsafe("select 1 as x")).toEqual([{ x: 1 }]); }); - test("unsafe does not OOB when the params array grows during binding", async () => { - // Signature generation and binding each iterate the user-supplied params - // array. If an index getter mutates the array so that the second - // iteration is longer than the first, bind() must not read/write past - // the param buffer it allocated based on the first iteration's length. - // Run in a subprocess so a crash doesn't take down the rest of the suite. - await using proc = Bun.spawn({ - cmd: [bunExe(), path.join(import.meta.dir, "sql-mysql-bind-oob.fixture.ts")], - env: { - ...bunEnv, - MYSQL_URL: String(getOptions().url), - CA_PATH: image.name === "MySQL with TLS" ? path.join(import.meta.dir, "mysql-tls", "ssl", "ca.pem") : "", - }, - stdout: "pipe", - stderr: "pipe", - }); - const [stdout, stderr, exitCode] = await Promise.all([ - proc.stdout.text(), - proc.stderr.text(), - proc.exited, - ]); - const filteredStderr = stderr - .split(/\r?\n/) - .filter(l => l && !l.startsWith("WARNING: ASAN interferes")) - .join("\n"); - expect(filteredStderr).toBe(""); - expect(JSON.parse(stdout.trim())).toEqual({ - result: { - ok: false, - code: "ERR_MYSQL_WRONG_NUMBER_OF_PARAMETERS_PROVIDED", - message: expect.any(String), - }, - // Connection must remain usable after the bind failure. - after: [{ x: 2 }], - }); - expect(exitCode).toBe(0); - }); - test("simple query with multiple statements", async () => { await using sql = new SQL({ ...getOptions(), max: 1 }); const result = await sql`select 1 as x;select 2 as x`.simple(); From 325c8ff78167d197c98a1eb46da8d024caefdedb Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 02:28:18 +0000 Subject: [PATCH 6/8] [autofix.ci] apply automated fixes --- test/js/sql/sql-mysql-bind-oob.test.ts | 30 +++++++++++--------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/test/js/sql/sql-mysql-bind-oob.test.ts b/test/js/sql/sql-mysql-bind-oob.test.ts index ba329351fa7..a7d2bc5368c 100644 --- a/test/js/sql/sql-mysql-bind-oob.test.ts +++ b/test/js/sql/sql-mysql-bind-oob.test.ts @@ -1,4 +1,4 @@ -import { test, expect, describe } from "bun:test"; +import { describe, expect, test } from "bun:test"; import { bunEnv, bunExe, describeWithContainer, isDockerEnabled } from "harness"; import path from "path"; @@ -59,21 +59,17 @@ if (isDockerEnabled()) { const url = process.env.MYSQL_URL || "mysql://bun@127.0.0.1:3306/bun_sql_test"; describe("mysql (local)", () => { - test( - "bind() does not OOB when the params array grows during binding", - async () => { - const { stdout, stderr, exitCode } = await runFixture(url); - // The fixture prints "CONNECTED" after the priming query succeeds. If - // it never got that far, there's no MySQL to talk to in this - // environment; the docker-gated branch above (and sql-mysql.test.ts) - // provide the CI coverage. - if (!stdout.startsWith("CONNECTED")) { - console.warn("sql-mysql-bind-oob: no MySQL reachable at " + url + "; skipping assertions"); - return; - } - assertFixtureOutput(stdout, stderr, exitCode); - }, - 30_000, - ); + test("bind() does not OOB when the params array grows during binding", async () => { + const { stdout, stderr, exitCode } = await runFixture(url); + // The fixture prints "CONNECTED" after the priming query succeeds. If + // it never got that far, there's no MySQL to talk to in this + // environment; the docker-gated branch above (and sql-mysql.test.ts) + // provide the CI coverage. + if (!stdout.startsWith("CONNECTED")) { + console.warn("sql-mysql-bind-oob: no MySQL reachable at " + url + "; skipping assertions"); + return; + } + assertFixtureOutput(stdout, stderr, exitCode); + }, 30_000); }); } From 89590a36ababb6ed0de0982492fdd4e9b561b0ab Mon Sep 17 00:00:00 2001 From: robobun Date: Wed, 29 Apr 2026 02:35:14 +0000 Subject: [PATCH 7/8] test(mysql): fail loudly if MYSQL_URL is set but unreachable --- test/js/sql/sql-mysql-bind-oob.test.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/test/js/sql/sql-mysql-bind-oob.test.ts b/test/js/sql/sql-mysql-bind-oob.test.ts index a7d2bc5368c..34110012262 100644 --- a/test/js/sql/sql-mysql-bind-oob.test.ts +++ b/test/js/sql/sql-mysql-bind-oob.test.ts @@ -63,9 +63,15 @@ if (isDockerEnabled()) { const { stdout, stderr, exitCode } = await runFixture(url); // The fixture prints "CONNECTED" after the priming query succeeds. If // it never got that far, there's no MySQL to talk to in this - // environment; the docker-gated branch above (and sql-mysql.test.ts) - // provide the CI coverage. + // environment; the docker-gated branch above provides the CI coverage. if (!stdout.startsWith("CONNECTED")) { + if (process.env.MYSQL_URL) { + // MYSQL_URL was explicitly provided; failing to connect is a real + // error, not an environment without MySQL. + throw new Error( + `sql-mysql-bind-oob: MYSQL_URL was provided but fixture never reached CONNECTED\nstdout:\n${stdout}\nstderr:\n${stderr}`, + ); + } console.warn("sql-mysql-bind-oob: no MySQL reachable at " + url + "; skipping assertions"); return; } From 1451d6de2d316a4bd8d7beecb22f4e411f50d7de Mon Sep 17 00:00:00 2001 From: robobun Date: Wed, 29 Apr 2026 07:39:16 +0000 Subject: [PATCH 8/8] test(mysql): drop explicit per-test timeout --- test/js/sql/sql-mysql-bind-oob.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/js/sql/sql-mysql-bind-oob.test.ts b/test/js/sql/sql-mysql-bind-oob.test.ts index 34110012262..700a146c5e5 100644 --- a/test/js/sql/sql-mysql-bind-oob.test.ts +++ b/test/js/sql/sql-mysql-bind-oob.test.ts @@ -76,6 +76,6 @@ if (isDockerEnabled()) { return; } assertFixtureOutput(stdout, stderr, exitCode); - }, 30_000); + }); }); }