From f73afc52445c238de6cb20819fad8ec753b69d81 Mon Sep 17 00:00:00 2001 From: Franck Royer Date: Tue, 1 Mar 2022 16:51:21 +1100 Subject: [PATCH 1/2] Handle errors thrown when converting to utf-8 --- CHANGELOG.md | 4 +++ src/lib/discovery/dns.ts | 53 ++++++++++++++++------------- src/lib/discovery/dns_over_https.ts | 8 +++++ src/lib/enr/enr.ts | 9 ++++- src/lib/waku_message/index.ts | 7 +++- 5 files changed, 56 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5b91fb731..e5584314ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- Handle errors thrown by `bytesToUtf8`. + ## [0.18.0] - 2022-02-24 ### Changed diff --git a/src/lib/discovery/dns.ts b/src/lib/discovery/dns.ts index d6d5cba6d7..96329f2506 100644 --- a/src/lib/discovery/dns.ts +++ b/src/lib/discovery/dns.ts @@ -79,38 +79,45 @@ export class DnsNodeDiscovery { subdomain: string, context: SearchContext ): Promise { - const entry = await this._getTXTRecord(subdomain, context); - context.visits[subdomain] = true; - - let next: string; - let branches: string[]; - - const entryType = getEntryType(entry); try { - switch (entryType) { - case ENRTree.ROOT_PREFIX: - next = ENRTree.parseAndVerifyRoot(entry, context.publicKey); - return await this._search(next, context); - case ENRTree.BRANCH_PREFIX: - branches = ENRTree.parseBranch(entry); - next = selectRandomPath(branches, context); - return await this._search(next, context); - case ENRTree.RECORD_PREFIX: - return ENR.decodeTxt(entry); - default: - return null; + const entry = await this._getTXTRecord(subdomain, context); + context.visits[subdomain] = true; + + let next: string; + let branches: string[]; + + const entryType = getEntryType(entry); + try { + switch (entryType) { + case ENRTree.ROOT_PREFIX: + next = ENRTree.parseAndVerifyRoot(entry, context.publicKey); + return await this._search(next, context); + case ENRTree.BRANCH_PREFIX: + branches = ENRTree.parseBranch(entry); + next = selectRandomPath(branches, context); + return await this._search(next, context); + case ENRTree.RECORD_PREFIX: + return ENR.decodeTxt(entry); + default: + return null; + } + } catch (error) { + dbg( + `Failed to search DNS tree ${entryType} at subdomain ${subdomain}: ${error}` + ); + return null; } } catch (error) { - dbg( - `Failed to search DNS tree ${entryType} at subdomain ${subdomain}: ${error}` - ); + dbg(`Failed to retrieve TXT record at subdomain ${subdomain}: ${error}`); return null; } } /** * Retrieves the TXT record stored at a location from either - * this DNS tree cache or via DNS query + * this DNS tree cache or via DNS query. + * + * @throws if the TXT Record contains non-UTF-8 values. */ private async _getTXTRecord( subdomain: string, diff --git a/src/lib/discovery/dns_over_https.ts b/src/lib/discovery/dns_over_https.ts index f339095ae0..97f57b2cba 100644 --- a/src/lib/discovery/dns_over_https.ts +++ b/src/lib/discovery/dns_over_https.ts @@ -31,6 +31,14 @@ export class DnsOverHttps implements DnsClient { public endpoints: Endpoints = [cloudflare, google, opendns] ) {} + /** + * Resolves a TXT record + * + * @param domain The domain name + * + * @throws if the result is provided in byte form which cannot be decoded + * to UTF-8 + */ async resolveTXT(domain: string): Promise { const response = await query({ questions: [{ type: "TXT", name: domain }], diff --git a/src/lib/enr/enr.ts b/src/lib/enr/enr.ts index d20e94c6af..c352f07a2e 100644 --- a/src/lib/enr/enr.ts +++ b/src/lib/enr/enr.ts @@ -1,4 +1,5 @@ import * as RLP from "@ethersproject/rlp"; +import debug from "debug"; import { Multiaddr, protocols } from "multiaddr"; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore: No types available @@ -21,6 +22,8 @@ import { decodeMultiaddrs, encodeMultiaddrs } from "./multiaddrs_codec"; import { ENRKey, ENRValue, NodeId, SequenceNumber } from "./types"; import * as v4 from "./v4"; +const dbg = debug("waku:enr"); + export class ENR extends Map { public static readonly RECORD_PREFIX = "enr:"; public seq: SequenceNumber; @@ -78,7 +81,11 @@ export class ENR extends Map { } const obj: Record = {}; for (let i = 0; i < kvs.length; i += 2) { - obj[bytesToUtf8(kvs[i])] = kvs[i + 1]; + try { + obj[bytesToUtf8(kvs[i])] = kvs[i + 1]; + } catch (e) { + dbg("Failed to decode ENR key to UTF-8, skipping it", kvs[i], e); + } } const enr = new ENR(obj, BigInt("0x" + bytesToHex(seq)), signature); diff --git a/src/lib/waku_message/index.ts b/src/lib/waku_message/index.ts index fa7b56902e..c31caa461a 100644 --- a/src/lib/waku_message/index.ts +++ b/src/lib/waku_message/index.ts @@ -256,7 +256,12 @@ export class WakuMessage { return ""; } - return bytesToUtf8(this.proto.payload); + try { + return bytesToUtf8(this.proto.payload); + } catch (e) { + dbg("Could not decode byte as UTF-8", e); + return ""; + } } get payload(): Uint8Array | undefined { From 067ebebdf08f241a4f9821730f4273bc10500ee6 Mon Sep 17 00:00:00 2001 From: Franck Royer Date: Tue, 1 Mar 2022 16:52:31 +1100 Subject: [PATCH 2/2] Remove unnecessary log As it is unlikely to decode as utf-8. --- examples/web-chat/src/Message.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/examples/web-chat/src/Message.ts b/examples/web-chat/src/Message.ts index ba225f7846..36407e4fda 100644 --- a/examples/web-chat/src/Message.ts +++ b/examples/web-chat/src/Message.ts @@ -19,11 +19,7 @@ export class Message { return new Message(chatMsg, wakuMsg.timestamp); } } catch (e) { - console.error( - "Failed to decode chat message", - wakuMsg.payloadAsUtf8, - e - ); + console.error("Failed to decode chat message", e); } } return;