![]() |
MySQL 8.4.9
Source Code Documentation
|
#include "sql/json_schema.h"#include <my_rapidjson_size_t.h>#include <assert.h>#include <rapidjson/document.h>#include <rapidjson/error/error.h>#include <rapidjson/memorystream.h>#include <rapidjson/pointer.h>#include <rapidjson/reader.h>#include <rapidjson/schema.h>#include <rapidjson/stringbuffer.h>#include <algorithm>#include <cassert>#include <cstdint>#include <string>#include <unordered_set>#include <utility>#include "my_alloc.h"#include "my_inttypes.h"#include "my_sys.h"#include "mysqld_error.h"#include "sql-common/json_syntax_check.h"#include "sql/sql_exception_handler.h"Functions | |
| static bool | is_local_json_pointer_ref (const rapidjson::Value &ref_value) |
Check whether a $ref value is a local JSON Pointer reference. More... | |
| static const rapidjson::Value * | resolve_local_json_pointer_ref (const rapidjson::Document &schema_document, const rapidjson::Value &ref_value) |
Resolve a local JSON Pointer $ref against the schema document. More... | |
| static bool | json_schema_exceeds_expansion_depth (const rapidjson::Document &schema_document, const rapidjson::Value *node, uint32_t depth_so_far, uint32_t limit, std::unordered_set< const rapidjson::Value * > *visiting) |
| Check whether any path from a schema node exceeds the expansion depth limit. More... | |
| static bool | check_json_schema_expansion_depth (const rapidjson::Document &schema_document) |
| Validate that a JSON Schema does not require excessive recursion depth during rapidjson schema compilation. More... | |
| static bool | parse_json_schema (const char *json_schema_str, size_t json_schema_length, const char *function_name, rapidjson::Document *schema_document) |
| parse_json_schema will parse a JSON input into a JSON Schema. More... | |
| bool | is_valid_json_schema (const char *document_str, size_t document_length, const char *json_schema_str, size_t json_schema_length, const char *function_name, bool *is_valid, Json_schema_validation_report *validation_report) |
| This function will validate a JSON document against a JSON Schema using the validation provided by rapidjson. More... | |
| unique_ptr_destroy_only< const Json_schema_validator > | create_json_schema_validator (MEM_ROOT *mem_root, const char *json_schema_str, size_t json_schema_length, const char *function_name) |
| Create a Json_schema_validator, allocated on a given MEM_ROOT. More... | |
Variables | |
| static constexpr uint32_t | JSON_SCHEMA_MAX_EXPANSION_DEPTH = 100 |
| Maximum "expansion depth" of a JSON Schema during rapidjson schema compilation. More... | |
|
static |
Validate that a JSON Schema does not require excessive recursion depth during rapidjson schema compilation.
rapidjson schema compilation expands local $ref by recursively compiling the referenced subschemas. The recursion depth is therefore related to the number of local reference "hops" along the deepest expansion path. This depth can be large even if no referred object has a $ref at its own top level, as long as each referred object contains a nested object with a $ref.
This function only checks whether any expansion path exceeds the limit. Each step into a nested object/array and each local $ref expansion counts as 1.
It does this by walking JSON-tree edges (object members / array elements) and local $ref edges (JSON pointer references starting with #), with early exit as soon as the limit is exceeded.
If the limit is exceeded (JSON_SCHEMA_MAX_EXPANSION_DEPTH), ER_JSON_DOCUMENT_TOO_DEEP is reported.
| schema_document | Parsed JSON schema document. |
| true | The schema exceeded the limit and an error was reported. |
| false | No expansion path exceeds the limit. |
| unique_ptr_destroy_only< const Json_schema_validator > create_json_schema_validator | ( | MEM_ROOT * | mem_root, |
| const char * | json_schema_str, | ||
| size_t | json_schema_length, | ||
| const char * | function_name | ||
| ) |
Create a Json_schema_validator, allocated on a given MEM_ROOT.
| mem_root | The MEM_ROOT to allocate the validator on |
| json_schema_str | A pointer to the JSON Schema |
| json_schema_length | The length of the JSON Schema input |
| function_name | The function name of the caller (to be used in error reporting) |
| nullptr | on error (my_error has been called) |
|
static |
Check whether a $ref value is a local JSON Pointer reference.
We only guard references of the form "#" or "#/...".
| ref_value | The value of the $ref member. |
| true | The $ref is a local JSON pointer reference. |
| false | Otherwise. |
| bool is_valid_json_schema | ( | const char * | document_str, |
| size_t | document_length, | ||
| const char * | json_schema_str, | ||
| size_t | json_schema_length, | ||
| const char * | function_name, | ||
| bool * | is_valid, | ||
| Json_schema_validation_report * | report | ||
| ) |
This function will validate a JSON document against a JSON Schema using the validation provided by rapidjson.
| document_str | A pointer to the JSON document to be validated. | |
| document_length | The length of the JSON document to be validated. | |
| json_schema_str | A pointer to the JSON Schema. | |
| json_schema_length | The length of the JSON Schema. | |
| function_name | The name of the SQL function calling this function. Used in error reporting. | |
| [out] | is_valid | A variable containing the result of the validation. If true, the JSON document is valid according to the given JSON Schema. |
| [out] | report | A structure containing a detailed report from the validation. Is only populated if is_valid is set to "false". Can be nullptr if a detailed report isn't needed. |
| true | if anything went wrong (like parsing the JSON inputs). my_error has been called with an appropriate error message. |
| false | if the validation succeeded. The result of the validation can be found in the output variable "is_valid". |
|
static |
Check whether any path from a schema node exceeds the expansion depth limit.
The expansion depth is the number of edges along a path in the schema's expansion graph:
$ref edges (local JSON Pointer references).visiting is used to break $ref cycles (cycles are treated as non-contributing; rapidjson will report cyclic references separately).
| schema_document | Parsed JSON schema document (used for resolving $ref). | |
| node | The node to start the search from. | |
| depth_so_far | Current depth from the schema root. | |
| limit | Maximum allowed expansion depth. | |
| [in,out] | visiting | Visitation set for cycle detection. |
| true | The limit is exceeded along some path. |
| false | No path exceeds the limit. |
|
static |
parse_json_schema will parse a JSON input into a JSON Schema.
If the input isn't a valid JSON, or if the JSON is too deeply nested, an error will be returned to the user.
| json_schema_str | A pointer to the JSON Schema input | |
| json_schema_length | The length of the JSON Schema input | |
| function_name | The function name of the caller (to be used in error reporting) | |
| [out] | schema_document | An object where the JSON Schema will be put. This variable MUST be initialized. |
| true | on error (my_error has been called) |
| false | on success. The JSON Schema can be found in the output parameter schema_document. |
|
static |
Resolve a local JSON Pointer $ref against the schema document.
| schema_document | The full JSON schema document. |
| ref_value | The $ref member value (must be a local JSON pointer). |
|
staticconstexpr |
Maximum "expansion depth" of a JSON Schema during rapidjson schema compilation.
rapidjson schema compilation is recursive. The call stack depth is driven by a combination of:
$ref expansion (compiling referenced subschemas recursively).This cap bounds the maximum number of edges along any path in the schema's "expansion graph", where both JSON-tree edges and local $ref edges count as 1.
Since MySQL rejects JSON documents deeper than 100 levels (see sql-common/json_syntax_check.cc), schemas requiring more than 100 levels of expansion cannot describe JSON documents supported by MySQL. We therefore use 100 as the single guard limit here as well.