From 212686baae410d3a4d2adceba90363794579c96b Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Wed, 8 May 2024 12:20:43 -0400 Subject: [PATCH] fix: better error handling for the binary codec (#2693) * better error handling * respond to comments * remove --watch --- .vscode/settings.json | 2 +- packages/ripple-binary-codec/HISTORY.md | 3 +++ packages/ripple-binary-codec/src/serdes/binary-parser.ts | 8 ++++++-- packages/ripple-binary-codec/src/types/blob.ts | 3 +++ packages/ripple-binary-codec/src/types/st-array.ts | 8 +++++++- packages/ripple-binary-codec/test/binary-parser.test.ts | 6 +++--- 6 files changed, 23 insertions(+), 7 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 5dc2e1cf..ef2c734c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -39,7 +39,7 @@ "enable": true }, "editor.codeActionsOnSave": { - "source.fixAll.eslint": true + "source.fixAll.eslint": "explicit" }, "files.insertFinalNewline": true, "files.trimFinalNewlines": true, diff --git a/packages/ripple-binary-codec/HISTORY.md b/packages/ripple-binary-codec/HISTORY.md index 6ba00b82..fdf9ecb3 100644 --- a/packages/ripple-binary-codec/HISTORY.md +++ b/packages/ripple-binary-codec/HISTORY.md @@ -2,6 +2,9 @@ ## Unreleased +### Fixed +* Better error handling/error messages for serialization/deserialization errors. + ## 2.0.0 (2024-02-01) ### BREAKING CHANGES diff --git a/packages/ripple-binary-codec/src/serdes/binary-parser.ts b/packages/ripple-binary-codec/src/serdes/binary-parser.ts index 007fe71f..8fb789dd 100644 --- a/packages/ripple-binary-codec/src/serdes/binary-parser.ts +++ b/packages/ripple-binary-codec/src/serdes/binary-parser.ts @@ -144,14 +144,18 @@ class BinaryParser { if (type === 0) { type = this.readUInt8() if (type === 0 || type < 16) { - throw new Error('Cannot read FieldOrdinal, type_code out of range') + throw new Error( + `Cannot read FieldOrdinal, type_code ${type} out of range`, + ) } } if (nth === 0) { nth = this.readUInt8() if (nth === 0 || nth < 16) { - throw new Error('Cannot read FieldOrdinal, field_code out of range') + throw new Error( + `Cannot read FieldOrdinal, field_code ${nth} out of range`, + ) } } diff --git a/packages/ripple-binary-codec/src/types/blob.ts b/packages/ripple-binary-codec/src/types/blob.ts index 3d7f26d0..36bd93f9 100644 --- a/packages/ripple-binary-codec/src/types/blob.ts +++ b/packages/ripple-binary-codec/src/types/blob.ts @@ -33,6 +33,9 @@ class Blob extends SerializedType { } if (typeof value === 'string') { + if (!/^[A-F0-9]*$/iu.test(value)) { + throw new Error('Cannot construct Blob from a non-hex string') + } return new Blob(hexToBytes(value)) } diff --git a/packages/ripple-binary-codec/src/types/st-array.ts b/packages/ripple-binary-codec/src/types/st-array.ts index 1b50f3e2..c705d4d8 100644 --- a/packages/ripple-binary-codec/src/types/st-array.ts +++ b/packages/ripple-binary-codec/src/types/st-array.ts @@ -14,7 +14,13 @@ const OBJECT_END_MARKER = Uint8Array.from([0xe1]) */ function isObjects(args): args is Array { return ( - Array.isArray(args) && (args.length === 0 || typeof args[0] === 'object') + Array.isArray(args) && + args.every( + (arg) => + typeof arg === 'object' && + Object.keys(arg).length === 1 && + typeof Object.values(arg)[0] === 'object', + ) ) } diff --git a/packages/ripple-binary-codec/test/binary-parser.test.ts b/packages/ripple-binary-codec/test/binary-parser.test.ts index eef94c4f..60b3fa11 100644 --- a/packages/ripple-binary-codec/test/binary-parser.test.ts +++ b/packages/ripple-binary-codec/test/binary-parser.test.ts @@ -238,19 +238,19 @@ function fieldParsingTests() { it('Field throws when type code out of range', () => { const parser = makeParser('0101') expect(() => parser.readField()).toThrow( - new Error('Cannot read FieldOrdinal, type_code out of range'), + new Error('Cannot read FieldOrdinal, type_code 1 out of range'), ) }) it('Field throws when field code out of range', () => { const parser = makeParser('1001') expect(() => parser.readFieldOrdinal()).toThrow( - new Error('Cannot read FieldOrdinal, field_code out of range'), + new Error('Cannot read FieldOrdinal, field_code 1 out of range'), ) }) it('Field throws when both type and field code out of range', () => { const parser = makeParser('000101') expect(() => parser.readFieldOrdinal()).toThrow( - new Error('Cannot read FieldOrdinal, type_code out of range'), + new Error('Cannot read FieldOrdinal, type_code 1 out of range'), ) }) it('readUIntN', () => {