From 4674c04cb80e0a50cde1b97464642e2778f9522f Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Sun, 24 Jul 2022 16:44:51 -0400 Subject: JSON schema: support multi-element array validation --- libqpdf/JSON.cc | 52 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 12 deletions(-) (limited to 'libqpdf/JSON.cc') diff --git a/libqpdf/JSON.cc b/libqpdf/JSON.cc index 7bd2337f..9b9da656 100644 --- a/libqpdf/JSON.cc +++ b/libqpdf/JSON.cc @@ -538,27 +538,55 @@ JSON::checkSchemaInternal( } } } else if (sch_arr) { - if (sch_arr->elements.size() != 1) { - QTC::TC("libtests", "JSON schema array error"); + auto n_elements = sch_arr->elements.size(); + if (n_elements == 1) { + // A single-element array in the schema allows a single + // element in the object or a variable-length array, each + // of whose items must conform to the single element of + // the schema array. This doesn't apply to arrays of + // arrays -- we fall back to the behavior of allowing a + // single item only when the object is not an array. + if (this_arr) { + int i = 0; + for (auto const& element: this_arr->elements) { + checkSchemaInternal( + element.get(), + sch_arr->elements.at(0).get(), + flags, + errors, + prefix + "." + QUtil::int_to_string(i)); + ++i; + } + } else { + QTC::TC("libtests", "JSON schema array for single item"); + checkSchemaInternal( + this_v, + sch_arr->elements.at(0).get(), + flags, + errors, + prefix); + } + } else if (!this_arr || (this_arr->elements.size() != n_elements)) { + QTC::TC("libtests", "JSON schema array length mismatch"); errors.push_back( - err_prefix + " schema array contains other than one item"); + err_prefix + " is supposed to be an array of length " + + QUtil::uint_to_string(n_elements)); return false; - } - if (this_arr) { - int i = 0; + } else { + // A multi-element array in the schema must correspond to + // an element of the same length in the object. Each + // element in the object is validated against the + // corresponding element in the schema. + size_t i = 0; for (auto const& element: this_arr->elements) { checkSchemaInternal( element.get(), - sch_arr->elements.at(0).get(), + sch_arr->elements.at(i).get(), flags, errors, - prefix + "." + QUtil::int_to_string(i)); + prefix + "." + QUtil::uint_to_string(i)); ++i; } - } else { - QTC::TC("libtests", "JSON schema array for single item"); - checkSchemaInternal( - this_v, sch_arr->elements.at(0).get(), flags, errors, prefix); } } else if (!sch_str) { QTC::TC("libtests", "JSON schema other type"); -- cgit v1.2.3-54-g00ecf