diff --git a/mysql-test/main/mdev40385.result b/mysql-test/main/mdev40385.result new file mode 100644 index 0000000000000..78f7b3b2239ea --- /dev/null +++ b/mysql-test/main/mdev40385.result @@ -0,0 +1,35 @@ +# +# MDEV-40385 use-of-uninitialized-value in Binary_string::c_ptr() +# +# KDF() with a 4th (kdf_name) argument that is an integer literal made +# Item_func_kdf::val_str() evaluate args[3]->val_str() into the shared +# result buffer and then call c_ptr() on it. The integer-to-string +# conversion does not NUL-terminate, and the buffer is not "alloced", +# so c_ptr() (sql/sql_string.h) read an uninitialized byte. +# Under MSAN this was flagged as use-of-uninitialized-value. +# +# The 4th argument that is not a valid kdf name must be rejected with a +# warning and NULL, without reading uninitialized memory. +# +SELECT KDF('','',1000,256); +KDF('','',1000,256) +NULL +Warnings: +Warning 3047 Invalid argument error: '256' in function kdf. +SELECT KDF('secret','salt',1000,999); +KDF('secret','salt',1000,999) +NULL +Warnings: +Warning 3047 Invalid argument error: '999' in function kdf. +# +# Valid kdf_name arguments must still work. +# +SELECT KDF('secret','salt',1000,'pbkdf2_hmac') IS NOT NULL; +KDF('secret','salt',1000,'pbkdf2_hmac') IS NOT NULL +1 +SELECT KDF('secret','salt') IS NOT NULL; +KDF('secret','salt') IS NOT NULL +1 +# +# End of 11.4 tests +# diff --git a/mysql-test/main/mdev40385.test b/mysql-test/main/mdev40385.test new file mode 100644 index 0000000000000..97830d54a340d --- /dev/null +++ b/mysql-test/main/mdev40385.test @@ -0,0 +1,28 @@ +# MSAN only: This test verifies the fix behaviorally (warning + NULL). The uninitialized +# read itself only triggers a failure when run on an MSAN build; on a normal +# build the test passes on both the unfixed and fixed server. +--echo # +--echo # MDEV-40385 use-of-uninitialized-value in Binary_string::c_ptr() +--echo # +--echo # KDF() with a 4th (kdf_name) argument that is an integer literal made +--echo # Item_func_kdf::val_str() evaluate args[3]->val_str() into the shared +--echo # result buffer and then call c_ptr() on it. The integer-to-string +--echo # conversion does not NUL-terminate, and the buffer is not "alloced", +--echo # so c_ptr() (sql/sql_string.h) read an uninitialized byte. +--echo # Under MSAN this was flagged as use-of-uninitialized-value. +--echo # +--echo # The 4th argument that is not a valid kdf name must be rejected with a +--echo # warning and NULL, without reading uninitialized memory. +--echo # +SELECT KDF('','',1000,256); +SELECT KDF('secret','salt',1000,999); + +--echo # +--echo # Valid kdf_name arguments must still work. +--echo # +SELECT KDF('secret','salt',1000,'pbkdf2_hmac') IS NOT NULL; +SELECT KDF('secret','salt') IS NOT NULL; + +--echo # +--echo # End of 11.4 tests +--echo # diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index c98dcdfeb03f1..27d4caabe5c5c 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -489,9 +489,9 @@ String *Item_func_kdf::val_str(String *buf) { if (String *s= args[3]->val_str(buf)) { - if (strcasecmp(s->c_ptr(), "hkdf") == 0) + if (strcasecmp(s->c_ptr_safe(), "hkdf") == 0) use_hkdf= true; - else if (strcasecmp(s->c_ptr(), "pbkdf2_hmac") != 0) + else if (strcasecmp(s->c_ptr_safe(), "pbkdf2_hmac") != 0) { invalid_argument_error(func_name(), ErrConvStringQ(s).ptr()); goto ret_null;