From 651f600ecad45c564d7b147c6480664c1848bdd5 Mon Sep 17 00:00:00 2001 From: RKS Date: Tue, 8 Sep 2026 10:54:30 -0400 Subject: [PATCH] fix: reject non-integer dynamic format arguments --- stdlib/std.jsonnet | 10 ++++++++-- test_suite/error.format.non_integer.jsonnet | 1 + .../error.format.non_integer.jsonnet.golden_regex | 1 + test_suite/error.format.non_integer_precision.jsonnet | 1 + ...r.format.non_integer_precision.jsonnet.golden_regex | 1 + 5 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 test_suite/error.format.non_integer.jsonnet create mode 100644 test_suite/error.format.non_integer.jsonnet.golden_regex create mode 100644 test_suite/error.format.non_integer_precision.jsonnet create mode 100644 test_suite/error.format.non_integer_precision.jsonnet.golden_regex diff --git a/stdlib/std.jsonnet b/stdlib/std.jsonnet index 9eee818ff..32e177781 100644 --- a/stdlib/std.jsonnet +++ b/stdlib/std.jsonnet @@ -720,6 +720,12 @@ limitations under the License. else error 'Unknown code: ' + code.ctype; + local validate_dynamic_format_arg(name, value) = + if std.isInteger(value) then + value + else + error 'Format ' + name + ' must be an integer, got ' + std.type(value); + // Render a parsed format string with an array of values. local format_codes_arr(codes, arr, i, j, v) = if i >= std.length(codes) then @@ -737,7 +743,7 @@ limitations under the License. fw: if j >= std.length(arr) then error ('Not enough values to format: ' + std.length(arr) + ', expected at least ' + j) else - arr[j], + validate_dynamic_format_arg('width', arr[j]), } else { j: j, fw: code.fw, @@ -747,7 +753,7 @@ limitations under the License. prec: if tmp.j >= std.length(arr) then error ('Not enough values to format: ' + std.length(arr) + ', expected at least ' + tmp.j) else - arr[tmp.j], + validate_dynamic_format_arg('precision', arr[tmp.j]), } else { j: tmp.j, prec: code.prec, diff --git a/test_suite/error.format.non_integer.jsonnet b/test_suite/error.format.non_integer.jsonnet new file mode 100644 index 000000000..d972136fa --- /dev/null +++ b/test_suite/error.format.non_integer.jsonnet @@ -0,0 +1 @@ +std.format('%*d', [2.5, 42]) diff --git a/test_suite/error.format.non_integer.jsonnet.golden_regex b/test_suite/error.format.non_integer.jsonnet.golden_regex new file mode 100644 index 000000000..1af8e80d2 --- /dev/null +++ b/test_suite/error.format.non_integer.jsonnet.golden_regex @@ -0,0 +1 @@ +RUNTIME ERROR: Format width must be an integer, got number diff --git a/test_suite/error.format.non_integer_precision.jsonnet b/test_suite/error.format.non_integer_precision.jsonnet new file mode 100644 index 000000000..986b6499a --- /dev/null +++ b/test_suite/error.format.non_integer_precision.jsonnet @@ -0,0 +1 @@ +std.format('%.*f', [2.5, 1.234]) diff --git a/test_suite/error.format.non_integer_precision.jsonnet.golden_regex b/test_suite/error.format.non_integer_precision.jsonnet.golden_regex new file mode 100644 index 000000000..5d84b9182 --- /dev/null +++ b/test_suite/error.format.non_integer_precision.jsonnet.golden_regex @@ -0,0 +1 @@ +RUNTIME ERROR: Format precision must be an integer, got number