Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error out if large (not-exactly-representable) integers are used in YAML #15102

Merged
merged 1 commit into from
Feb 14, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 2 additions & 2 deletions src/app/tests/suites/TestCluster.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -606,13 +606,13 @@ tests:
command: "writeAttribute"
attribute: "float_double"
arguments:
value: 1.7e200
value: "1.7e+200"

- label: "Read attribute DOUBLE large Value"
command: "readAttribute"
attribute: "float_double"
response:
value: 1.7e200
value: "1.7e+200"

- label: "Write attribute DOUBLE small Value"
command: "writeAttribute"
Expand Down
32 changes: 26 additions & 6 deletions src/app/zap-templates/common/ClusterTestGeneration.js
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ function parse(filename)

function printErrorAndExit(context, msg)
{
console.log(context.testName, ': ', context.label);
console.log("\nERROR:\n", context.testName, ': ', context.label);
console.log(msg);
process.exit(1);
}
Expand Down Expand Up @@ -574,22 +574,26 @@ function chip_tests_config_get_type(name, options)
// test_cluster_command_value and test_cluster_value-equals are recursive partials using #each. At some point the |global|
// context is lost and it fails. Make sure to attach the global context as a property of the | value |
// that is evaluated.
function attachGlobal(global, value)
//
// errorContext should have "thisVal" and "name" properties that will be used
// for error reporting via printErrorAndExit.
function attachGlobal(global, value, errorContext)
{
if (Array.isArray(value)) {
value = value.map(v => attachGlobal(global, v));
value = value.map(v => attachGlobal(global, v, errorContext));
} else if (value instanceof Object) {
for (key in value) {
if (key == "global") {
continue;
}
value[key] = attachGlobal(global, value[key]);
value[key] = attachGlobal(global, value[key], errorContext);
}
} else if (value === null) {
value = new NullObject();
} else {
switch (typeof value) {
case 'number':
checkNumberSanity(value, errorContext);
value = new Number(value);
break;
case 'string':
Expand All @@ -607,6 +611,21 @@ function attachGlobal(global, value)
return value;
}

/**
* Ensure the given value is not a possibly-corrupted-by-going-through-double
* integer. If it is, tell the user (using that errorContext.name to describe
* it) and die.
*/
function checkNumberSanity(value, errorContext)
{
// Number.isInteger is false for non-Numbers.
if (Number.isInteger(value) && !Number.isSafeInteger(value)) {
printErrorAndExit(errorContext.thisVal,
`${errorContext.name} value ${
value} is too large to represent exactly as an integer in YAML. Put quotes around it to treat it as a string.\n\n`);
}
}

function chip_tests_item_parameters(options)
{
const commandValues = this.arguments.values;
Expand Down Expand Up @@ -634,7 +653,8 @@ function chip_tests_item_parameters(options)
'Missing "' + commandArg.name + '" in arguments list: \n\t* '
+ commandValues.map(command => command.name).join('\n\t* '));
}
commandArg.definedValue = attachGlobal(this.global, expected.value);

commandArg.definedValue = attachGlobal(this.global, expected.value, { thisVal : this, name : commandArg.name });

return commandArg;
});
Expand Down Expand Up @@ -663,7 +683,7 @@ function chip_tests_item_response_parameters(options)
const expected = responseValues.splice(expectedIndex, 1)[0];
if ('value' in expected) {
responseArg.hasExpectedValue = true;
responseArg.expectedValue = attachGlobal(this.global, expected.value);
responseArg.expectedValue = attachGlobal(this.global, expected.value, { thisVal : this, name : responseArg.name });
}

if ('constraints' in expected) {
Expand Down