Skip to content

Commit

Permalink
Correctly transform base64 with multiple instances of + or / (#4252)
Browse files Browse the repository at this point in the history
String.replace only replaces a single instance of the search pattern by default; we need a regex in g mode if we want to replace them all.
  • Loading branch information
robintown authored Jun 18, 2024
1 parent c55289e commit b1701ff
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 6 deletions.
9 changes: 5 additions & 4 deletions spec/unit/base64.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,18 @@ describe.each(["browser", "node"])("Base64 encoding (%s)", (env) => {
});

it("Should encode unpadded URL-safe base64", () => {
const toEncode = "?????";
// Chosen to have padding and multiple instances of / and + in the base64
const toEncode = "???????⊕⊗⊗";
const data = new TextEncoder().encode(toEncode);

const encoded = encodeUnpaddedBase64Url(data);
expect(encoded).toEqual("Pz8_Pz8");
expect(encoded).toEqual("Pz8_Pz8_P-KKleKKl-KKlw");
});

it("Should decode URL-safe base64", () => {
const decoded = new TextDecoder().decode(decodeBase64("Pz8_Pz8="));
const decoded = new TextDecoder().decode(decodeBase64("Pz8_Pz8_P-KKleKKl-KKlw=="));

expect(decoded).toStrictEqual("?????");
expect(decoded).toStrictEqual("???????⊕⊗⊗");
});

it("Encode unpadded should not have padding", () => {
Expand Down
4 changes: 2 additions & 2 deletions src/base64.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export function encodeUnpaddedBase64(uint8Array: ArrayBuffer | Uint8Array): stri
* @returns The unpadded base64.
*/
export function encodeUnpaddedBase64Url(uint8Array: ArrayBuffer | Uint8Array): string {
return encodeUnpaddedBase64(uint8Array).replace("+", "-").replace("/", "_");
return encodeUnpaddedBase64(uint8Array).replace(/\+/g, "-").replace(/\//g, "_");
}

/**
Expand All @@ -75,7 +75,7 @@ export function decodeBase64(base64: string): Uint8Array {
const itFunc = function* (): Generator<number> {
const decoded = atob(
// built-in atob doesn't support base64url: convert so we support either
base64.replace("-", "+").replace("_", "/"),
base64.replace(/-/g, "+").replace(/_/g, "/"),
);
for (let i = 0; i < decoded.length; ++i) {
yield decoded.charCodeAt(i);
Expand Down

0 comments on commit b1701ff

Please sign in to comment.