From f433bc80c7d9ff25abacaa189c6a324fb94a772c Mon Sep 17 00:00:00 2001 From: Braden Kopenkoskey Date: Wed, 30 Oct 2024 22:54:16 -0400 Subject: [PATCH] Use ProtoDef `skipChecks` flag to allow full NBT array size support (#91) * feat: use `skipChecks` flag to allow full NBT array size support NBT arrays are allowed a length up to 32 bits, so skipping checks is necessary to allow full NBT support. https://minecraft.wiki/w/NBT_format#Binary_format * feat: add optional `options` to functions * improve: update type definitions * chore: use node-protodef dev branch * fix: `parse` callback type definition * chore: update docs * improve: remove unnecessary parameter defaults * Revert "improve: remove unnecessary parameter defaults" This reverts commit d1b29fe0de72a9e4134bf661d82d5248ec1d5fe1. * Revert "chore: update docs" This reverts commit 522459c5f17196cd4fa9394dd64f196f6c2e04dd. * Revert "fix: `parse` callback type definition" This reverts commit c599564e3db04a058f8937e3cd91b797bba6e1e3. * Revert "feat: add optional `options` to functions" This reverts commit ad494eab280cd9c8647e411865feff954d70e520. * Revert "feat: use `skipChecks` flag to allow full NBT array size support" This reverts commit 6457edb5640fcb7204cae480b3a5cc8b100ce56c. * feat: setskip checks variable * fix: properly set variable to prototype * revert: previous approach types * improve: setVariable in parse function * chore: apply lint standard * improve: simplify variable setting and don't update * chore: update docs * Revert "chore: use node-protodef dev branch" This reverts commit 867b301e39a9662b275d44aa45ee12b0ef11e32a. * fix: lint --- README.md | 10 +++++++++- nbt.js | 11 +++++++++-- typings/index.d.ts | 7 ++++++- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 365237a..d12ef77 100644 --- a/README.md +++ b/README.md @@ -58,10 +58,18 @@ Minecraft Java Edition uses big-endian format, and Bedrock uses little-endian. Returns a buffer with a serialized nbt `value`. -### parseUncompressed(data, format='big') +### parseUncompressed(data, format='big', options?= {noArraySizeCheck?: boolean}) Takes a buffer `data` and returns a parsed nbt value. +The `options` parameter is optional. When `noArraySizeCheck` is `true`, an array size check is disabled which allows for parsing of large arrays. + +### parseAs(data, type, options?= {noArraySizeCheck?: boolean}) + +Takes a buffer `data` and returns a parsed nbt value. If the buffer is gzipped, it will unzip the data first. + +The `options` parameter is optional. When `noArraySizeCheck` is `true`, an array size check is disabled which allows for parsing of large arrays. + ### simplify(nbt) diff --git a/nbt.js b/nbt.js index ed46dfd..0b827af 100644 --- a/nbt.js +++ b/nbt.js @@ -55,8 +55,11 @@ function writeUncompressed (value, proto = 'big') { return protos[proto].createPacketBuffer('nbt', value) } -function parseUncompressed (data, proto = 'big') { +function parseUncompressed (data, proto = 'big', options = {}) { if (proto === true) proto = 'little' + + protos[proto].setVariable('noArraySizeCheck', options.noArraySizeCheck) + return protos[proto].parsePacketBuffer('nbt', data, data.startOffset).data } @@ -70,7 +73,7 @@ const hasGzipHeader = function (data) { const hasBedrockLevelHeader = (data) => data[1] === 0 && data[2] === 0 && data[3] === 0 -async function parseAs (data, type) { +async function parseAs (data, type, options = {}) { if (hasGzipHeader(data)) { data = await new Promise((resolve, reject) => { zlib.gunzip(data, (error, uncompressed) => { @@ -79,7 +82,11 @@ async function parseAs (data, type) { }) }) } + + protos[type].setVariable('noArraySizeCheck', options.noArraySizeCheck) + const parsed = protos[type].parsePacketBuffer('nbt', data, data.startOffset) + parsed.metadata.buffer = data parsed.type = type return parsed diff --git a/typings/index.d.ts b/typings/index.d.ts index d91f185..855bd13 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -64,6 +64,10 @@ declare module 'prismarine-nbt'{ [TagType.LongArray]: LongArray; } + interface ParseOptions { + noArraySizeCheck?: boolean; + } + export type NBTFormat = 'big' | 'little' | 'littleVarint' export type NBT = Tags['compound'] & {name: string}; @@ -74,7 +78,8 @@ declare module 'prismarine-nbt'{ size: number } export function writeUncompressed(value: NBT, format?: NBTFormat): Buffer; - export function parseUncompressed(value: Buffer, format?: NBTFormat): NBT; + export function parseUncompressed(value: Buffer, format?: NBTFormat, options?: ParseOptions): NBT; + export function parseAs(value: Buffer, type: NBTFormat, options?: ParseOptions): Promise<{parsed: NBT, type: NBTFormat, metadata: Metadata}>; export function parse(data: Buffer, nbtType?: NBTFormat): Promise<{parsed: NBT, type: NBTFormat, metadata: Metadata}>; export function simplify(data: Tags[TagType]): any