@@ -247,6 +247,12 @@ auto sourcemeta::jsonschema::validate(const sourcemeta::core::Options &options)
247247 schema_path, std::make_error_code (std::errc::is_a_directory)};
248248 }
249249
250+ if (options.contains (" path" ) && !options.at (" path" ).empty () &&
251+ options.contains (" template" ) && !options.at (" template" ).empty ()) {
252+ throw OptionConflictError{
253+ " The --path option cannot be used with --template" };
254+ }
255+
250256 const auto schema_config_base{schema_from_stdin
251257 ? std::filesystem::current_path ()
252258 : std::filesystem::path (schema_path)};
@@ -258,10 +264,27 @@ auto sourcemeta::jsonschema::validate(const sourcemeta::core::Options &options)
258264 read_configuration (options, configuration_path, schema_config_base)};
259265 const auto dialect{default_dialect (options, configuration)};
260266
261- const auto schema{schema_from_stdin
262- ? read_from_stdin ().document
267+ sourcemeta::core::JSON schema{
268+ schema_from_stdin ? read_from_stdin ().document
263269 : sourcemeta::core::read_yaml_or_json (schema_path)};
264270
271+ if (options.contains (" path" ) && !options.at (" path" ).empty ()) {
272+ const auto path_string{std::string{options.at (" path" ).front ()}};
273+ const auto pointer{sourcemeta::core::to_pointer (path_string)};
274+ const auto *const result{sourcemeta::core::try_get (schema, pointer)};
275+ // We intentionally reuse NotSchemaError here to align with existing CLI
276+ // error semantics without introducing a new error type.
277+ if (!result) {
278+ throw NotSchemaError{schema_from_stdin ? stdin_path ()
279+ : schema_resolution_base};
280+ }
281+ // `result` points into `schema`, so we must copy before reassigning to
282+ // avoid a use-after-free (the copy assignment destroys schema's storage
283+ // before reading from other when they alias).
284+ sourcemeta::core::JSON subschema{*result};
285+ schema = std::move (subschema);
286+ }
287+
265288 if (!sourcemeta::core::is_schema (schema)) {
266289 throw NotSchemaError{schema_from_stdin ? stdin_path ()
267290 : schema_resolution_base};
@@ -291,9 +314,9 @@ auto sourcemeta::jsonschema::validate(const sourcemeta::core::Options &options)
291314
292315 const sourcemeta::core::JSON bundled{[&]() {
293316 try {
294- return sourcemeta::core::bundle (schema, sourcemeta::core::schema_walker,
295- custom_resolver, dialect ,
296- schema_default_id);
317+ return sourcemeta::core::bundle (
318+ std::as_const (schema), sourcemeta::core::schema_walker ,
319+ custom_resolver, dialect, schema_default_id);
297320 } catch (const sourcemeta::core::SchemaKeywordError &error) {
298321 throw sourcemeta::core::FileError<sourcemeta::core::SchemaKeywordError>(
299322 schema_resolution_base, error);
0 commit comments