1
0
mirror of https://github.com/MariaDB/server.git synced 2026-10-23 18:49:29 +03:00

MDEV-39049: Memory corruption & crash in check_key_in_list upon using

JSON_KEYS after modifying character set name/collation

Analysis:
Buffer overflow crashes and empty key duplication in check_key_in_list.

Fix:
Checking result buffer validity prevents segmentation faults on empty
strings and malformed inputs while preserving correct key matching behavior.
This commit is contained in:
Rucha Deodhar
2026-09-23 16:59:00 -04:00
parent 0d10b89fbf
commit c7f549e26b
3 changed files with 27 additions and 25 deletions

View File

@@ -3091,11 +3091,13 @@ DROP TABLE t;
# using JSON_KEYS after modifying character set name/collation
#
SET SESSION character_set_database=utf32;
SET CHARSET DEFAULT;
SELECT JSON_KEYS('{"":');
JSON_KEYS('{"":')
SELECT JSON_KEYS ('{"S":-1.0,"D": {"o":,"a": }}');
JSON_KEYS ('{"S":-1.0,"D": {"o":,"a": }}')
NULL
Warnings:
Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_keys'
Warning 4038 Syntax error in JSON text in argument 1 to function 'json_keys' at position 25
SELECT JSON_KEYS('{"":1, "k2":2, "":3, "k2":4 }');
JSON_KEYS('{"":1, "k2":2, "":3, "k2":4 }')
["", "k2"]
SET SESSION character_set_database= default;
# End of 10.11 Test

View File

@@ -2189,9 +2189,8 @@ DROP TABLE t;
--echo # MDEV-39049: Memory corruption & crash in check_key_in_list upon
--echo # using JSON_KEYS after modifying character set name/collation
--echo #
SET SESSION character_set_database=utf32;
SET CHARSET DEFAULT;
SELECT JSON_KEYS('{"":');
SELECT JSON_KEYS ('{"S":-1.0,"D": {"o":,"a": }}');
SELECT JSON_KEYS('{"":1, "k2":2, "":3, "k2":4 }');
SET SESSION character_set_database= default;
--echo # End of 10.11 Test

View File

@@ -3882,31 +3882,32 @@ static int check_key_in_list(String *res,
{
const uchar *c, *end;
if (!key_len)
if (!res || res->length() < 2)
return 0;
c= (const uchar *) res->ptr() + 2; /* beginning '["' */
end= (const uchar *) res->end() - 1; /* ending '"' */
c= (const uchar *) res->ptr() + 1;
end= (const uchar *) res->end();
while (c < end)
{
int n_char;
for (n_char=0; c[n_char] != '"' && n_char < key_len; n_char++)
while (c < end && *c != '"')
c++;
if (c >= end)
break;
c++;
const uchar *key_start= c;
int n_char= 0;
while (c + n_char < end && c[n_char] != '"')
{
if (c[n_char] != key[n_char])
break;
n_char++;
}
if (c[n_char] == '"')
{
if (n_char == key_len)
return 1;
}
else
{
while (c[n_char] != '"')
n_char++;
}
c+= n_char + 4; /* skip ', "' */
if (n_char == key_len &&
(key_len == 0 || memcmp(key_start, key, key_len) == 0))
return 1;
c+= n_char + 1;
}
return 0;
}