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(() => {