mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
MDEV-41556 Unexpected error: Incorrect ASSOCIATIVE ARRAY KEY value
my_strntoull10rnd_8bit() did not set *error when a signed negative value
was exactly LONGLONG_MIN (-9223372036854775808): that path returned the
value and left *error untouched. Callers passing an uninitialized
"int error", such as the associative array key conversion in
Type_handler_assoc_array, then read a garbage value and raised a
spurious ER_WRONG_VALUE. Field_num::get_int() and Field_year::store()
also pass an uninitialized error, and my_strntoull10rnd_mb2_or_mb4()
calls this function too.
Fix: initialize *error to 0 at function entry, like the sibling
my_strntoll_8bit() and my_strntoll_mb2_or_mb4() do, so that no exit
path can leave it unset.
The bug was introduced by commit 031f11717d (Fix all warnings given by
UBSAN, 2021-04-18), which started skipping the *error assignment when
the value equals LONGLONG_MIN.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -3122,4 +3122,18 @@ $$
|
||||
DROP PROCEDURE p1;
|
||||
DROP PROCEDURE p2;
|
||||
DROP PROCEDURE p_inout;
|
||||
#
|
||||
# MDEV-41556 Unexpected error: Incorrect ASSOCIATIVE ARRAY KEY value
|
||||
#
|
||||
SET sql_mode=ORACLE;
|
||||
DECLARE
|
||||
TYPE t IS TABLE OF INT INDEX BY BIGINT;
|
||||
a t;
|
||||
BEGIN
|
||||
a(-9223372036854775807-1):= 10; -- key is LONGLONG_MIN
|
||||
SELECT a(-9223372036854775807-1) AS c1;
|
||||
END;
|
||||
$$
|
||||
c1
|
||||
10
|
||||
# End of 12.3 tests
|
||||
|
||||
@@ -3561,4 +3561,22 @@ DROP PROCEDURE p1;
|
||||
DROP PROCEDURE p2;
|
||||
DROP PROCEDURE p_inout;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-41556 Unexpected error: Incorrect ASSOCIATIVE ARRAY KEY value
|
||||
--echo #
|
||||
|
||||
SET sql_mode=ORACLE;
|
||||
DELIMITER $$;
|
||||
DECLARE
|
||||
TYPE t IS TABLE OF INT INDEX BY BIGINT;
|
||||
a t;
|
||||
BEGIN
|
||||
a(-9223372036854775807-1):= 10; -- key is LONGLONG_MIN
|
||||
SELECT a(-9223372036854775807-1) AS c1;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
|
||||
--echo # End of 12.3 tests
|
||||
|
||||
@@ -1693,6 +1693,8 @@ my_strntoull10rnd_8bit(CHARSET_INFO *cs __attribute__((unused)),
|
||||
uchar ch;
|
||||
int shift= 0, digits= 0, negative, addon;
|
||||
|
||||
*error= 0;
|
||||
|
||||
/* Skip leading spaces and tabs */
|
||||
for ( ; str < end && my_isspace(&my_charset_latin1, *str) ; )
|
||||
str++;
|
||||
|
||||
@@ -1735,13 +1735,58 @@ static int test_mb_wc_filename_truncated()
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
MDEV-41556: my_strntoull10rnd() must always set *error, also when a signed
|
||||
value equals LONGLONG_MIN exactly. Pre-set "error" to a non-zero value, so
|
||||
the check does not depend on the caller's uninitialized stack contents.
|
||||
*/
|
||||
static int test_strntoull10rnd_error_set()
|
||||
{
|
||||
static const struct
|
||||
{
|
||||
const char *str;
|
||||
int unsigned_flag;
|
||||
int expected_error;
|
||||
} tests[]=
|
||||
{
|
||||
{"-9223372036854775808", 0, 0},
|
||||
{"-9223372036854775809", 0, ERANGE},
|
||||
{"9223372036854775807", 0, 0},
|
||||
{"9223372036854775808", 0, ERANGE},
|
||||
{"18446744073709551615", 1, 0},
|
||||
};
|
||||
CHARSET_INFO *charsets[]= {&my_charset_latin1, &my_charset_bin};
|
||||
int failed= 0;
|
||||
size_t i, j;
|
||||
|
||||
for (j= 0; j < array_elements(charsets); j++)
|
||||
{
|
||||
for (i= 0; i < array_elements(tests); i++)
|
||||
{
|
||||
char *endptr;
|
||||
int error= 12345;
|
||||
my_ci_strntoull10rnd(charsets[j], tests[i].str, strlen(tests[i].str),
|
||||
tests[i].unsigned_flag, &endptr, &error);
|
||||
if (error != tests[i].expected_error)
|
||||
{
|
||||
diag("%s: %s unsigned_flag=%d: error=%d, expected %d",
|
||||
charsets[j]->coll_name.str, tests[i].str,
|
||||
tests[i].unsigned_flag, error, tests[i].expected_error);
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return failed;
|
||||
}
|
||||
|
||||
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
size_t i, failed= 0;
|
||||
|
||||
MY_INIT(av[0]);
|
||||
|
||||
plan(5);
|
||||
plan(6);
|
||||
diag("Testing my_like_range_xxx() functions");
|
||||
|
||||
for (i= 0; i < array_elements(charset_list); i++)
|
||||
@@ -1771,6 +1816,10 @@ int main(int ac, char **av)
|
||||
ok(test_mb_wc_filename_truncated() == 0,
|
||||
"filename decoder does not read past the end pointer");
|
||||
|
||||
diag("Testing my_ci_strntoull10rnd() error output");
|
||||
ok(test_strntoull10rnd_error_set() == 0,
|
||||
"my_ci_strntoull10rnd() always sets error");
|
||||
|
||||
my_end(0);
|
||||
|
||||
return exit_status();
|
||||
|
||||
Reference in New Issue
Block a user