From 9ac8172ac386c6506be3624121d672ec042c4ce2 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 20 Sep 2024 11:47:56 +0400 Subject: [PATCH] MDEV-31221 UBSAN runtime error: negation of -9223372036854775808 cannot be represented in type 'long long int' in my_strtoll10_utf32 The code in my_strtoll10_mb2 and my_strtoll10_utf32 could hit undefinite behavior by negation of LONGLONG_MIN. Fixing to avoid this. Also, fixing my_strtoll10() in the same style. The previous reduction produced a redundant warning on CAST(_latin1'-9223372036854775808' AS SIGNED) --- mysql-test/main/ctype_latin1.result | 6 ++++++ mysql-test/main/ctype_latin1.test | 7 +++++++ mysql-test/main/ctype_ucs.result | 6 ++++++ mysql-test/main/ctype_ucs.test | 5 +++++ mysql-test/main/ctype_utf32.result | 9 +++++++++ mysql-test/main/ctype_utf32.test | 11 +++++++++++ strings/ctype-ucs2.c | 4 ++++ strings/my_strtoll10.c | 4 +++- 8 files changed, 51 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/ctype_latin1.result b/mysql-test/main/ctype_latin1.result index 4548c076c1b..7ebfcea6e90 100644 --- a/mysql-test/main/ctype_latin1.result +++ b/mysql-test/main/ctype_latin1.result @@ -8975,5 +8975,11 @@ CAST(_latin1 0x61FF62 AS INT) Warnings: Warning 1292 Truncated incorrect INTEGER value: 'aÿb' # +# MDEV-31221 UBSAN runtime error: negation of -9223372036854775808 cannot be represented in type 'long long int' in my_strtoll10_utf32 +# +SELECT CAST(CONVERT('-9223372036854775808' USING latin1) AS SIGNED) AS c1; +c1 +-9223372036854775808 +# # End of 10.5 tests # diff --git a/mysql-test/main/ctype_latin1.test b/mysql-test/main/ctype_latin1.test index b00dc374a05..6b3d2dd744f 100644 --- a/mysql-test/main/ctype_latin1.test +++ b/mysql-test/main/ctype_latin1.test @@ -501,6 +501,13 @@ SELECT CAST(_latin1 0x617E62 AS INT); SELECT CAST(_latin1 0x61FF62 AS INT); +--echo # +--echo # MDEV-31221 UBSAN runtime error: negation of -9223372036854775808 cannot be represented in type 'long long int' in my_strtoll10_utf32 +--echo # + +SELECT CAST(CONVERT('-9223372036854775808' USING latin1) AS SIGNED) AS c1; + + --echo # --echo # End of 10.5 tests --echo # diff --git a/mysql-test/main/ctype_ucs.result b/mysql-test/main/ctype_ucs.result index a603d07b08a..de73f41c5a7 100644 --- a/mysql-test/main/ctype_ucs.result +++ b/mysql-test/main/ctype_ucs.result @@ -6549,5 +6549,11 @@ OCT(c) 1000000000000000000000 DROP TABLE t1; # +# MDEV-31221 UBSAN runtime error: negation of -9223372036854775808 cannot be represented in type 'long long int' in my_strtoll10_utf32 +# +SELECT CAST(CONVERT('-9223372036854775808' USING ucs2) AS SIGNED) AS c1; +c1 +-9223372036854775808 +# # End of 10.5 tests # diff --git a/mysql-test/main/ctype_ucs.test b/mysql-test/main/ctype_ucs.test index bf967ba7619..84ee8c5387c 100644 --- a/mysql-test/main/ctype_ucs.test +++ b/mysql-test/main/ctype_ucs.test @@ -1226,6 +1226,11 @@ INSERT INTO t1 VALUES ('-9223372036854775808.5'); SELECT OCT(c) FROM t1; DROP TABLE t1; +--echo # +--echo # MDEV-31221 UBSAN runtime error: negation of -9223372036854775808 cannot be represented in type 'long long int' in my_strtoll10_utf32 +--echo # + +SELECT CAST(CONVERT('-9223372036854775808' USING ucs2) AS SIGNED) AS c1; --echo # --echo # End of 10.5 tests diff --git a/mysql-test/main/ctype_utf32.result b/mysql-test/main/ctype_utf32.result index 46a8a5fed0f..546a7415603 100644 --- a/mysql-test/main/ctype_utf32.result +++ b/mysql-test/main/ctype_utf32.result @@ -3024,3 +3024,12 @@ HEX(DATE_FORMAT(TIME'11:22:33',@format)) # # End of 10.4 tests # +# +# MDEV-31221 UBSAN runtime error: negation of -9223372036854775808 cannot be represented in type 'long long int' in my_strtoll10_utf32 +# +SELECT CAST(CONVERT('-9223372036854775808' USING utf32) AS SIGNED) AS c1; +c1 +-9223372036854775808 +# +# End of 10.5 tests +# diff --git a/mysql-test/main/ctype_utf32.test b/mysql-test/main/ctype_utf32.test index f35a94e909c..4a1f27260c6 100644 --- a/mysql-test/main/ctype_utf32.test +++ b/mysql-test/main/ctype_utf32.test @@ -1162,3 +1162,14 @@ SELECT HEX(DATE_FORMAT(TIME'11:22:33',@format)); --echo # --enable_service_connection + + +--echo # +--echo # MDEV-31221 UBSAN runtime error: negation of -9223372036854775808 cannot be represented in type 'long long int' in my_strtoll10_utf32 +--echo # + +SELECT CAST(CONVERT('-9223372036854775808' USING utf32) AS SIGNED) AS c1; + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index fb33d8cc764..99f4f73ff78 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -1011,6 +1011,8 @@ end4: { if (li > MAX_NEGATIVE_NUMBER) goto overflow; + if (li == MAX_NEGATIVE_NUMBER) // Avoid undefinite behavior in negation + return LONGLONG_MIN; return -((longlong) li); } return (longlong) li; @@ -2574,6 +2576,8 @@ end4: { if (li > MAX_NEGATIVE_NUMBER) goto overflow; + if (li == MAX_NEGATIVE_NUMBER) // Avoid undefinite behavior in negation + return LONGLONG_MIN; return -((longlong) li); } return (longlong) li; diff --git a/strings/my_strtoll10.c b/strings/my_strtoll10.c index 74baef080eb..6c4ccea0b21 100644 --- a/strings/my_strtoll10.c +++ b/strings/my_strtoll10.c @@ -241,8 +241,10 @@ end4: *endptr= (char*) s; if (negative) { - if (li >= MAX_NEGATIVE_NUMBER) // Avoid undefined behavior + if (li > MAX_NEGATIVE_NUMBER) goto overflow; + if (li == MAX_NEGATIVE_NUMBER) // Avoid undefined behavior + return LONGLONG_MIN; return -((longlong) li); } return (longlong) li;