diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a5b53ab..ed273005 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,12 @@ if(JSONBINPACK_INSTALL) COMPONENT sourcemeta_jsonbinpack_dev) endif() +if(JSONBINPACK_ADDRESS_SANITIZER) + sourcemeta_sanitizer(TYPE address) +elseif(JSONBINPACK_UNDEFINED_SANITIZER) + sourcemeta_sanitizer(TYPE undefined) +endif() + # Runtime if(JSONBINPACK_RUNTIME) add_subdirectory(src/runtime) @@ -46,12 +52,6 @@ if(JSONBINPACK_COMPILER) add_subdirectory(src/compiler) endif() -if(JSONBINPACK_ADDRESS_SANITIZER) - sourcemeta_sanitizer(TYPE address) -elseif(JSONBINPACK_UNDEFINED_SANITIZER) - sourcemeta_sanitizer(TYPE undefined) -endif() - if(JSONBINPACK_DOCS) sourcemeta_target_doxygen(CONFIG "${PROJECT_SOURCE_DIR}/doxygen/Doxyfile.in" OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/www") diff --git a/DEPENDENCIES b/DEPENDENCIES index 94b1c9fe..227116dd 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -1,4 +1,4 @@ vendorpull https://github.com/sourcemeta/vendorpull 1dcbac42809cf87cb5b045106b863e17ad84ba02 -core https://github.com/sourcemeta/core 036ae97b31bf133fa5c19ad0192bc1eb008f1b0b -blaze https://github.com/sourcemeta/blaze 31d3723e2bfac22acbaaae23f1f9d02e75ce4c00 +core https://github.com/sourcemeta/core 3e1d11893f8a7144c4ec2267f5d3f54da551f083 +blaze https://github.com/sourcemeta/blaze 554ac837d7a088602276df5fff6fac21434fbeda bootstrap https://github.com/twbs/bootstrap 1a6fdfae6be09b09eaced8f0e442ca6f7680a61e diff --git a/cmake/FindCore.cmake b/cmake/FindCore.cmake index 88a98d04..3924264c 100644 --- a/cmake/FindCore.cmake +++ b/cmake/FindCore.cmake @@ -5,6 +5,12 @@ if(NOT Core_FOUND) set(SOURCEMETA_CORE_INSTALL OFF CACHE BOOL "disable installation") endif() + if(JSONBINPACK_ADDRESS_SANITIZER OR JSONBINPACK_UNDEFINED_SANITIZER) + set(SOURCEMETA_CORE_USE_SYSTEM_ALLOCATOR ON CACHE BOOL "enable the system allocator") + else() + set(SOURCEMETA_CORE_USE_SYSTEM_ALLOCATOR OFF CACHE BOOL "disable the system allocator") + endif() + set(SOURCEMETA_CORE_LANG_PROCESS OFF CACHE BOOL "disable") set(SOURCEMETA_CORE_LANG_PARALLEL OFF CACHE BOOL "disable") set(SOURCEMETA_CORE_LANG_ERROR OFF CACHE BOOL "disable") diff --git a/vendor/blaze/CMakeLists.txt b/vendor/blaze/CMakeLists.txt index d4da10a5..ff0c803c 100644 --- a/vendor/blaze/CMakeLists.txt +++ b/vendor/blaze/CMakeLists.txt @@ -50,6 +50,13 @@ if(PROJECT_IS_TOP_LEVEL) sourcemeta_enable_simd() endif() +# Enable the sanitizers before defining any target +if(BLAZE_ADDRESS_SANITIZER) + sourcemeta_sanitizer(TYPE address) +elseif(BLAZE_UNDEFINED_SANITIZER) + sourcemeta_sanitizer(TYPE undefined) +endif() + if(BLAZE_FOUNDATION) add_subdirectory(src/foundation) endif() @@ -106,12 +113,6 @@ if(BLAZE_CONTRIB) add_subdirectory(contrib) endif() -if(BLAZE_ADDRESS_SANITIZER) - sourcemeta_sanitizer(TYPE address) -elseif(BLAZE_UNDEFINED_SANITIZER) - sourcemeta_sanitizer(TYPE undefined) -endif() - if(BLAZE_DOCS) sourcemeta_target_doxygen(CONFIG "${PROJECT_SOURCE_DIR}/doxygen/Doxyfile.in" OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/website") diff --git a/vendor/blaze/DEPENDENCIES b/vendor/blaze/DEPENDENCIES index 14b37c78..f44968c2 100644 --- a/vendor/blaze/DEPENDENCIES +++ b/vendor/blaze/DEPENDENCIES @@ -1,5 +1,5 @@ vendorpull https://github.com/sourcemeta/vendorpull 1dcbac42809cf87cb5b045106b863e17ad84ba02 -core https://github.com/sourcemeta/core 036ae97b31bf133fa5c19ad0192bc1eb008f1b0b +core https://github.com/sourcemeta/core 3e1d11893f8a7144c4ec2267f5d3f54da551f083 jsonschema-test-suite https://github.com/json-schema-org/JSON-Schema-Test-Suite 1acd90e53554fa24d2529b49fd7d50bab18f8b7e jsonschema-2020-12 https://github.com/json-schema-org/json-schema-spec 769daad75a9553562333a8937a187741cb708c72 jsonschema-2019-09 https://github.com/json-schema-org/json-schema-spec 41014ea723120ce70b314d72f863c6929d9f3cfd diff --git a/vendor/blaze/src/bundle/bundle.cc b/vendor/blaze/src/bundle/bundle.cc index efdba7b7..c5ccee7b 100644 --- a/vendor/blaze/src/bundle/bundle.cc +++ b/vendor/blaze/src/bundle/bundle.cc @@ -11,7 +11,7 @@ #include // std::tuple #include // std::unordered_map #include // std::unordered_set -#include // std::move +#include // std::move, std::pair #include // std::vector namespace { @@ -166,6 +166,8 @@ auto elevate_embedded_resources( } auto &defs{remote.at(keyword_string)}; + const auto remote_dialect_uri{ + sourcemeta::blaze::dialect(remote, default_dialect)}; // Navigate to the root container once, as it doesn't change per entry const sourcemeta::core::JSON *root_container{&root}; @@ -180,7 +182,7 @@ auto elevate_embedded_resources( root_container = &root_container->at(token.to_property()); } - std::vector to_extract; + std::vector> to_extract; std::vector to_remove; for (const auto &entry : defs.as_object()) { const auto &key{entry.first}; @@ -196,6 +198,7 @@ auto elevate_embedded_resources( } const sourcemeta::core::JSON::String identifier_string{identifier}; + const auto defines_dialect{value.defines("$schema")}; if (bundled.contains(identifier_string)) { if (container_exists && root_container->is_object()) { for (const auto &root_entry : root_container->as_object()) { @@ -214,9 +217,23 @@ auto elevate_embedded_resources( continue; } - if (root_entry.second != value) { - throw sourcemeta::blaze::SchemaError( - "Conflicting embedded resources with the same identifier"); + if (defines_dialect) { + if (root_entry.second != value) { + throw sourcemeta::blaze::SchemaError( + "Conflicting embedded resources with the same identifier"); + } + } else { + // The stored copy of the resource got its dialect stamped on + // extraction, so compare against a candidate that is stamped in + // the same way + auto candidate{value}; + candidate.assign("$schema", + sourcemeta::core::JSON{sourcemeta::blaze::dialect( + value, remote_dialect_uri)}); + if (root_entry.second != candidate) { + throw sourcemeta::blaze::SchemaError( + "Conflicting embedded resources with the same identifier"); + } } break; @@ -225,14 +242,22 @@ auto elevate_embedded_resources( to_remove.emplace_back(key); } else { - to_extract.emplace_back(key); + to_extract.emplace_back(key, !defines_dialect); bundled.emplace(identifier_string, identifier_string); } } - for (const auto &key : to_extract) { + for (const auto &[key, needs_dialect] : to_extract) { auto value{std::move(defs.at(key))}; defs.erase(key); + // Otherwise the elevated resource would be re-interpreted under the + // dialect of the schema it gets embedded into, which can differ from + // the dialect it inherited from the remote it was elevated out of + if (needs_dialect) { + value.assign("$schema", sourcemeta::core::JSON{sourcemeta::blaze::dialect( + value, remote_dialect_uri)}); + } + embed_schema(root, container, key, std::move(value)); } diff --git a/vendor/blaze/src/foundation/foundation.cc b/vendor/blaze/src/foundation/foundation.cc index 4371c415..bc9cf63d 100644 --- a/vendor/blaze/src/foundation/foundation.cc +++ b/vendor/blaze/src/foundation/foundation.cc @@ -260,13 +260,14 @@ auto sourcemeta::blaze::dialect(const sourcemeta::core::JSON &schema, return dialect_value.to_string(); } -// A meta-schema that is not known to the resolver may still be embedded in -// the document itself. Across every official base dialect, the only -// containers that can hold embedded resources are `$defs` and `definitions`, -// which no custom dialect can redefine away. A candidate only counts if its -// entire meta-schema chain terminates at an official base dialect and every -// embedded link declares its identifier and sits in a container in a way -// that is valid for such base dialect +// A meta-schema that the document embeds takes precedence over what the +// resolver knows about, at every link of the chain, as the document pins the +// exact meta-schemas it is described by. Across every official base dialect, +// the only containers that can hold embedded resources are `$defs` and +// `definitions`, which no custom dialect can redefine away. A candidate only +// counts if its entire meta-schema chain terminates at an official base +// dialect and every embedded link declares its identifier and sits in a +// container in a way that is valid for such base dialect auto sourcemeta::blaze::metaschema_try_embedded( const sourcemeta::core::JSON &schema, const std::string_view identifier, const SchemaResolver &resolver) -> const sourcemeta::core::JSON * { @@ -319,28 +320,26 @@ auto sourcemeta::blaze::metaschema_try_embedded( break; } - auto remote{resolver(dialect_uri)}; - if (remote.has_value()) { - resolved.push_back(std::move(remote).value()); - current = &resolved.back(); - current_identifier = dialect_uri; - continue; - } - - if (!sourcemeta::core::URI::is_uri(dialect_uri)) { - return nullptr; + if (sourcemeta::core::URI::is_uri(dialect_uri)) { + const auto next{sourcemeta::blaze::embedded_metaschema_candidate( + schema, dialect_uri)}; + if (next.first) { + links.push_back({.schema = next.first, + .identifier = dialect_uri, + .container = next.second}); + current = next.first; + current_identifier = dialect_uri; + continue; + } } - const auto next{ - sourcemeta::blaze::embedded_metaschema_candidate(schema, dialect_uri)}; - if (!next.first) { + auto remote{resolver(dialect_uri)}; + if (!remote.has_value()) { return nullptr; } - links.push_back({.schema = next.first, - .identifier = dialect_uri, - .container = next.second}); - current = next.first; + resolved.push_back(std::move(remote).value()); + current = &resolved.back(); current_identifier = dialect_uri; } diff --git a/vendor/blaze/src/test/include/sourcemeta/blaze/test.h b/vendor/blaze/src/test/include/sourcemeta/blaze/test.h index cc9f794a..de024109 100644 --- a/vendor/blaze/src/test/include/sourcemeta/blaze/test.h +++ b/vendor/blaze/src/test/include/sourcemeta/blaze/test.h @@ -118,10 +118,6 @@ struct SOURCEMETA_BLAZE_TEST_EXPORT TestSuite { std::vector targets; /// The list of test cases in the suite std::vector tests; - /// The compiled schema templates for fast validation - std::vector