8000 fix: refuse text for a binary parameter by colinhacks · Pull Request #40 · colinhacks/reylo · GitHub
[go: up one dir, main page]

Skip to content

fix: refuse text for a binary parameter - #40

Merged
colinhacks merged 3 commits into
mainfrom
binary-param-check
Oct 22, 2026
Merged

colinhacks merged 3 commits into
mainfrom
binary-param-check

Conversation

@colinhacks
Copy link
Copy Markdown
Owner

A binary parameter (bytea on Postgres, BINARY, VARBINARY and BLOB on MySQL, BLOB on SQLite) is typed Uint8Array, but .run() passed any other value to the driver unchanged. A string then means something different on each database: Postgres reads it as bytea's hex or escape text, MySQL stores the bytes of its UTF-8, and SQLite stores it as TEXT, which comes back a string where the column's type says Uint8Array. Base64 text, for one, was stored as its own letters.

.run() now refuses anything but a Uint8Array (a Buffer is one) for a binary parameter, and for each element of a binary array, before the statement runs, the way a structured parameter's binary member already did:

Parameter "b" is binary data, so it takes a Uint8Array (a Buffer is one), as `.run()` returns one; got "AQL/". Decode base64 or hex text into one first.
  • src/execute.ts: checkBinary, beside the date and time checks.
  • src/rows.ts: exports describe for the message.
  • tests/execute.test.ts: the refusal on all three dialects, for a scalar and an array element, and that a Buffer, a Uint8Array and null still bind.

nub run typecheck and nub run test pass locally (the server-backed tests run in CI).

Copilot AI balanced review requested due to automatic review settings October 22, 2026 21:58
@vercel
vercel Bot commented Oct 22, 2026 •
Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
reylo Ready Ready Preview Oct 22, 2026 10:23pm UTC

Request Review

Copilot AI left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@pullfrog pullfrog Bot left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ No critical issues. Two small suggestions: a hint in the error message and a docs gap.

Reviewed changes

I reviewed the new run-time check that refuses any value other than a Uint8Array for a binary parameter, and its tests.

  • checkBinary in statement(): a scalar parameter whose engine type is exactly bytea or blob, or an element of an array of one, must be a Uint8Array. Otherwise .run() throws a ParameterError before the statement runs. This matches what renderParamType already gives as the TS type, and the check a structured parameter's binary member already had in src/rows.ts.
  • Scope checked against the engine: an unnarrowed MySQL BIT context is typed bool|bytea (param_type in engine/mysql/src/mysql.rs). The match is on the exact name, so it isn't checked, and BIT(1) columns keep taking truth values. On SQLite, an untyped column or a STRICT ANY column is unknown, not blob, so it isn't affected either.
  • Tests: node --test tests/execute.test.ts passes (46/46) at 687c06a.

ℹ️ The docs don't mention the new refusal

The "Binary parameters" rules say only that a binary parameter "takes a Uint8Array, a Buffer or not, on every driver". The Postgres parameter bullets list each refusal .run() makes before the statement runs: text without a zone, a Date, a NULL array element. This one isn't there, so a reader still can't tell that base64 or hex text is now refused rather than stored.

Technical details
# Document that `.run()` refuses a non-Uint8Array binary parameter

## Affected sites
- site/content/docs/postgres.mdx:443-445 — "Binary parameters" rule; also the parameter bullets at ~L741-748
- site/content/docs/sqlite.mdx:429-431 — "Binary parameters" rule
- site/content/docs/mysql.mdx:414+ — "Binary" section (BINARY, VARBINARY, BLOB, BIT wider than 1)

## Required outcome
- Each dialect's docs say that a binary parameter refuses any other value, base64 or hex text included, before the statement runs, and say to decode the text into a `Uint8Array` first.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using claude-opus-5-5 | 𝕏

Comment thread src/execute.ts Resolved
@pullfrog pullfrog Bot left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found. Both points from the last review are addressed.

Reviewed changes

I reviewed the two commits pushed since the last review: one changes the refusal message, the other updates the docs.

  • ArrayBuffer hint: when the value is an ArrayBuffer, checkBinary now ends its message with "Wrap an ArrayBuffer in one: new Uint8Array(buffer)." instead of the base64 or hex hint. The test now checks the whole message.
  • Docs: the binary parameter rule in postgres.mdx, mysql.mdx and sqlite.mdx now says that any other value, base64 or hex text included, is refused before the statement runs, and says to decode the text first. The Postgres parameter list has a matching bytea bullet.
  • Tests: node --test tests/execute.test.ts passes (46/46) at 7d448bd.

Pullfrog  | View workflow run | Using claude-opus-5-5 | 𝕏

A binary parameter is typed Uint8Array, but run passed any other value to
the driver as it was. A string then meant something different on each
database, and base64 text was stored as its own letters. A structured
parameter's binary member already refused it.
@pullfrog pullfrog Bot left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found. The rebase leaves the check as it was and moves the docs into main's rewritten pages.

Reviewed changes

Since the last review, the branch was rebased onto main, where the database docs pages had been rewritten. src/execute.ts, src/rows.ts and the test are unchanged apart from context lines.

  • Docs moved into "What a parameter takes": the old "Binary parameters" sections are gone from main, so the refusal is now one line on each page. postgres.mdx and mysql.mdx have it as a bullet beside the date and JSON rules. sqlite.mdx has it as a sentence under the type table, because that section has no list. Each one says a binary parameter takes only a Uint8Array, gives the per‑database reason, and says to decode the text first.
  • Tests: node --test tests/execute.test.ts passes (46/46) at 3913d4b.

Pullfrog  | View workflow run | Using claude-opus-5-5 | 𝕏

@colinhacks
colinhacks merged commit 50b2583 into main Oct 22, 2026
6 checks passed
@colinhacks
colinhacks deleted the binary-param-check branch October 22, 2026 22:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

0