fix: std.base64 rejects string codepoints outside byte range - #1008
fix: std.base64 rejects string codepoints outside byte range#1008He-Pin wants to merge 1 commit into
Conversation
Motivation: The Jsonnet standard library defines std.base64 input as a string or an array whose codepoints or numbers are in the 0 to 255 range. sjsonnet already rejected out-of-range array values, but the string path passed every non-ASCII string to PlatformBase64 and UTF-8 encoded invalid codepoints instead of reporting an error. Modification: Validate non-AsciiSafeStr string inputs codepoint-by-codepoint before encoding and fail on the first codepoint above 255. Keep the existing ASCII fast path and existing UTF-8 behavior for in-range non-ASCII codepoints. Update Scala tests and file-test fixtures, including the official go_test_suite high-codepoint case, to cover the rejection behavior across JVM, JS, and Native file-test harnesses. Result: std.base64 now rejects string inputs outside the byte-string domain while preserving existing behavior for valid inputs and fast ASCII strings.
95e6c61 to
44cbec4
Compare
|
Didn't we agree that the official behavior is incorrect here? #793 (comment) |
|
If you want to limit the codepoint range - then the limit should be 127, and not 255: #793 (comment) |
|
Thank you for the reminder. @CertainLach |
|
Closing this PR. I re-read #793 and the latest comments here. This PR was based on a strict reading of the current stdlib wording / go-jsonnet's high-codepoint rejection, but it conflicts with the The patch also leaves us in a hybrid state: it rejects codepoints >255 while still UTF-8-encoding codepoints in 128..255, so it neither fully matches official C++ Jsonnet's codepoint- Any future change here should be a separate policy PR after consensus, likely either preserving UTF-8 semantics explicitly or moving to an ASCII-only restriction for string input. |
|
@CertainLach, would you do a final release of jrsonnet soon? |
Motivation
std.base64(input)accepts string or array inputs, but the Jsonnet stdlib defines the input domain as codepoints/numbers in[0, 255].sjsonnet already validated array elements, but string input had a gap: non-ASCII strings went straight to
PlatformBase64, so codepoints above255were UTF-8 encoded instead of rejected. The observable bug isstd.base64(std.char(256)): before this PR sjsonnet returned"xIA=", while go-jsonnet rejects the input withgot 256.This PR is intentionally scoped to that validation gap. It does not change the existing in-range string encoding behavior for
[128, 255]; local checks showstd.base64(std.char(233))remains"w6k=", matching go-jsonnet 0.22.0 and jrsonnet 0.5.0-pre99.Modification
validateBase64StringCodepointsinEncodingModule.scalaand call it for non-Val.AsciiSafeStrstring inputs before encoding.255with:base64 encountered invalid codepoint value in the string (must be 0 <= X <= 255), got <value>.Val.AsciiSafeStrfast path unchanged; those values are known to be printable ASCII-safe and therefore in range.[128, 255].Base64Tests.scalafor CJK, emoji, large non-ASCII rejection, and in-range non-ASCII roundtrip.go_test_suite/builtinBase64_string_high_codepoint.jsonnetin JVM/Native and JS file tests, and update its golden output.new_test_suitefixtures forstd.char(256)and a mid-string out-of-range codepoint.Result
std.base64now rejects string inputs outside the byte-string domain, aligning the out-of-range behavior with the Jsonnet stdlib contract and the go-jsonnet high-codepoint fixture, while preserving valid ASCII and in-range non-ASCII behavior.Behavior comparison:
std.base64("hello")"aGVsbG8=""aGVsbG8=""aGVsbG8=""aGVsbG8="std.base64(std.char(0))"AA==""AA==""AA==""AA=="std.base64(std.char(233))"w6k=""w6k=""w6k=""w6k="std.base64(std.char(255))"w78=""w78=""w78=""w78="std.base64(std.char(256))"xIA="got 256got 256"xIA="std.base64(std.char(19990))got 19990got 19990The intended behavior change is limited to string codepoints above
255. Valid ASCII and in-range non-ASCII cases remain unchanged.Verification:
./mill sjsonnet.jvm.3_3_7.reformatpassed../mill sjsonnet.jvm.3_3_7.testpassed: 143/143../mill sjsonnet.js.3_3_7.testpassed: 475/475../mill sjsonnet.native.3_3_7.testpassed: 488/488.std.base64(std.char(233))remains"w6k=".std.base64(std.char(256))fails withgot 256.44cbec46 fix: std.base64 rejects string codepoints outside byte range.References
std.base64: https://jsonnet.org/ref/stdlib.html#std-base64std.char(233)=>"w6k=",std.char(256)=> error.std.char(233)=>"w6k=",std.char(256)=>"xIA=".