summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRucha Deodhar <rucha.deodhar@mariadb.com>2023-03-02 19:09:45 +0530
committerRucha Deodhar <rucha.deodhar@mariadb.com>2023-04-26 11:00:09 +0530
commitdffd1679ba97e5e8145575f0f11cb87553670c6f (patch)
treebb8ecb0ef138d0c2fdb90939e59bb0bb481a72b2
parentd555f38af819db8b051c4f754358041f146e83f4 (diff)
downloadmariadb-git-dffd1679ba97e5e8145575f0f11cb87553670c6f.tar.gz
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.
-rw-r--r--mysql-test/main/func_json.result15
-rw-r--r--mysql-test/main/func_json.test20
-rw-r--r--sql/json_schema.cc45
-rw-r--r--sql/json_schema.h7
4 files changed, 67 insertions, 20 deletions
diff --git a/mysql-test/main/func_json.result b/mysql-test/main/func_json.result
index 8b4c98ae9fd..5fee9ce4c32 100644
--- a/mysql-test/main/func_json.result
+++ b/mysql-test/main/func_json.result
@@ -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
diff --git a/mysql-test/main/func_json.test b/mysql-test/main/func_json.test
index c417a8ea4f8..a1e52a0494c 100644
--- a/mysql-test/main/func_json.test
+++ b/mysql-test/main/func_json.test
@@ -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
diff --git a/sql/json_schema.cc b/sql/json_schema.cc
index a358ef735d0..d0bb162cefe 100644
--- a/sql/json_schema.cc
+++ b/sql/json_schema.cc
@@ -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
{
diff --git a/sql/json_schema.h b/sql/json_schema.h
index 5da2576d7c4..4f1e146c862 100644
--- a/sql/json_schema.h
+++ b/sql/json_schema.h
@@ -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()
{