Details
-
Bug
-
Status: Confirmed (View Workflow)
-
Major
-
Resolution: Unresolved
-
10.11, 11.4, 11.8, 12.3, 13.1
Description
- MariaDB GIS NULL predicates violate three-valued filtering
Status: reproduced on MariaDB 13.0.2, source commit `620a4b5624222048fece7fe1789978ae0675cae2`.
-
- Minimal reproducer
```sql
SELECT ST_IsValid(NULL), ST_IsValid(NULL) IS NULL;
SELECT 1 WHERE ST_IsValid(NULL);
SELECT 1 WHERE NOT ST_IsValid(NULL);
SELECT 1 WHERE ST_IsValid(NULL) IS NULL;
SELECT ST_IsEmpty(NULL), ST_IsEmpty(NULL) IS NULL;
SELECT 1 WHERE ST_IsEmpty(NULL);
SELECT 1 WHERE NOT ST_IsEmpty(NULL);
SELECT 1 WHERE ST_IsEmpty(NULL) IS NULL;
```
-
- Actual and expected results
Both scalar GIS predicates evaluate to `NULL`, and `predicate IS NULL` evaluates to `1`.
For each predicate, SQL three-valued logic therefore requires the TRUE/FALSE/NULL partitions to contain `0/0/1` rows. MariaDB instead returns `1/0/1`: the same row is accepted by both the bare predicate and its `IS NULL` partition.
The result is stable without tables, data, special SQL mode, or optimizer-dependent query structure.
-
- Root cause
In MariaDB 13.0.2:
- `Item_func_isvalid::val_int()` sets `null_value=1` for a NULL/invalid argument but returns integer `1` (`sql/item_geofunc.cc:2136-2149`).
- The integer `val_bool` fallback evaluates only `val_int()!=0` and does not reject the accompanying NULL flag (`sql/sql_type.cc:5323-5341`).
- `Item_func_isempty::val_bool()` likewise sets the NULL flag and returns `1` (`sql/item_geofunc.cc:2226-2235`).
Thus the expressions remain NULL for scalar NULL inspection but expose a true boolean payload when used directly as conditions.
-
- Impact
Read-only queries can include rows that do not satisfy a GIS predicate. A NULL-valued condition is simultaneously selected by the TRUE and NULL partitions, violating SQL three-valued logic and making logically equivalent filters disagree.
-
- Duplicate audit
MDEV-35960 is related: it changed scalar `ST_IsValid(NULL)` from an error to NULL and mentions `ST_IsEmpty(NULL)`, but it does not cover the bare `WHERE` truth-value behavior or the overlapping TRUE/NULL partitions. MDEV-40143 and related reports require VIEW/CTE/join optimizer structures and are not this table-free predicate path.
-
- Discovery
Found by DBMS-StateFuzz using typed TLP checks. Two independent generated queries reduced to the two table-free expressions above.
Credit: Zheng Wang, Yanjie Zhao, and Yiyang Liu.