Skip to content

feat(common/lib/utils): catch error on bad b64 string inputs; add tests #222

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 25 additions & 10 deletions src/common/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import * as B64js from "base64-js";

class UtilsError extends Error {
constructor(...args: ConstructorParameters<typeof Error>) {
super(...args);
this.name = "UtilsError";
}
}

export type Base64UrlString = string;

export function concatBuffers(
Expand Down Expand Up @@ -56,17 +63,25 @@ export function bufferTob64Url(buffer: Uint8Array): string {
}

export function b64UrlEncode(b64UrlString: string): string {
return b64UrlString
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/\=/g, "");
try {
return b64UrlString
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/\=/g, "");
} catch (error) {
throw new UtilsError("Failed to encode string", { cause: error });
}
}

export function b64UrlDecode(b64UrlString: string): string {
b64UrlString = b64UrlString.replace(/\-/g, "+").replace(/\_/g, "/");
let padding;
b64UrlString.length % 4 == 0
? (padding = 0)
: (padding = 4 - (b64UrlString.length % 4));
return b64UrlString.concat("=".repeat(padding));
try {
b64UrlString = b64UrlString.replace(/\-/g, "+").replace(/\_/g, "/");
let padding;
b64UrlString.length % 4 == 0
? (padding = 0)
: (padding = 4 - (b64UrlString.length % 4));
return b64UrlString.concat("=".repeat(padding));
} catch (error) {
throw new UtilsError("Failed to decode string", { cause: error });
}
}
64 changes: 64 additions & 0 deletions test/common/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import * as chai from "chai";
import * as utils from "../../../src/common/lib/utils";

const expect = chai.expect;

describe("Common Utils", function () {
describe("b64UrlDecode()", () => {
for (const testCase of b64UrlDecodeValues()) {
it(`should throw an error on non-strings: ${testCase.value}`, () => {
try {
// @ts-ignore Ignoring to test non-strings
utils.b64UrlDecode(testCase.value);
} catch (error) {
expect(error).to.have.property("message");
expect(error).to.have.property("cause");
expect((error as Error).name).to.be.string("UtilsError");
expect((error as Error).message).to.be.string(testCase.message);
}
});
}
});

describe("b64UrlEncode()", () => {
for (const testCase of b64UrlEncodeValues()) {
it(`should throw an error on non-strings: ${testCase.value}`, () => {
try {
// @ts-ignore Ignoring to test non-strings
utils.b64UrlEncode(testCase.value);
} catch (error) {
expect(error).to.have.property("message");
expect(error).to.have.property("cause");
expect((error as Error).name).to.be.string("UtilsError");
expect((error as Error).message).to.be.string(testCase.message);
}
});
}
});
});

function b64UrlDecodeValues() {
return [
{ value: false, message: "Failed to decode string" },
{ value: undefined, message: "Failed to decode string" },
{ value: null, message: "Failed to decode string" },
{ value: true, message: "Failed to decode string" },
{ value: {}, message: "Failed to decode string" },
{ value: { test: "hello" }, message: "Failed to decode string" },
{ value: [], message: "Failed to decode string" },
{ value: ["1"], message: "Failed to decode string" },
];
}

function b64UrlEncodeValues() {
return [
{ value: false, message: "Failed to encode string" },
{ value: undefined, message: "Failed to encode string" },
{ value: null, message: "Failed to encode string" },
{ value: true, message: "Failed to encode string" },
{ value: {}, message: "Failed to encode string" },
{ value: { test: "hello" }, message: "Failed to encode string" },
{ value: [], message: "Failed to encode string" },
{ value: ["1"], message: "Failed to encode string" },
];
}