MDEV-30703: JSON_SCHEMA_VALID : Enum array must have at least one value

Analysis: Current implementation does not check the number of elements in
the enum array and whether they are unique or not.
Fix: Add a counter that counts number of elements and before inserting the
element in the enum hash check whether it exists.
This commit is contained in:
Rucha Deodhar 2023-03-02 19:09:45 +05:30
parent d555f38af8
commit dffd1679ba
4 changed files with 67 additions and 20 deletions

View file

@ -4590,4 +4590,19 @@ JSON_SCHEMA_VALID(@invalid_schema, '{"number1":3, "obj2":{"key1":3}}')
NULL
Warnings:
Warning 4038 Syntax error in JSON text in argument 1 to function 'json_schema_valid' at position 45
#
# MDEV-30703: JSON_SCHEMA_VALID : Enum array must have at least one value
#
SET @schema = '{
"type":"array",
"enum": []
}';
SELECT JSON_SCHEMA_VALID(@schema, '2');
ERROR HY000: Invalid value for keyword enum
SET @schema = '{
"type":"number",
"enum": [2, 2]
}';
SELECT JSON_SCHEMA_VALID(@schema, '2');
ERROR HY000: Invalid value for keyword enum
# End of 11.1 test

View file

@ -3357,6 +3357,7 @@ SET @schema_reference= '{"$defs": "http://example.com/custom-email-validator.jso
SELECT JSON_SCHEMA_VALID(@schema_reference, '{}');
--echo #
--echo # MDEV-30795: JSON_SCHEMA_VALID bugs mentioned in comment
--echo #
@ -3474,4 +3475,23 @@ SET @invalid_schema= '{"type":"object"
}';
SELECT JSON_SCHEMA_VALID(@invalid_schema, '{"number1":3, "obj2":{"key1":3}}');
--echo #
--echo # MDEV-30703: JSON_SCHEMA_VALID : Enum array must have at least one value
--echo #
SET @schema = '{
"type":"array",
"enum": []
}';
--error ER_JSON_INVALID_VALUE_FOR_KEYWORD
SELECT JSON_SCHEMA_VALID(@schema, '2');
SET @schema = '{
"type":"number",
"enum": [2, 2]
}';
--error ER_JSON_INVALID_VALUE_FOR_KEYWORD
SELECT JSON_SCHEMA_VALID(@schema, '2');
--echo # End of 11.1 test

View file

@ -520,12 +520,10 @@ bool Json_schema_enum::validate(const json_engine_t *je,
if (temp_je.value_type > JSON_VALUE_NUMBER)
{
if (temp_je.value_type == JSON_VALUE_TRUE)
return !(enum_scalar & HAS_TRUE_VAL);
if (temp_je.value_type == JSON_VALUE_FALSE)
return !(enum_scalar & HAS_FALSE_VAL);
if (temp_je.value_type == JSON_VALUE_NULL)
return !(enum_scalar & HAS_NULL_VAL);
if (!(enum_scalar & (1 << temp_je.value_type)))
return true;
else
return false;
}
json_get_normalized_string(&temp_je, &a_res, &err);
if (err)
@ -546,6 +544,7 @@ bool Json_schema_enum::handle_keyword(THD *thd, json_engine_t *je,
List<Json_schema_keyword>
*all_keywords)
{
int count= 0;
if (my_hash_init(PSI_INSTRUMENT_ME,
&this->enum_values,
je->s.cs, 1024, 0, 0, (my_hash_get_key) get_key_name,
@ -559,14 +558,16 @@ bool Json_schema_enum::handle_keyword(THD *thd, json_engine_t *je,
{
if (json_read_value(je))
return true;
count++;
if (je->value_type > JSON_VALUE_NUMBER)
{
if (je->value_type == JSON_VALUE_TRUE)
enum_scalar|= HAS_TRUE_VAL;
else if (je->value_type == JSON_VALUE_FALSE)
enum_scalar|= HAS_FALSE_VAL;
else if (je->value_type == JSON_VALUE_NULL)
enum_scalar|= HAS_NULL_VAL;
if (!(enum_scalar & (1 << je->value_type)))
enum_scalar|= 1 << je->value_type;
else
{
my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "enum");
return true;
}
}
else
{
@ -586,12 +587,26 @@ bool Json_schema_enum::handle_keyword(THD *thd, json_engine_t *je,
{
norm_str[a_res.length()]= '\0';
strncpy(norm_str, (const char*)a_res.ptr(), a_res.length());
if (my_hash_insert(&this->enum_values, (uchar*)norm_str))
return true;
if (!my_hash_search(&this->enum_values, (uchar*)norm_str,
strlen(norm_str)))
{
if (my_hash_insert(&this->enum_values, (uchar*)norm_str))
return true;
}
else
{
my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "enum");
return true;
}
}
}
}
return je->s.error ? true : false;
if (!count)
{
my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "enum");
return true;
}
return false;
}
else
{

View file

@ -176,10 +176,7 @@ class Json_schema_const : public Json_schema_keyword
}
};
enum enum_scalar_values {
HAS_NO_VAL= 0, HAS_TRUE_VAL= 2,
HAS_FALSE_VAL= 4, HAS_NULL_VAL= 8
};
class Json_schema_enum : public Json_schema_keyword
{
private:
@ -196,7 +193,7 @@ class Json_schema_enum : public Json_schema_keyword
List<Json_schema_keyword> *all_keywords) override;
Json_schema_enum()
{
enum_scalar= HAS_NO_VAL;
enum_scalar= 0;
}
~Json_schema_enum()
{