Repository navigation
fix: std.format %c rejects multi-character strings - #1015
Merged
stephenamar-db merged 2 commits intoJun 24, 2026
Merged
Conversation
Motivation: The %c format specifier should only accept a single-character string or a numeric codepoint. sjsonnet silently accepted multi-character strings (e.g. "%c" % "AB" → "AB"), while C++ jsonnet, go-jsonnet, and jrsonnet all correctly reject them with an error. Modification: - Format.scala: When %c receives a Val.Str, validate it contains exactly 1 codepoint. Raise "%c expected 1-sized string got: N" if the codepoint count is != 1, matching C++ jsonnet's error format. Result: "%c" % "AB" now correctly errors instead of silently returning "AB". Cross-implementation comparison: | Expression | C++ jsonnet | go-jsonnet | jrsonnet | sjsonnet (before) | sjsonnet (after) | |-------------------|-----------------------|------------|------------------------------|-------------------|-----------------------------| | "%c" % "A" | "A" | "A" | "A" | "A" | "A" | | "%c" % "AB" | ERROR: 1-sized string | ERROR | ERROR: 1 char string got 2 | "AB" ❌ | ERROR: 1-sized string ✅ | | "%c" % "" | ERROR | ERROR | ERROR: 1 char string got 0 | "" ❌ | ERROR: 1-sized string ✅ | | "%c" % 65 | "A" | "A" | "A" | "A" | "A" | | "%c" % "世" | "世" | "世" | "世" | "世" | "世" |
stephenamar-db
approved these changes
Jun 24, 2026
4 tasks done
He-Pin
added a commit
to He-Pin/sjsonnet
that referenced
this pull request
Jun 24, 2026
…ged code behavior PR databricks#1022 added format_c error test files (intended as part of PR databricks#1015's %c validation coverage). However, PR databricks#1022's CI ran at 08:07 UTC, before PR databricks#1015 was merged at 16:51 UTC. The golden files were generated from code without %c rejection, so they contained success output instead of error messages. Two minutes after databricks#1015 merged, databricks#1022 was squash-merged — the stale golden files entered master without a CI re-run on the combined state. Fix both golden files to contain the actual sjsonnet.Error output: - error.format_c_multichar.jsonnet.golden: "AB" → error message - error.format_c_empty_string.jsonnet.golden: "" → error message
stephenamar-db
pushed a commit
that referenced
this pull request
Jun 24, 2026
…ehavior (#1031) ## Summary PR #1022 added format_c error test files intended as part of PR #1015 `%c` validation coverage. However, PR #1022 CI ran at 08:07 UTC, before PR #1015 was merged at 16:51 UTC. The golden files were generated from code without `%c` rejection, so they contained success output instead of error messages. Two minutes after #1015 merged, #1022 was squash-merged. The stale golden files entered master without a CI re-run on the combined state. ## Timeline ``` 08:07 PR #1022 CI runs, master has NO %c rejection code "%c" % "" outputs "" golden correct at this time "%c" % "AB" outputs "AB" golden correct at this time CI all green 16:51 PR #1015 merged, %c rejection code enters master 16:53 PR #1022 merged, stale golden files enter master with no CI re-run After All PRs branch from master with both %c rejection and stale goldens "%c" % "" errors, golden "" is now wrong "%c" % "AB" errors, golden "AB" is now wrong ``` ## Fix Update both golden files to contain the actual `sjsonnet.Error` output: | File | Before stale | After correct | |---|---|---| | `error.format_c_multichar.jsonnet.golden` | `"AB"` | `sjsonnet.Error: [std.format] %c expected 1-sized string got: 2` | | `error.format_c_empty_string.jsonnet.golden` | `""` | `sjsonnet.Error: [std.format] %c expected 1-sized string got: 0` | ## Implementation behavior comparison Behavior verified with go-jsonnet and jrsonnet latest local binary, `jrsonnet 0.5.0-pre99`. Both implementations reject empty and multi-character strings for `%c`, and accept single Unicode code points. | Expression | go-jsonnet 0.21.0 | jrsonnet 0.5.0-pre99 | Expected sjsonnet behavior | |---|---|---|---| | `std.format("%c", "")` | exit 1, `%c expected 1-sized string got: 0` | exit 1, `%c expected 1 char string, got 0` | exit 1, `%c expected 1-sized string got: 0` | | `std.format("%c", "AB")` | exit 1, `%c expected 1-sized string got: 2` | exit 1, `%c expected 1 char string, got 2` | exit 1, `%c expected 1-sized string got: 2` | | `std.format("%c", "A")` | exit 0, `"A"` | exit 0, `"A"` | exit 0, `"A"` | | `std.format("%c", "世")` | exit 0, `"世"` | exit 0, `"世"` | exit 0, `"世"` | | `std.format("%c", 127757)` | exit 0, `"🌍"` | exit 0, `"🌍"` | exit 0, `"🌍"` | ## Verification ``` ./mill "sjsonnet.jvm.2_13_18.test" -- "*FileTests*" Tests: 102, Passed: 102, Failed: 0 rtk ./mill "sjsonnet.jvm[3.3.7]".test.testOnly sjsonnet.FileTests Tests: 3, Passed: 3, Failed: 0 rtk ./mill "sjsonnet.jvm[3.3.7]".test SUCCESS ``` ## Test plan - [x] FileTests.new_test_suite passes with corrected golden files - [x] Full JVM Scala 3.3.7 test suite passes locally - [x] go-jsonnet and jrsonnet behavior compared for `%c` empty, multi-character, single ASCII, single Unicode, and numeric codepoint cases - [ ] CI green on all 4 build targets: js, jvm, native, wasm
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fix: std.format %c rejects multi-character strings
Motivation
The
%cformat specifier should only accept a single-character string or a numeric codepoint. sjsonnet silently accepted multi-character strings (e.g."%c" % "AB"→"AB"), while C++ jsonnet, go-jsonnet, and jrsonnet all correctly reject them.Modification
Format.scala: When%creceives aVal.Str, validate codepoint count is exactly 1 usingcodePointCount. Multi-char or empty strings raise"%c expected 1-sized string got: N", matching C++ jsonnet's error format.error.format_c_multi_char_string.jsonnet,error.format_c_empty_string.jsonnetResult
"%c" % "AB"and"%c" % ""now correctly error, matching all reference implementations."%c" % "A""A""A""A""A"✅"A"✅"%c" % "AB""AB"❌"%c" % """"❌"%c" % 65"A""A""A""A"✅"A"✅