v0.11 item 1a: a row that does not parse is one row too - #200
Merged
Merged
Conversation
An independent review found json.loads running outside _read_receipt's guard. Signed-off-by: arpan <contact@arpanghoshal.com>
Signed-off-by: arpan <contact@arpanghoshal.com>
|
Warning Review limit reachedNext included review available in 40 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (5)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #199, on a new branch because #199 was green and merged before this landed. An independent review of #199 found a hole in item 1's own claim, and it is a real one.
The defect
Item 1's reader is
_read_receipt, which catches whatReceipt.from_dictcan raise and returns anUnreadableReceiptinstead of blinding every caller. But both stores calledjson.loads(row["json"])in the generator expression that fed it, outside the guard.So a row whose stored
jsonis not JSON at all raised straight through, exactly as before v0.11. Measured atmain(7fb2068), oneUPDATE receipts SET json = 'not json at all' WHERE seq = 2on a four-receipt chain:Worse than before item 1, on one count:
JSONDecodeErroris not aCTRLRunError, socli/main.py's handler did not turn it into a clean message either, and the command printed a traceback where 0.10.0 printedError: ....The same store on this branch:
Why item 1's tests missed it
Every tamper they ran changed a row's content.
{}and[1.5]among the controls are both valid JSON, so the parse was never on trial.T514bwas written precisely to cover "a row that is not a receipt at all" and reached for{}, which parses.That is the same failure mode
SPEC-v0.10.md§11 records in a different costume: a test that covers the case you thought of covers the case you thought of. The fix is not only the code butT520, which parametrizes over seven ways a row can fail to parse rather than one.The fix
_read_receipttakes the stored text and parses inside its own guard.JSONDecodeErrorsubclassesValueError, which the caught tuple already carried, so the change is where the parse happens and not what is caught.A row that parses to something that is not an object is refused rather than trusted:
json.loads("3")is anint, and_stored_receiptwould have raisedTypeErroron it a line later. Naming it at the parse says what is wrong with the row rather than what the next line tripped over.Tests
T520, parametrized over seven tampers, each asserting one row is lost, the other three still read, the break lands at the rightseq, and no CLI prints a traceback:jsonnot json at allJSONDecodeErrorJSONDecodeError{"receipt_id": "ctr_1JSONDecodeError[1, 2, 3]TypeError3TypeError"a receipt"TypeErrornullTypeErrorT520bis the same against Postgres, because the amendment is toStateStoreand a backend that raised here would blind every reader in a deployment that uses it.Mutations
ValueErrordrops out of the caught setCounts
./scripts/check.shwith Postgres: 4420 passed + 66 serial.mainat 7fb2068 is 4412 + 66, so this adds 8 (sevenT520rows plusT520b). mypy--strictclean, ruff clean.Docs
None. No public name changes, no CLI surface changes, no schema changes: the only externally visible difference is that a command which used to print a traceback now prints its output.
🤖 Generated with Claude Code