Repository navigation
fix: report odd json object arguments and errors at end of input - #7
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No configured credential can serve this run. Your Claude Pro/Max subscription was rejected. Sign in again by running The providers' responses
|
95fce7e to
2b5e2ec
Compare
There was a problem hiding this comment.
Important
odd_pairs panics on an unquoted non-ASCII identifier inside a JSON object call. Under the release profile's panic = "abort", that panic traps the wasm engine, so a statement that analyzed fine before this PR now crashes it.
Reviewed changes
This is the first Pullfrog review of the PR. It covers the single commit 2b5e2ec.
- Added
odd_pairsin core: it scans the text outside strings and comments for JSON object constructor calls with an odd argument count and reports them asreylo15. - Wired the check into Postgres and SQLite: Postgres runs it on
json_build_object/jsonb_build_objectwhen they are the built-ins. SQLite runs it onjson_object/jsonb_object. - Moved end-of-input errors onto the last word:
db_diagnosticnow places a server position at or past the end of the text on the statement's last word instead of byte 0. - Split the oracle's savepoint from the statement:
SAVEPOINT qis now sent on its own, so a statement that does not parse no longer takes the savepoint down with it. Oracle errors now go throughmessage(&e). - Added oracle cases:
odd_json_pairsandsqlite_odd_json_pairs. The threeengine.wasmartifacts were rebuilt.
claude-opus-5-5 | 𝕏
2b5e2ec to
e89568c
Compare
There was a problem hiding this comment.
✅ No new issues found. Both earlier findings are fixed, and I resolved their threads.
Reviewed changes
This run covers what changed since the last Pullfrog review (2b5e2ec → e89568c).
- Made
odd_pairscompare bytes, not string slices: it matches the constructor names andVARIADICon bytes and treats every byte past ASCII as part of a name. A non-ASCII identifier no longer panics the scan, and names likeéjson_build_objectandvariadicéare no longer mistaken for the constructor or the keyword. - Limited the end-of-input placement to Postgres's whitespace:
db_diagnosticnow splits on the newis_space(the ASCII whitespace Postgres's scanner uses). So a no-break space before the end of input can no longer put the start inside a character. - Skipped SQLite constructors the host shadows: the check drops
json_object/jsonb_objectwhenextras.totalregisters the name, or when the host's function list shows it with a fixed argument count. A new unit test covers both cases.
I ran the new core and SQLite unit tests (a_json_object_of_an_odd_count_of_arguments_is_an_error_at_its_name, ..._is_built_in_alone), and both pass.
claude-opus-5-5 | 𝕏
e89568c to
b82d449
Compare
- json_build_object, jsonb_build_object and SQLite's json_object with an odd number of arguments are an error (reylo15) at the call's name: the database prepares such a call and refuses it only when it runs - a syntax error at the end of the statement is placed on its last word rather than on its first character - the oracle sets its savepoint apart from the statement, so a statement that does not parse is reported with the server's message
- the odd-argument scan compares bytes, so a name such as café among the arguments no longer slices inside a character, and it reads a byte past ascii as part of a name, as Postgres and SQLite do - the end-of-input placement splits words on Postgres's ascii whitespace, so a no-break space no longer puts its start mid-character - SQLite skips json_object and jsonb_object where the host registers a function of that name, which a call resolves to in the built-in's place
b82d449 to
6563e7f
Compare

Three diagnostics that pointed at the wrong place or said nothing.
select json_build_object('id', id, 'name') from treylo15onjson_build_object: it takes keys and values in pairs, and this call has 3 argumentsselect json_object('id', id, 'name') from t(SQLite)reylo15onjson_objectselect id from t wherewhere, the statement's last wordanalysis::odd_pairsin core): commas at the call's own depth, an empty call is zero arguments, and aVARIADICargument, a schema-qualified name or a user's function that shadows the built-in proves nothing. Postgres checksjson_build_objectandjsonb_build_object, SQLitejson_objectandjsonb_object; MySQL already refuses an oddJSON_OBJECTwhen it prepares it.positionfor an end-of-input error) is placed on the last word.SAVEPOINT q; <statement>as one query, so a statement that did not parse failed the savepoint with it, and the case failed with tokio-postgres's bare "db error". The savepoint now goes on its own, and every Postgres error the oracle prints carries the server's message.New oracle cases
odd_json_pairs(Postgres) andsqlite_odd_json_pairs. Verified locally: the engine's native tests, every oracle case on Postgres 18.6, SQLite and MySQL 8.4 with--strict-coverage, the rebuiltengine.wasmartifacts,nub run typecheck, the loader's tests with every lab installed, the package build and the docs site.