Commit d729882
authored
Merge 'fix: adjust
Caught by differential fuzzer
`PRAGMA integrity_check` incorrectly flagged rows with NULL values as
CHECK constraint violations. Per the SQL standard, NULL does not violate
CHECK constraints — SQLite correctly allows NULLs and reports `ok` on
integrity check, but Turso's integrity check reported false positives
like:
```
CHECK constraint failed in t1
```
This was the root cause of 3 fuzzer-reported "data corruption" failures
(seeds: `4713306089706541904`, `13879125450750994315`,
`16798752381237836570`). The data itself was correct — only the
integrity check diagnosis was wrong.
### Reproducer
```sql
CREATE TABLE t1 (id INTEGER PRIMARY KEY, val REAL CHECK (val > 0));
INSERT INTO t1 (id, val) VALUES (1, NULL); -- NULL passes CHECK (correct)
PRAGMA integrity_check;
-- SQLite: ok
-- Turso (before fix): CHECK constraint failed in t1
-- Turso (after fix): ok
```
### Root Cause
In `core/translate/expr.rs`, `emit_binary_condition_insn` controls the
`jump_if_null` flag on comparison instructions (`Gt`, `Lt`, `Eq`, etc.).
The flag was only set when `jump_if_condition_is_true == false` (the
common WHERE clause path). When `jump_if_condition_is_true == true` (as
used by integrity_check), NULL comparisons fell through to the error
path instead of jumping to the "check ok" label.
The integrity check emits CHECK validation with
`jump_if_condition_is_true: true` and `jump_target_when_null: check_ok`,
but the comparison instruction had no `jump_if_null` flag, so `NULL > 0`
evaluated to NULL, didn't jump, and fell through to report a false
violation.
### Fix
Changed the `jump_if_null` flag logic to be driven by whether
`jump_target_when_null` matches the jump target, rather than being
hardcoded per direction:
- `jump_if_condition_is_true == true`: set `jump_if_null` when
`null_target == true_target`
- `jump_if_condition_is_true == false`: set `jump_if_null` when
`null_target == false_target`
This is backward-compatible — all existing callers with
`jump_if_condition_is_true == false` already have `null_target ==
false_target`.
Claude did it all
Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com>
Closes #5495jump_if_null branch offset as incorrectly failed NULL in check constraints in integrity checks' from Pedro MunizFile tree
2 files changed
+35
-12
lines changed- core/translate
- testing/runner/tests
2 files changed
+35
-12
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3823 | 3823 | | |
3824 | 3824 | | |
3825 | 3825 | | |
3826 | | - | |
3827 | | - | |
3828 | | - | |
3829 | | - | |
3830 | | - | |
3831 | | - | |
3832 | | - | |
| 3826 | + | |
| 3827 | + | |
| 3828 | + | |
| 3829 | + | |
| 3830 | + | |
| 3831 | + | |
| 3832 | + | |
| 3833 | + | |
| 3834 | + | |
| 3835 | + | |
| 3836 | + | |
3833 | 3837 | | |
3834 | 3838 | | |
3835 | 3839 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1655 | 1655 | | |
1656 | 1656 | | |
1657 | 1657 | | |
1658 | | - | |
1659 | | - | |
1660 | | - | |
| 1658 | + | |
| 1659 | + | |
| 1660 | + | |
| 1661 | + | |
| 1662 | + | |
| 1663 | + | |
| 1664 | + | |
| 1665 | + | |
| 1666 | + | |
1661 | 1667 | | |
1662 | | - | |
1663 | | - | |
| 1668 | + | |
| 1669 | + | |
1664 | 1670 | | |
1665 | 1671 | | |
| 1672 | + | |
| 1673 | + | |
| 1674 | + | |
| 1675 | + | |
| 1676 | + | |
| 1677 | + | |
| 1678 | + | |
| 1679 | + | |
| 1680 | + | |
| 1681 | + | |
| 1682 | + | |
| 1683 | + | |
| 1684 | + | |
1666 | 1685 | | |
1667 | 1686 | | |
1668 | 1687 | | |
| |||
0 commit comments