Skip to content

Commit dffd167

Browse files
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.
1 parent d555f38 commit dffd167

File tree

4 files changed

+67
-20
lines changed

4 files changed

+67
-20
lines changed

mysql-test/main/func_json.result

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4590,4 +4590,19 @@ JSON_SCHEMA_VALID(@invalid_schema, '{"number1":3, "obj2":{"key1":3}}')
45904590
NULL
45914591
Warnings:
45924592
Warning 4038 Syntax error in JSON text in argument 1 to function 'json_schema_valid' at position 45
4593+
#
4594+
# MDEV-30703: JSON_SCHEMA_VALID : Enum array must have at least one value
4595+
#
4596+
SET @schema = '{
4597+
"type":"array",
4598+
"enum": []
4599+
}';
4600+
SELECT JSON_SCHEMA_VALID(@schema, '2');
4601+
ERROR HY000: Invalid value for keyword enum
4602+
SET @schema = '{
4603+
"type":"number",
4604+
"enum": [2, 2]
4605+
}';
4606+
SELECT JSON_SCHEMA_VALID(@schema, '2');
4607+
ERROR HY000: Invalid value for keyword enum
45934608
# End of 11.1 test

mysql-test/main/func_json.test

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3357,6 +3357,7 @@ SET @schema_reference= '{"$defs": "http://example.com/custom-email-validator.jso
33573357
SELECT JSON_SCHEMA_VALID(@schema_reference, '{}');
33583358

33593359

3360+
33603361
--echo #
33613362
--echo # MDEV-30795: JSON_SCHEMA_VALID bugs mentioned in comment
33623363
--echo #
@@ -3474,4 +3475,23 @@ SET @invalid_schema= '{"type":"object"
34743475
}';
34753476
SELECT JSON_SCHEMA_VALID(@invalid_schema, '{"number1":3, "obj2":{"key1":3}}');
34763477

3478+
--echo #
3479+
--echo # MDEV-30703: JSON_SCHEMA_VALID : Enum array must have at least one value
3480+
--echo #
3481+
3482+
SET @schema = '{
3483+
"type":"array",
3484+
"enum": []
3485+
}';
3486+
--error ER_JSON_INVALID_VALUE_FOR_KEYWORD
3487+
SELECT JSON_SCHEMA_VALID(@schema, '2');
3488+
3489+
SET @schema = '{
3490+
"type":"number",
3491+
"enum": [2, 2]
3492+
}';
3493+
--error ER_JSON_INVALID_VALUE_FOR_KEYWORD
3494+
SELECT JSON_SCHEMA_VALID(@schema, '2');
3495+
3496+
34773497
--echo # End of 11.1 test

sql/json_schema.cc

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -520,12 +520,10 @@ bool Json_schema_enum::validate(const json_engine_t *je,
520520

521521
if (temp_je.value_type > JSON_VALUE_NUMBER)
522522
{
523-
if (temp_je.value_type == JSON_VALUE_TRUE)
524-
return !(enum_scalar & HAS_TRUE_VAL);
525-
if (temp_je.value_type == JSON_VALUE_FALSE)
526-
return !(enum_scalar & HAS_FALSE_VAL);
527-
if (temp_je.value_type == JSON_VALUE_NULL)
528-
return !(enum_scalar & HAS_NULL_VAL);
523+
if (!(enum_scalar & (1 << temp_je.value_type)))
524+
return true;
525+
else
526+
return false;
529527
}
530528
json_get_normalized_string(&temp_je, &a_res, &err);
531529
if (err)
@@ -546,6 +544,7 @@ bool Json_schema_enum::handle_keyword(THD *thd, json_engine_t *je,
546544
List<Json_schema_keyword>
547545
*all_keywords)
548546
{
547+
int count= 0;
549548
if (my_hash_init(PSI_INSTRUMENT_ME,
550549
&this->enum_values,
551550
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,
559558
{
560559
if (json_read_value(je))
561560
return true;
561+
count++;
562562
if (je->value_type > JSON_VALUE_NUMBER)
563563
{
564-
if (je->value_type == JSON_VALUE_TRUE)
565-
enum_scalar|= HAS_TRUE_VAL;
566-
else if (je->value_type == JSON_VALUE_FALSE)
567-
enum_scalar|= HAS_FALSE_VAL;
568-
else if (je->value_type == JSON_VALUE_NULL)
569-
enum_scalar|= HAS_NULL_VAL;
564+
if (!(enum_scalar & (1 << je->value_type)))
565+
enum_scalar|= 1 << je->value_type;
566+
else
567+
{
568+
my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "enum");
569+
return true;
570+
}
570571
}
571572
else
572573
{
@@ -586,12 +587,26 @@ bool Json_schema_enum::handle_keyword(THD *thd, json_engine_t *je,
586587
{
587588
norm_str[a_res.length()]= '\0';
588589
strncpy(norm_str, (const char*)a_res.ptr(), a_res.length());
589-
if (my_hash_insert(&this->enum_values, (uchar*)norm_str))
590-
return true;
590+
if (!my_hash_search(&this->enum_values, (uchar*)norm_str,
591+
strlen(norm_str)))
592+
{
593+
if (my_hash_insert(&this->enum_values, (uchar*)norm_str))
594+
return true;
595+
}
596+
else
597+
{
598+
my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "enum");
599+
return true;
600+
}
591601
}
592602
}
593603
}
594-
return je->s.error ? true : false;
604+
if (!count)
605+
{
606+
my_error(ER_JSON_INVALID_VALUE_FOR_KEYWORD, MYF(0), "enum");
607+
return true;
608+
}
609+
return false;
595610
}
596611
else
597612
{

sql/json_schema.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,7 @@ class Json_schema_const : public Json_schema_keyword
176176
}
177177
};
178178

179-
enum enum_scalar_values {
180-
HAS_NO_VAL= 0, HAS_TRUE_VAL= 2,
181-
HAS_FALSE_VAL= 4, HAS_NULL_VAL= 8
182-
};
179+
183180
class Json_schema_enum : public Json_schema_keyword
184181
{
185182
private:
@@ -196,7 +193,7 @@ class Json_schema_enum : public Json_schema_keyword
196193
List<Json_schema_keyword> *all_keywords) override;
197194
Json_schema_enum()
198195
{
199-
enum_scalar= HAS_NO_VAL;
196+
enum_scalar= 0;
200197
}
201198
~Json_schema_enum()
202199
{

0 commit comments

Comments
 (0)