|Title:||UPSERT results in a corrupt database|
|Last Modified:||2018-07-11 13:37:14|
|Version Found In:||3.24.0|
drh added on 2018-07-11 12:11:13:
An UPSERT discovered by OSSFuzz results in a corrupt database file: <blockquote><verbatim> CREATE TABLE t1( a INT, b INT, c INT UNIQUE, PRIMARY KEY(a,b) ) WITHOUT ROWID; INSERT INTO t1(a,b) VALUES(json(3),4),(1,2) ON CONFLICT(a,b) DO NOTHING; PRAGMA integrity_check; </verbatim></blockquote> The corruption is a missing entry from the unique index and is easily fixed using REINDEX. Nevertheless, this should not be happening.
drh added on 2018-07-11 12:12:20: (text/x-fossil-wiki)
Correction: The error case was not found by OSSFuzz but rather by the AFL fuzzer running locally.
drh added on 2018-07-11 12:50:58: (text/x-fossil-wiki)
Here is a simplified script to demonstrate the problem: <blockquote><verbatim> CREATE TABLE t1(b UNIQUE, a INT PRIMARY KEY) WITHOUT ROWID; INSERT INTO t1(a) VALUES('1'),(1) ON CONFLICT(a) DO NOTHING; PRAGMA integrity_check; </verbatim></blockquote>
drh added on 2018-07-11 13:37:14: (text/x-fossil-wiki)
The problem was that the affinity change from '1' to 1 on the PRIMARY KEY column was happening on the first constraint check in bytecode order, which is the UNIQUE constraint. But the PRIMARY KEY constraint was checked first, and hence was checked before the affinity change. The fix was to move the affinity change to before the branch that reorders the constraint checks for the UPSERT.