Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 41 additions & 5 deletions packages/ruleset/src/functions/integer-attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ module.exports = function (schema, _opts, context) {
// These are the valid format values that can be used with integer schemas.
const intFormats = ['int32', 'int64'];

//These are the minimum and maximum values for integer schemas
const int32Minimum = -2147483648;
const int32Maximum = 2147483647;

const int64Minimum = -9007199254740991;
const int64Maximum = 9007199254740991;
Comment thread
diatrcz marked this conversation as resolved.
Outdated

/**
* This function performs various checks on an integer schema property to make sure it
* contains the "minimum", "maximum" attributes.
Expand Down Expand Up @@ -70,11 +77,40 @@ function integerBoundaryErrors(schema, path) {
path,
});
}
if (isDefined(minimum) && isDefined(maximum) && minimum > maximum) {
errors.push({
message: `'minimum' cannot be greater than 'maximum'`,
path,
});
if (isDefined(minimum) && isDefined(maximum)) {
if (minimum > maximum) {
errors.push({
message: `'minimum' cannot be greater than 'maximum'`,
path,
});
}
if (format === 'int32') {
if (minimum > int32Maximum || minimum < int32Minimum) {
errors.push({
message: `'minimum' value is out of safe range`,
path,
});
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We might not want to gate this on maximum also being defined (and corresponding feedback for the three below).

if (maximum > int32Maximum || maximum < int32Minimum) {
errors.push({
message: `'maximum' value is out of safe range`,
path,
});
}
} else {
if (minimum > int64Maximum || minimum < int64Minimum) {
errors.push({
message: `'minimum' value is out of safe range`,
path,
});
}
if (maximum > int64Maximum || maximum < int64Minimum) {
errors.push({
message: `'maximum' value is out of safe range`,
path,
});
}
}
}

return errors;
Expand Down
64 changes: 64 additions & 0 deletions packages/ruleset/test/rules/integer-attributes.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -464,5 +464,69 @@ describe(`Spectral rule: ${ruleId}`, () => {
expect(results[i].path.join('.')).toBe(expectedPaths[i]);
}
});
it('Integer schema int32 minimum is out of safe range', async () => {
const testDocument = makeCopy(rootDocument);
testDocument.paths['/v1/movies'].post.parameters = [
{
name: 'max_movie_length',
in: 'query',
schema: {
type: 'integer',
format: 'int32',
minimum: -9007199254740991,
maximum: 2147483649,
},
},
];

const results = await testRule(ruleId, rule, testDocument);
expect(results).toHaveLength(2);

const expectedPath = 'paths./v1/movies.post.parameters.0.schema';

const expectedMessages = [
`'minimum' value is out of safe range`,
`'maximum' value is out of safe range`,
];

for (let i = 0; i < results.length; i++) {
expect(results[i].code).toBe(ruleId);
expect(results[i].message).toBe(expectedMessages[i]);
expect(results[i].severity).toBe(expectedSeverity);
expect(results[i].path.join('.')).toBe(expectedPath);
}
});
it('Integer schema int64 minimum is out of safe range', async () => {
const testDocument = makeCopy(rootDocument);
testDocument.paths['/v1/movies'].post.parameters = [
{
name: 'max_movie_length',
in: 'query',
schema: {
type: 'integer',
format: 'int64',
minimum: -9007199254740992,
maximum: -9007199254740992,
},
},
];

const results = await testRule(ruleId, rule, testDocument);
expect(results).toHaveLength(2);

const expectedPath = 'paths./v1/movies.post.parameters.0.schema';

const expectedMessages = [
`'minimum' value is out of safe range`,
`'maximum' value is out of safe range`,
];

for (let i = 0; i < results.length; i++) {
expect(results[i].code).toBe(ruleId);
expect(results[i].message).toBe(expectedMessages[i]);
expect(results[i].severity).toBe(expectedSeverity);
expect(results[i].path.join('.')).toBe(expectedPath);
}
});
});
});