Skip to content

Commit

Permalink
Throw an exception when re-identifying and $ref overrides ($)id (#…
Browse files Browse the repository at this point in the history
…1421)

Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
  • Loading branch information
jviotti authored Jan 6, 2025
1 parent 16e66cd commit b3a208d
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 9 deletions.
28 changes: 19 additions & 9 deletions src/jsonschema/jsonschema.cc
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,17 @@ auto sourcemeta::jsontoolkit::identify(
return identify(schema, maybe_base_dialect.value(), default_id);
}

static auto ref_overrides_sibling(const std::string &base_dialect) -> bool {
return (base_dialect == "http://json-schema.org/draft-07/schema#" ||
base_dialect == "http://json-schema.org/draft-07/hyper-schema#" ||
base_dialect == "http://json-schema.org/draft-06/schema#" ||
base_dialect == "http://json-schema.org/draft-06/hyper-schema#" ||
base_dialect == "http://json-schema.org/draft-04/schema#" ||
base_dialect == "http://json-schema.org/draft-04/hyper-schema#" ||
base_dialect == "http://json-schema.org/draft-03/schema#" ||
base_dialect == "http://json-schema.org/draft-03/hyper-schema#");
}

auto sourcemeta::jsontoolkit::identify(
const JSON &schema, const std::string &base_dialect,
const std::optional<std::string> &default_id)
Expand All @@ -125,15 +136,7 @@ auto sourcemeta::jsontoolkit::identify(
// don't check for base dialects lower than that.
// See
// https://json-schema.org/draft-07/draft-handrews-json-schema-01#rfc.section.8.3
if (schema.defines("$ref") &&
(base_dialect == "http://json-schema.org/draft-07/schema#" ||
base_dialect == "http://json-schema.org/draft-07/hyper-schema#" ||
base_dialect == "http://json-schema.org/draft-06/schema#" ||
base_dialect == "http://json-schema.org/draft-06/hyper-schema#" ||
base_dialect == "http://json-schema.org/draft-04/schema#" ||
base_dialect == "http://json-schema.org/draft-04/hyper-schema#" ||
base_dialect == "http://json-schema.org/draft-03/schema#" ||
base_dialect == "http://json-schema.org/draft-03/hyper-schema#")) {
if (schema.defines("$ref") && ref_overrides_sibling(base_dialect)) {
return std::nullopt;
}

Expand Down Expand Up @@ -167,6 +170,13 @@ auto sourcemeta::jsontoolkit::reidentify(JSON &schema,
-> void {
assert(is_schema(schema));
assert(schema.is_object());

if (ref_overrides_sibling(base_dialect) && schema.defines("$ref")) {
throw SchemaError(
"Cannot set an identifier on a schema that declares a "
"top-level static reference in this dialect of JSON Schema");
}

schema.assign(id_keyword(base_dialect), JSON{new_identifier});
assert(identify(schema, base_dialect).has_value());
}
Expand Down
21 changes: 21 additions & 0 deletions test/jsonschema/jsonschema_identify_2019_09_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -237,3 +237,24 @@ TEST(JSONSchema_identify_2019_09, reidentify_replace_base_dialect_shortcut) {

EXPECT_EQ(document, expected);
}

TEST(JSONSchema_identify_2019_09, reidentify_set_with_top_level_ref) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$ref": "https://example.com/schema"
})JSON");

sourcemeta::jsontoolkit::reidentify(
document, "https://example.com/my-new-id",
sourcemeta::jsontoolkit::official_resolver);

const sourcemeta::jsontoolkit::JSON expected =
sourcemeta::jsontoolkit::parse(R"JSON({
"$id": "https://example.com/my-new-id",
"$schema": "https://json-schema.org/draft/2019-09/schema",
"$ref": "https://example.com/schema"
})JSON");

EXPECT_EQ(document, expected);
}
21 changes: 21 additions & 0 deletions test/jsonschema/jsonschema_identify_2020_12_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -237,3 +237,24 @@ TEST(JSONSchema_identify_2020_12, reidentify_replace_base_dialect_shortcut) {

EXPECT_EQ(document, expected);
}

TEST(JSONSchema_identify_2020_12, reidentify_set_with_top_level_ref) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$ref": "https://example.com/schema"
})JSON");

sourcemeta::jsontoolkit::reidentify(
document, "https://example.com/my-new-id",
sourcemeta::jsontoolkit::official_resolver);

const sourcemeta::jsontoolkit::JSON expected =
sourcemeta::jsontoolkit::parse(R"JSON({
"$id": "https://example.com/my-new-id",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$ref": "https://example.com/schema"
})JSON");

EXPECT_EQ(document, expected);
}
13 changes: 13 additions & 0 deletions test/jsonschema/jsonschema_identify_draft3_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -236,3 +236,16 @@ TEST(JSONSchema_identify_draft3, reidentify_replace_base_dialect_shortcut) {

EXPECT_EQ(document, expected);
}

TEST(JSONSchema_identify_draft3, reidentify_set_with_top_level_ref) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-03/schema#",
"$ref": "https://example.com/schema"
})JSON");

EXPECT_THROW(sourcemeta::jsontoolkit::reidentify(
document, "https://example.com/my-new-id",
sourcemeta::jsontoolkit::official_resolver),
sourcemeta::jsontoolkit::SchemaError);
}
13 changes: 13 additions & 0 deletions test/jsonschema/jsonschema_identify_draft4_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -236,3 +236,16 @@ TEST(JSONSchema_identify_draft4, reidentify_replace_base_dialect_shortcut) {

EXPECT_EQ(document, expected);
}

TEST(JSONSchema_identify_draft4, reidentify_set_with_top_level_ref) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-04/schema#",
"$ref": "https://example.com/schema"
})JSON");

EXPECT_THROW(sourcemeta::jsontoolkit::reidentify(
document, "https://example.com/my-new-id",
sourcemeta::jsontoolkit::official_resolver),
sourcemeta::jsontoolkit::SchemaError);
}
13 changes: 13 additions & 0 deletions test/jsonschema/jsonschema_identify_draft6_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -236,3 +236,16 @@ TEST(JSONSchema_identify_draft6, reidentify_replace_base_dialect_shortcut) {

EXPECT_EQ(document, expected);
}

TEST(JSONSchema_identify_draft6, reidentify_set_with_top_level_ref) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-06/schema#",
"$ref": "https://example.com/schema"
})JSON");

EXPECT_THROW(sourcemeta::jsontoolkit::reidentify(
document, "https://example.com/my-new-id",
sourcemeta::jsontoolkit::official_resolver),
sourcemeta::jsontoolkit::SchemaError);
}
13 changes: 13 additions & 0 deletions test/jsonschema/jsonschema_identify_draft7_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -236,3 +236,16 @@ TEST(JSONSchema_identify_draft7, reidentify_replace_base_dialect_shortcut) {

EXPECT_EQ(document, expected);
}

TEST(JSONSchema_identify_draft7, reidentify_set_with_top_level_ref) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-07/schema#",
"$ref": "https://example.com/schema"
})JSON");

EXPECT_THROW(sourcemeta::jsontoolkit::reidentify(
document, "https://example.com/my-new-id",
sourcemeta::jsontoolkit::official_resolver),
sourcemeta::jsontoolkit::SchemaError);
}

4 comments on commit b3a208d

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark (macos/llvm)

Benchmark suite Current: b3a208d Previous: 16e66cd Ratio
JSON_Array_Of_Objects_Unique 388.3547347296708 ns/iter 334.78911762452213 ns/iter 1.16
JSON_Parse_1 24593.317760815295 ns/iter 21334.131343576417 ns/iter 1.15
JSON_Fast_Hash_Helm_Chart_Lock 58.545023577415286 ns/iter 49.16698021640305 ns/iter 1.19
JSON_Equality_Helm_Chart_Lock 148.4749491930972 ns/iter 140.25525054753484 ns/iter 1.06
Regex_Lower_S_Or_Upper_S_Asterisk 1.719109787862507 ns/iter 1.5671186552599168 ns/iter 1.10
Regex_Caret_Lower_S_Or_Upper_S_Asterisk_Dollar 1.7953203700805556 ns/iter 1.5789722906608812 ns/iter 1.14
Regex_Period_Asterisk 1.7820022235608939 ns/iter 1.789275723592215 ns/iter 1.00
Regex_Group_Period_Asterisk_Group 1.7994713276109702 ns/iter 1.576536627262247 ns/iter 1.14
Regex_Period_Plus 2.180514648595153 ns/iter 2.0543490345555355 ns/iter 1.06
Regex_Period 2.1915495853826847 ns/iter 1.8989788051477159 ns/iter 1.15
Regex_Caret_Period_Plus_Dollar 2.1299995452718052 ns/iter 1.8993088161357106 ns/iter 1.12
Regex_Caret_Group_Period_Plus_Group_Dollar 2.1227368247285763 ns/iter 1.8981785176258545 ns/iter 1.12
Regex_Caret_Period_Asterisk_Dollar 1.8125836474450305 ns/iter 1.5760333282378687 ns/iter 1.15
Regex_Caret_Group_Period_Asterisk_Group_Dollar 1.8456102863971515 ns/iter 1.5829595761755584 ns/iter 1.17
Regex_Caret_X_Hyphen 6.935337984107705 ns/iter 6.313721402418762 ns/iter 1.10
Regex_Period_Md_Dollar 79.50944666746975 ns/iter 67.89963623684277 ns/iter 1.17
Regex_Caret_Slash_Period_Asterisk 7.311963883187427 ns/iter 6.731995979847379 ns/iter 1.09
Regex_Caret_Period_Range_Dollar 2.236217299441727 ns/iter 2.059469095130364 ns/iter 1.09
Regex_Nested_Backtrack 807.2955664750376 ns/iter 738.7008692913683 ns/iter 1.09
Pointer_Object_Traverse 16.02090361945681 ns/iter 16.909531927793754 ns/iter 0.95
Pointer_Object_Try_Traverse 34.536290676619224 ns/iter 32.4261222750035 ns/iter 1.07
Pointer_Push_Back_Pointer_To_Weak_Pointer 198.01715156545967 ns/iter 174.43094317138178 ns/iter 1.14

This comment was automatically generated by workflow using github-action-benchmark.

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark (linux/llvm)

Benchmark suite Current: b3a208d Previous: 16e66cd Ratio
JSON_Array_Of_Objects_Unique 443.8216909718648 ns/iter 447.66520367185745 ns/iter 0.99
JSON_Parse_1 30870.327975979046 ns/iter 30251.57244213812 ns/iter 1.02
JSON_Fast_Hash_Helm_Chart_Lock 54.807580190187196 ns/iter 54.64601006541843 ns/iter 1.00
JSON_Equality_Helm_Chart_Lock 149.31430527388156 ns/iter 149.58393090647078 ns/iter 1.00
Regex_Lower_S_Or_Upper_S_Asterisk 2.204875721950247 ns/iter 2.200158840817654 ns/iter 1.00
Regex_Caret_Lower_S_Or_Upper_S_Asterisk_Dollar 2.1928518973772166 ns/iter 2.1811356928147183 ns/iter 1.01
Regex_Period_Asterisk 2.19866263447157 ns/iter 2.201214575926632 ns/iter 1.00
Regex_Group_Period_Asterisk_Group 2.202792555923439 ns/iter 2.216045958713959 ns/iter 0.99
Regex_Period_Plus 2.486444520734314 ns/iter 2.244878844220564 ns/iter 1.11
Regex_Period 2.506823397558652 ns/iter 2.261169073222483 ns/iter 1.11
Regex_Caret_Period_Plus_Dollar 2.4891329500093318 ns/iter 2.2661915249759224 ns/iter 1.10
Regex_Caret_Group_Period_Plus_Group_Dollar 2.4865027104304285 ns/iter 2.2603063315400305 ns/iter 1.10
Regex_Caret_Period_Asterisk_Dollar 3.417071023765133 ns/iter 2.487120680708214 ns/iter 1.37
Regex_Caret_Group_Period_Asterisk_Group_Dollar 3.417194620003428 ns/iter 2.4865028776082605 ns/iter 1.37
Regex_Caret_X_Hyphen 7.461082750338184 ns/iter 7.461329389148237 ns/iter 1.00
Regex_Period_Md_Dollar 74.71244249975501 ns/iter 74.11868915665042 ns/iter 1.01
Regex_Caret_Slash_Period_Asterisk 7.147608018317036 ns/iter 7.145345089989452 ns/iter 1.00
Regex_Caret_Period_Range_Dollar 3.728394814670792 ns/iter 3.7244037623666104 ns/iter 1.00
Regex_Nested_Backtrack 493.96259124150424 ns/iter 492.89612697866085 ns/iter 1.00
Pointer_Object_Traverse 44.81471572939452 ns/iter 45.650367825891664 ns/iter 0.98
Pointer_Object_Try_Traverse 52.38450672696248 ns/iter 52.21074023036143 ns/iter 1.00
Pointer_Push_Back_Pointer_To_Weak_Pointer 352.9591835293568 ns/iter 353.8390478493588 ns/iter 1.00

This comment was automatically generated by workflow using github-action-benchmark.

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark (windows/msvc)

Benchmark suite Current: b3a208d Previous: 16e66cd Ratio
JSON_Array_Of_Objects_Unique 419.47351197132787 ns/iter 439.97843125580846 ns/iter 0.95
JSON_Parse_1 79436.81532074645 ns/iter 86810.15133253469 ns/iter 0.92
JSON_Fast_Hash_Helm_Chart_Lock 52.2561200000041 ns/iter 56.89972999999782 ns/iter 0.92
JSON_Equality_Helm_Chart_Lock 220.12059375001058 ns/iter 234.44159374999884 ns/iter 0.94
Regex_Lower_S_Or_Upper_S_Asterisk 8.16581915997396 ns/iter 8.929441031565641 ns/iter 0.91
Regex_Caret_Lower_S_Or_Upper_S_Asterisk_Dollar 7.9006350446420015 ns/iter 7.929005321745428 ns/iter 1.00
Regex_Period_Asterisk 7.895462911179545 ns/iter 8.067330357142767 ns/iter 0.98
Regex_Group_Period_Asterisk_Group 7.849104875673845 ns/iter 7.84424441964328 ns/iter 1.00
Regex_Period_Plus 7.786670054523892 ns/iter 8.034847731986886 ns/iter 0.97
Regex_Period 7.886783000505064 ns/iter 7.877407366071612 ns/iter 1.00
Regex_Caret_Period_Plus_Dollar 7.904286125427345 ns/iter 8.125233258929095 ns/iter 0.97
Regex_Caret_Group_Period_Plus_Group_Dollar 8.10100576740719 ns/iter 8.186296875000007 ns/iter 0.99
Regex_Caret_Period_Asterisk_Dollar 7.863545054179978 ns/iter 8.239706473214575 ns/iter 0.95
Regex_Caret_Group_Period_Asterisk_Group_Dollar 7.877563616071218 ns/iter 8.336635677068307 ns/iter 0.94
Regex_Caret_X_Hyphen 11.871144642857498 ns/iter 12.161824499276952 ns/iter 0.98
Regex_Period_Md_Dollar 142.7856364827829 ns/iter 145.74046875000283 ns/iter 0.98
Regex_Caret_Slash_Period_Asterisk 11.739018749999275 ns/iter 11.535155357143319 ns/iter 1.02
Regex_Caret_Period_Range_Dollar 8.727760675322878 ns/iter 8.703137907574638 ns/iter 1.00
Regex_Nested_Backtrack 588.2827678570987 ns/iter 593.8169642857158 ns/iter 0.99
Pointer_Object_Traverse 56.780030000004444 ns/iter 56.34542857143694 ns/iter 1.01
Pointer_Object_Try_Traverse 75.86959821429063 ns/iter 76.24186383929604 ns/iter 1.00
Pointer_Push_Back_Pointer_To_Weak_Pointer 182.80445382182648 ns/iter 181.24099651167313 ns/iter 1.01

This comment was automatically generated by workflow using github-action-benchmark.

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark (linux/gcc)

Benchmark suite Current: b3a208d Previous: 16e66cd Ratio
Pointer_Object_Traverse 44.755567175655656 ns/iter 46.72869247972302 ns/iter 0.96
Pointer_Object_Try_Traverse 22.434193227016205 ns/iter 22.42281395275975 ns/iter 1.00
Pointer_Push_Back_Pointer_To_Weak_Pointer 214.67710321269962 ns/iter 213.1276868115032 ns/iter 1.01
Regex_Lower_S_Or_Upper_S_Asterisk 3.126022176619008 ns/iter 3.124726224897788 ns/iter 1.00
Regex_Caret_Lower_S_Or_Upper_S_Asterisk_Dollar 3.1305882731536867 ns/iter 3.1340321782658807 ns/iter 1.00
Regex_Period_Asterisk 3.123425530322061 ns/iter 3.1432972943424278 ns/iter 0.99
Regex_Group_Period_Asterisk_Group 3.1298497215982115 ns/iter 3.1301289854032373 ns/iter 1.00
Regex_Period_Plus 3.122830425844465 ns/iter 3.1242674036195486 ns/iter 1.00
Regex_Period 3.1234952580334596 ns/iter 3.126393244408423 ns/iter 1.00
Regex_Caret_Period_Plus_Dollar 3.1286515476959122 ns/iter 3.1261821865256976 ns/iter 1.00
Regex_Caret_Group_Period_Plus_Group_Dollar 3.1571107485885914 ns/iter 3.126988682397506 ns/iter 1.01
Regex_Caret_Period_Asterisk_Dollar 3.733453373388718 ns/iter 3.72920273657548 ns/iter 1.00
Regex_Caret_Group_Period_Asterisk_Group_Dollar 3.73085095616093 ns/iter 3.589990857045418 ns/iter 1.04
Regex_Caret_X_Hyphen 12.428559836232674 ns/iter 12.43338893722167 ns/iter 1.00
Regex_Period_Md_Dollar 90.09064432168736 ns/iter 89.96237420154176 ns/iter 1.00
Regex_Caret_Slash_Period_Asterisk 7.14730105289689 ns/iter 6.219499606530663 ns/iter 1.15
Regex_Caret_Period_Range_Dollar 4.04044961193531 ns/iter 3.1732187403859444 ns/iter 1.27
Regex_Nested_Backtrack 812.6147451917195 ns/iter 816.2189365544923 ns/iter 1.00
JSON_Array_Of_Objects_Unique 382.4648036039672 ns/iter 378.6682252693765 ns/iter 1.01
JSON_Parse_1 32924.76700720282 ns/iter 32605.412195353118 ns/iter 1.01
JSON_Fast_Hash_Helm_Chart_Lock 62.78438304285357 ns/iter 66.7538971245688 ns/iter 0.94
JSON_Equality_Helm_Chart_Lock 143.8481141125099 ns/iter 143.02210425039226 ns/iter 1.01

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.