Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions mysql-test/main/type_bit_mdev35715.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#
# MDEV-35715 UBSAN float-cast-overflow in Field_bit::store and Field_enum::store
#
# Field_bit: value >= 2^63 (outside long long range)
CREATE TABLE t1 (c BIT);
INSERT INTO t1 VALUES (1e+19);
Warnings:
Warning 1264 Out of range value for column 'c' at row 1
SELECT HEX(c) FROM t1;
HEX(c)
1
DROP TABLE t1;
# Field_bit: very large value
CREATE TABLE t1 (c BIT);
INSERT INTO t1 VALUES (1e+100);
Warnings:
Warning 1264 Out of range value for column 'c' at row 1
SELECT HEX(c) FROM t1;
HEX(c)
1
DROP TABLE t1;
# Field_bit: negative out-of-range (should clamp/warn)
CREATE TABLE t1 (c BIT);
INSERT INTO t1 VALUES (-1e+30);
Warnings:
Warning 1264 Out of range value for column 'c' at row 1
SELECT HEX(c) FROM t1;
HEX(c)
0
DROP TABLE t1;
# Field_enum: positive out-of-range
CREATE TABLE t1 (c ENUM('a','b','c'));
INSERT INTO t1 VALUES (-1e+30);
Warnings:
Warning 1265 Data truncated for column 'c' at row 1
SELECT c FROM t1;
c

DROP TABLE t1;
# Field_set: out-of-range via SET column
CREATE TABLE t1 (c SET('x','y'));
INSERT INTO t1 VALUES (-1e+30);
Warnings:
Warning 1265 Data truncated for column 'c' at row 1
SELECT c FROM t1;
c

DROP TABLE t1;
# Additional testcase from bug report: DOUBLE UNSIGNED ZEROFILL + BIT
CREATE TABLE t2 (c DOUBLE UNSIGNED ZEROFILL DEFAULT NULL, c2 BIT(1) DEFAULT NULL);
INSERT INTO t2 VALUES (+3E+38, +3.4E+38);
Warnings:
Warning 1264 Out of range value for column 'c' at row 1
Warning 1264 Out of range value for column 'c2' at row 1
SELECT HEX(c2) FROM t2;
HEX(c2)
1
DROP TABLE t2;
39 changes: 39 additions & 0 deletions mysql-test/main/type_bit_mdev35715.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
--echo #
--echo # MDEV-35715 UBSAN float-cast-overflow in Field_bit::store and Field_enum::store
--echo #

--echo # Field_bit: value >= 2^63 (outside long long range)
CREATE TABLE t1 (c BIT);
INSERT INTO t1 VALUES (1e+19);
SELECT HEX(c) FROM t1;
DROP TABLE t1;

--echo # Field_bit: very large value
CREATE TABLE t1 (c BIT);
INSERT INTO t1 VALUES (1e+100);
SELECT HEX(c) FROM t1;
DROP TABLE t1;

--echo # Field_bit: negative out-of-range (should clamp/warn)
CREATE TABLE t1 (c BIT);
INSERT INTO t1 VALUES (-1e+30);
SELECT HEX(c) FROM t1;
DROP TABLE t1;

--echo # Field_enum: positive out-of-range
CREATE TABLE t1 (c ENUM('a','b','c'));
INSERT INTO t1 VALUES (-1e+30);
SELECT c FROM t1;
DROP TABLE t1;

--echo # Field_set: out-of-range via SET column
CREATE TABLE t1 (c SET('x','y'));
INSERT INTO t1 VALUES (-1e+30);
SELECT c FROM t1;
DROP TABLE t1;

--echo # Additional testcase from bug report: DOUBLE UNSIGNED ZEROFILL + BIT
CREATE TABLE t2 (c DOUBLE UNSIGNED ZEROFILL DEFAULT NULL, c2 BIT(1) DEFAULT NULL);
INSERT INTO t2 VALUES (+3E+38, +3.4E+38);
SELECT HEX(c2) FROM t2;
DROP TABLE t2;
4 changes: 2 additions & 2 deletions sql/field.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9621,7 +9621,7 @@ int Field_enum::store(const char *from,size_t length,CHARSET_INFO *cs)

int Field_enum::store(double nr)
{
return Field_enum::store((longlong) nr, FALSE);
return Field_enum::store(Converter_double_to_longlong(nr, false).result(), FALSE);
}


Expand Down Expand Up @@ -10249,7 +10249,7 @@ int Field_bit::store(const char *from, size_t length, CHARSET_INFO *cs)

int Field_bit::store(double nr)
{
return Field_bit::store((longlong) nr, FALSE);
return Field_bit::store(Converter_double_to_longlong(nr, true).result(), FALSE);
}


Expand Down
2 changes: 1 addition & 1 deletion sql/field.h
Original file line number Diff line number Diff line change
Expand Up @@ -5059,7 +5059,7 @@ class Field_set final :public Field_enum {
int store_field(Field *from) override { return from->save_in_field(this); }
int store(const char *to,size_t length,CHARSET_INFO *charset) override;
int store(double nr) override
{ return Field_set::store((longlong) nr, FALSE); }
{ return Field_set::store(Converter_double_to_longlong(nr, false).result(), FALSE); }
int store(longlong nr, bool unsigned_val) override;

bool zero_pack() const override { return true; }
Expand Down
Loading