MDEV-35715: UBSAN: runtime error: 1e+19 is outside the range of representable values of type 'long long' in Field_bit::store on INSERT#5081
Conversation
ae4413f to
c20fff0
Compare
…(double) Casting a double like 1e19 directly to longlong is UB when the value is outside [-2^63, 2^63-1]. Clamp before the cast, same way other numeric store() methods already do.
c20fff0 to
a6268f5
Compare
There was a problem hiding this comment.
Code Review
This pull request performs extensive security hardening and bug fixes, notably replacing sprintf with snprintf across the codebase and the CONNECT storage engine to prevent buffer overflows. Key enhancements include strict numeric validation for master.info, LENENC support for long passwords in COM_CHANGE_USER, and improved handling of negative zero in floating-point storage. It also resolves various crash scenarios in GIS and JSON functions, memory leaks, and replication inconsistencies. Review feedback identified a critical type mismatch in sql/wsrep_applier.cc that could lead to undefined behavior during debug logging, and a potential stack buffer overflow in sql/mysqld.cc when handling Unix socket paths.
I am having trouble creating individual review comments. Click here to see my feedback.
sql/wsrep_applier.cc (103-104)
The change from a byte buffer to a std::vectorstd::string (implied by push_back(err_str)) seems to conflict with the subsequent WSREP_DEBUG call (line 106-108 in context) which uses dst.data() with a %s format specifier. If dst is now a vector of strings, dst.data() returns a std::string*, which will cause Undefined Behavior or a crash when passed to %s. Please ensure the debug print is updated to access the string content correctly, e.g., dst.empty() ? "" : dst[0].c_str().
sql/mysqld.cc (2707)
The use of strmov to copy path into addr.sun_path is potentially dangerous if path exceeds the fixed size of the sun_path array (typically 108 bytes). While there is a length check later in network_init, this utility function should ideally be self-protecting. Consider using strmake or adding an explicit length check before the copy to prevent a stack buffer overflow.
if (strlen(path) >= sizeof(addr.sun_path))
{
sql_print_error("Unix socket path is too long: %s", path);
unireg_abort(1);
}
strmov(addr.sun_path, path);|
Lets get a working local test environment so mtr matches results before submitting. |
When a floating-point value (e.g.,
1e+19or-1e+30) that is outside the representable range of a 64-bit integer type is cast directly via(longlong) nror(ulonglong) nr, C++ produces Undefined Behavior (UB). UndefinedBehaviorSanitizer (UBSAN) flags this during runtime as afloat-cast-overflow.This directly affected:
Field_bit::store(double)Field_enum::store(double)Field_set::store(double)(inlined toField_enum::store)Solution
Replaced the direct C-style
(longlong)casts with MariaDB's standardConverter_double_to_longlonghelper class.Instead of an unsafe cast, the converter safely rounds and clamps out-of-bounds
doublevalues to their respective integer minimums/maximums (ULLONG_MAX,LLONG_MAX, orLLONG_MINdepending on the explicitunsigned_flag) before proceeding with the normal truncation logic. This replicates the exact behavior existing in other numericstore(double)methods, maintaining the same warning outputs (ER_WARN_DATA_OUT_OF_RANGE/WARN_DATA_TRUNCATED) while completely eliminating the Undefined Behavior.Testing
main.type_bit_mdev35715validatingBIT,ENUM, andSEToverflow boundaries.