From c1a5e01a2ccfc6d8a7dcd54c9c4f72f83c058245 Mon Sep 17 00:00:00 2001 From: William Chargin Date: Thu, 7 Jun 2018 09:10:11 -0700 Subject: [PATCH] Add top-level address module error handling (#356) Summary: This commit implements all the code needed for the top-level `makeAddressModule` function, without implementing any of the address functions. This mostly comprises handling of errors in the module options. Test Plan: Unit tests added. Run `yarn travis`. wchargin-branch: address-error-handling --- src/v3/core/address.js | 28 +++++++++++++++++++++++++++- src/v3/core/address.test.js | 23 +++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/v3/core/address.js b/src/v3/core/address.js index 009849c..9069df1 100644 --- a/src/v3/core/address.js +++ b/src/v3/core/address.js @@ -1,5 +1,7 @@ // @flow +import stringify from "json-stable-stringify"; + export interface AddressModule
{ /** * Assert at runtime that the provided address is actually a valid @@ -89,7 +91,31 @@ export type Options = {| export function makeAddressModule(options: Options): AddressModule { type Address = string; // for readability and interface consistency - const _ = options; + const {name, nonce} = options; + const otherNonces = new Map(options.otherNonces || new Map()); + + const separator = "\0"; + if (nonce.indexOf(separator) !== -1) { + throw new Error(`invalid nonce (contains NUL): ${stringify(nonce)}`); + } + + const nonceWithSeparator = nonce + separator; + const otherNoncesWithSeparators = new Map(); + for (const [otherNonce, otherName] of otherNonces.entries()) { + if (otherNonce === nonce) { + throw new Error( + `primary nonce listed as otherNonce: ${stringify(nonce)}` + ); + } + if (otherNonce.indexOf(separator) !== -1) { + throw new Error( + `invalid otherNonce (contains NUL): ${stringify(otherNonce)}` + ); + } + otherNoncesWithSeparators.set(otherNonce + separator, otherName); + } + + const _ = {name, nonceWithSeparator}; function assertValid(address: Address, what?: string): void { const _ = {address, what}; diff --git a/src/v3/core/address.test.js b/src/v3/core/address.test.js index 6feb667..7d194ce 100644 --- a/src/v3/core/address.test.js +++ b/src/v3/core/address.test.js @@ -28,6 +28,29 @@ describe("core/address", () => { it("makes address modules using all the options", () => { makeModules(); }); + it("rejects a module whose nonce contains NUL", () => { + expect(() => { + makeAddressModule({name: "BadAddress", nonce: "n\0o"}); + }).toThrow("invalid nonce (contains NUL):"); + }); + it("rejects a module with `otherNonces` containing NUL", () => { + expect(() => { + makeAddressModule({ + name: "GoodAddress", + nonce: "G", + otherNonces: new Map().set("n\0o", "BadAddress"), + }); + }).toThrow("invalid otherNonce (contains NUL):"); + }); + it("rejects a module with `nonce` in `otherNonces`", () => { + expect(() => { + makeAddressModule({ + name: "GoodAddress", + nonce: "G", + otherNonces: new Map().set("G", "WatAddress"), + }); + }).toThrow("primary nonce listed as otherNonce"); + }); it("returns an object with read-only properties", () => { const {FooAddress} = makeModules(); expect(() => {