sql(mysql): decode DATETIME/TIMESTAMP as UTC #29216
Open
Claude / Claude Code Review
completed
Apr 12, 2026 in 22m 15s
Code review found 1 important issue
Found 3 candidates, confirmed 2. See review comments for details.
Details
| Severity | Count |
|---|---|
| 🔴 Important | 1 |
| 🟡 Nit | 0 |
| 🟣 Pre-existing | 1 |
| Severity | File:Line | Issue |
|---|---|---|
| 🔴 Important | src/sql/mysql/protocol/DecodeBinaryValue.zig:134-135 |
Partial zero-dates in binary protocol normalize instead of NaN |
| 🟣 Pre-existing | src/sql/mysql/MySQLTypes.zig:663-673 |
gregorianDate() panics on pre-1970 dates (write path) |
Annotations
Check failure on line 135 in src/sql/mysql/protocol/DecodeBinaryValue.zig
claude / Claude Code Review
Partial zero-dates in binary protocol normalize instead of NaN
The binary protocol path for partial zero-dates like '2024-00-15' (month=0) or '2024-01-00' (day=0) silently normalizes them to wrong timestamps instead of NaN. MySQL sends these as non-zero-length 4/7/11-byte payloads, bypassing the zero-length NaN guard added by this PR; fromBinary() reads month/day with no range validation, so toJSTimestamp() calls gregorianDateTimeToMSUTC(year, 0, day) which triggers setMonth(-1) in WTF::GregorianDateTime and normalizes to December of year-1. Meanwhile fromT
Check notice on line 673 in src/sql/mysql/MySQLTypes.zig
claude / Claude Code Review
gregorianDate() panics on pre-1970 dates (write path)
Pre-existing bug: `gregorianDate()` only iterates forward from 1970, so any negative `days` value (representing a pre-1970 date) skips both while-loops entirely and attempts `@intCast(d + 1)` to `u8` where `d` is still the original large negative number — a panic in Zig Debug/ReleaseSafe mode and silent garbage in ReleaseFast. Any INSERT of a pre-1970 JS Date (e.g. `new Date('1900-01-01')`) via Bun MySQL will trigger this through the `fromJS() → fromUnixTimestamp() → gregorianDate()` call chain.
Loading