Details
-
Bug
-
Status: Confirmed (View Workflow)
-
Major
-
Resolution: Unresolved
-
10.11, 11.4, 11.8, 12.3, 13.1
Description
- MariaDB `SUBSTR` signed overflow for `INT32_MIN` position
Status: reproduced on MariaDB current main SHA `9d7ab2c0092df4bc73b64b915464aecf7e5fe6c4` (13.2.0 development tree).
-
- Reproduction environment
- Linux x86_64
- Clang 14
- Debug build with AddressSanitizer and UndefinedBehaviorSanitizer
- `WITH_UNIT_TESTS=OFF`, `WITH_WSREP=OFF`
-
- Minimal reproducer
```sql
SELECT SUBSTR('a', -2147483648);
```
`SUBSTRING` is equivalent and reaches the same path. No table, data, transaction state, special SQL mode, or elevated privilege is required.
-
- Observed result
UBSan reports:
```text
sql/item_strfunc.cc:2005:27: runtime error:
negation of -2147483648 cannot be represented in type 'int32' (aka 'int')
```
With UBSan recovery enabled, the query returns the empty result and the server remains usable. With `UBSAN_OPTIONS=halt_on_error=1`, the client loses the connection and the server exits with status 1. A non-sanitized Debug build returns the empty result and remains alive.
-
- Expected result
The out-of-range negative position should produce the empty result without invoking undefined behavior.
-
- Root cause
`Item_func_substr::fix_length_and_dec()` narrows the constant position to `int32`. When the value is negative, it evaluates `(uint)(-start)`. Negating `INT32_MIN` is not representable in signed `int32`, so the expression has undefined behavior before the unsigned cast.
The same unguarded negation remains in current main at the tested SHA.
-
- Impact
This is SQL-reachable signed-overflow UB and a correctness/hardening defect. No ordinary-release crash, memory corruption, privilege-boundary impact, or security exploitability has been demonstrated.
-
- Duplicate audit
No exact public duplicate was found. MDEV-37012 reaches the same fixup method through an out-of-range user-variable-to-`long long` conversion. MDEV-28387/MDEV-31221 concern `LLONG_MIN` parsing in `my_strtoll10`. Neither covers the `int32 -start` operation here.
-
- Discovery
Found by DBMS-StateFuzz and reduced from a stateful typed query to the scalar statement above.
Credit: Zheng Wang, Yanjie Zhao, and Yiyang Liu.
Attachments
Issue Links
- relates to
-
MDEV-30931 UBSAN: negation of -X cannot be represented in type 'long long int'; cast to an unsigned type to negate this value to itself in get_interval_value on SELECT
-
- Closed
-
-
MDEV-31221 UBSAN runtime error: negation of -9223372036854775808 cannot be represented in type 'long long int' in my_strtoll10_utf32
-
- Closed
-
-
MDEV-37012 UBSAN: X is outside the range of representable values of type 'long long' in sql/item_func.cc | user_var_entry::val_int
-
- Open
-