Skip to content

Commit 3abfd1f

Browse files
prohibit the use of initial_schema_uri as an override in evaluate()
The indexed resource would be permanently altered in both the document and the main resource index; the correct thing to do to adjust the root identifier for a schema would be to pass a canonical_uri to either the Document constructor or to add_document().
1 parent 795b286 commit 3abfd1f

File tree

2 files changed

+49
-85
lines changed

2 files changed

+49
-85
lines changed

lib/JSON/Schema/Modern.pm

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,8 @@ sub traverse ($self, $schema_reference, $config_override = {}) {
279279
croak join(', ', sort keys %overrides), ' not supported as a config override in traverse'
280280
if keys %overrides;
281281

282-
# Note: the starting position is not guaranteed to be at the root of the $document.
282+
# Note: the starting position is not guaranteed to be at the root of the $document,
283+
# nor is the fragment portion of this uri necessarily empty
283284
my $initial_uri = Mojo::URL->new($config_override->{initial_schema_uri} // '');
284285
my $initial_path = $config_override->{traversed_schema_path} // '';
285286
my $spec_version = $config_override->{specification_version} // $self->specification_version // SPECIFICATION_VERSION_DEFAULT;
@@ -363,7 +364,7 @@ sub evaluate ($self, $data, $schema_reference, $config_override = {}) {
363364

364365
# note this is not quite the same list as what we use when defining $state below
365366
my %overrides = %$config_override;
366-
delete @overrides{qw(validate_formats validate_content_schemas short_circuit collect_annotations scalarref_booleans stringy_numbers strict callbacks initial_schema_uri effective_base_uri data_path traversed_schema_path _strict_schema_data)};
367+
delete @overrides{qw(validate_formats validate_content_schemas short_circuit collect_annotations scalarref_booleans stringy_numbers strict callbacks effective_base_uri data_path traversed_schema_path _strict_schema_data)};
367368
croak join(', ', sort keys %overrides), ' not supported as a config override in evaluate'
368369
if keys %overrides;
369370

@@ -373,7 +374,6 @@ sub evaluate ($self, $data, $schema_reference, $config_override = {}) {
373374

374375
if (not is_ref($schema_reference) or $schema_reference->$_isa('Mojo::URL')) {
375376
$schema_info = $self->_fetch_from_uri($schema_reference);
376-
$state->{initial_schema_uri} = Mojo::URL->new($config_override->{initial_schema_uri} // '');
377377
}
378378
else {
379379
# traverse is called via add_schema -> ::Document->new -> ::Document->BUILD
@@ -1465,7 +1465,6 @@ applications that contain embedded JSON Schemas):
14651465
=for :list
14661466
* C<data_path>: adjusts the effective path of the data instance as of the start of evaluation
14671467
* C<traversed_schema_path>: adjusts the accumulated path as of the start of evaluation (or last C<$id> or C<$ref>)
1468-
* C<initial_schema_uri>: adjusts the recorded absolute keyword location as of the start of evaluation
14691468
* C<effective_base_uri>: locations in errors and annotations are resolved against this URI
14701469
14711470
You can pass a series of callback subs to this method corresponding to keywords, which is useful for
@@ -1509,7 +1508,7 @@ applications that contain embedded JSON Schemas):
15091508
15101509
=for :list
15111510
* C<traversed_schema_path>: adjusts the accumulated path as of the start of evaluation (or last C<$id> or C<$ref>)
1512-
* C<initial_schema_uri>: adjusts the recorded absolute keyword location as of the start of evaluation
1511+
* C<initial_schema_uri>: adjusts the absolute keyword location as of the start of evaluation
15131512
* C<metaschema_uri>: use the indicated URI as the metaschema
15141513
15151514
You can pass a series of callback subs to this method corresponding to keywords, which is useful for

t/errors.t

Lines changed: 45 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,85 +1312,6 @@ subtest dependentRequired => sub {
13121312
);
13131313
};
13141314

1315-
subtest 'evaluate in the middle of a document' => sub {
1316-
$js->add_schema({
1317-
'$id' => 'https://myschema',
1318-
properties => {
1319-
foo => {
1320-
'$id' => 'https://my-inner-schema',
1321-
allOf => [
1322-
{ # <-- evaluation starts here
1323-
type => 'object',
1324-
properties => {
1325-
bar => {
1326-
type => 'string',
1327-
},
1328-
},
1329-
},
1330-
],
1331-
},
1332-
},
1333-
});
1334-
1335-
cmp_result(
1336-
$js->evaluate(
1337-
{
1338-
bar => ['not a string'],
1339-
},
1340-
'https://myschema#/properties/foo/allOf/1',
1341-
{
1342-
data_path => '/request/body',
1343-
traversed_schema_path => '/some/other/thing/$ref/foo/$ref',
1344-
initial_schema_uri => 'https://somewhere/else#/foo',
1345-
},
1346-
)->TO_JSON,
1347-
{
1348-
valid => false,
1349-
errors => [
1350-
{
1351-
instanceLocation => '/request/body',
1352-
keywordLocation => '/some/other/thing/$ref/foo/$ref',
1353-
absoluteKeywordLocation => 'https://somewhere/else#/foo',
1354-
error => 'EXCEPTION: unable to find resource "https://myschema#/properties/foo/allOf/1"',
1355-
},
1356-
],
1357-
},
1358-
'provided evaluation uri does not exist',
1359-
);
1360-
1361-
cmp_result(
1362-
$js->evaluate(
1363-
{
1364-
bar => ['not a string'],
1365-
},
1366-
'https://myschema#/properties/foo/allOf/0', # <-- not the canonical URI!
1367-
{
1368-
data_path => '/request/body',
1369-
traversed_schema_path => '/some/other/thing/$ref/foo/$ref',
1370-
initial_schema_uri => 'https://somewhere/else#/foo',
1371-
},
1372-
)->TO_JSON,
1373-
{
1374-
valid => false,
1375-
errors => [
1376-
{
1377-
instanceLocation => '/request/body/bar',
1378-
keywordLocation => '/some/other/thing/$ref/foo/$ref/properties/bar/type',
1379-
absoluteKeywordLocation => 'https://my-inner-schema#/allOf/0/properties/bar/type',
1380-
error => 'got array, not string',
1381-
},
1382-
{
1383-
instanceLocation => '/request/body',
1384-
keywordLocation => '/some/other/thing/$ref/foo/$ref/properties',
1385-
absoluteKeywordLocation => 'https://my-inner-schema#/allOf/0/properties',
1386-
error => 'not all properties are valid',
1387-
},
1388-
],
1389-
},
1390-
'error has correct locations from override hash',
1391-
);
1392-
};
1393-
13941315
subtest 'numbers in output' => sub {
13951316
cmp_result(
13961317
$js->evaluate(
@@ -1437,7 +1358,7 @@ subtest 'numbers in output' => sub {
14371358
);
14381359
};
14391360

1440-
subtest 'effective_base_uri' => sub {
1361+
subtest 'effective_base_uri and overriding starting locations' => sub {
14411362
cmp_result(
14421363
$js->evaluate(
14431364
5,
@@ -1470,6 +1391,50 @@ subtest 'effective_base_uri' => sub {
14701391
},
14711392
'error locations are relative to the effective_base_uri, but $ref usage is not restricted',
14721393
);
1394+
1395+
# evaluating this document from its root would do nothing, as it is only definitions
1396+
$js->add_schema('/api', {
1397+
'$defs' => {
1398+
alpha => {
1399+
items => {
1400+
'$ref' => '#/$defs/beta',
1401+
},
1402+
},
1403+
beta => {
1404+
not => true,
1405+
},
1406+
},
1407+
});
1408+
1409+
cmp_result(
1410+
$js->evaluate(
1411+
[ 5 ],
1412+
'/api#/$defs/alpha',
1413+
{
1414+
data_path => '/html/body/div/div/h1/div/p', # reported data location
1415+
traversed_schema_path => '/some/other/document/$ref', # reported keywords passed through before we start
1416+
effective_base_uri => 'https://example.com', # base uri to use for document locations
1417+
},
1418+
)->TO_JSON,
1419+
{
1420+
valid => false,
1421+
errors => [
1422+
{
1423+
instanceLocation => '/html/body/div/div/h1/div/p/0',
1424+
keywordLocation => '/some/other/document/$ref/items/$ref/not',
1425+
absoluteKeywordLocation => 'https://example.com/api#/$defs/beta/not',
1426+
error => 'subschema is valid',
1427+
},
1428+
{
1429+
instanceLocation => '/html/body/div/div/h1/div/p',
1430+
keywordLocation => '/some/other/document/$ref/items',
1431+
absoluteKeywordLocation => 'https://example.com/api#/$defs/alpha/items',
1432+
error => 'subschema is not valid against all items',
1433+
},
1434+
],
1435+
},
1436+
'can alter locations with data_path, traversed_schema_path, effective_base_uri',
1437+
);
14731438
};
14741439

14751440
subtest 'recommended_response' => sub {

0 commit comments

Comments
 (0)