Skip to content

Commit b443feb

Browse files
goffrieConvex, Inc.
authored and
Convex, Inc.
committed
Allow non-canonical base64 in atob (#37208)
Per the spec this should be a "forgiving" base64 decode that allows trailing bits. GitOrigin-RevId: fce133bab077101cab458ffb6b0d85b135334c8d
1 parent 4f21209 commit b443feb

File tree

2 files changed

+14
-5
lines changed

2 files changed

+14
-5
lines changed

crates/isolate/src/ops/text.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,21 @@ pub fn op_atob<'b, P: OpProvider<'b>>(
3232
encoded: String,
3333
) -> anyhow::Result<JsonValue> {
3434
let mut encoded = encoded;
35+
// https://infra.spec.whatwg.org/#forgiving-base64
3536
encoded.retain(|c| !c.is_ascii_whitespace());
36-
let bytes = match base64::decode(encoded) {
37+
// Per forgiving-base64 we need to allow trailing bits.
38+
// This is a bit *too* forgiving since this version of base64 allows
39+
// improper padding like in "39=", whereas the specification says that
40+
// should be an error.
41+
let bytes = match base64::decode_config(
42+
encoded,
43+
base64::STANDARD_NO_PAD.decode_allow_trailing_bits(true),
44+
) {
3745
Ok(bytes) => bytes,
3846
Err(err) => return Ok(json!({ "error": err.to_string() })),
3947
};
4048

41-
let decoded: String = bytes
42-
.into_iter()
43-
.map(|c| std::char::from_u32(c as u32).expect("all u8s are valid characters"))
44-
.collect();
49+
let decoded: String = bytes.into_iter().map(char::from).collect();
4550
Ok(json!({ "decoded": decoded }))
4651
}
4752

npm-packages/udf-tests/convex/js_builtins/textEncoder.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ function atobSuccess() {
1717
assert.strictEqual(decoded, "hello world");
1818
const latin1 = String.fromCharCode(151);
1919
assert.strictEqual(atob("lw=="), latin1);
20+
// allow non-canonical encodings (proper encoding of "C" should be "Qw==")
21+
assert.strictEqual(atob("Qx=="), "C");
22+
// allow improper padding (even though the spec says this should error)
23+
assert.strictEqual(atob("Qx="), "C");
2024
}
2125

2226
function atobWithAsciiWhitespace() {

0 commit comments

Comments
 (0)