Skip to content

Commit

Permalink
End of Buffer Error
Browse files Browse the repository at this point in the history
Been chewing on this for the last few days for some reason. I think the error message wasn't quite what I wanted it to be, so I wasn't ready to commit it to the repo just yet. I like this error message now, as it's more clear what happened, but also not overly-verbose, which is what I didn't like about the error messages I had made so far.

This essentially checks if the `NBTReader`'s reading `#byteOffset` is longer than the source `Uint8Array`'s length, which would mean that it can't read any more data, since it's read up to the end of the buffer. This puts a little roadblock before showing any confusing `DataView` errors, which aren't as apparent as to what went wrong. These should help make things more visible to the user, if something is wrong with the data, or if they are reading in the wrong format.

I'm gonna do some more testing after getting this initial version for these errors up, and maybe moving the error back a little bit, to where the `#byteOffset` is incremented to a value higher than the buffer length. This would make the error show up sooner while reading the data, as it would make the error-prone next read exclusive, rather than inclusive. In other words, instead of throwing the error when it tries to read at an il-formatted offset, it will throw when the offset is set to that il-formatted length.

I just keep flip-flopping on how the errors should be (I seem to do this a lot with the JSDoc annotations too), so I have to commit something now, or else I'll just keep working on this derpy little fix forever, for some reason, aaah! XD
  • Loading branch information
Offroaders123 committed Dec 12, 2022
1 parent 2e042b5 commit ca05acd
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 3 deletions.
32 changes: 30 additions & 2 deletions src/read.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,6 @@ export class NBTReader {
const remaining = this.#data.byteLength - this.#byteOffset;
throw new Error(`Encountered unexpected End tag at byte offset ${this.#byteOffset}, ${remaining} unread bytes remaining`);
}

case TAG.BYTE: return new Byte(this.#readByte());
case TAG.SHORT: return new Short(this.#readShort());
case TAG.INT: return new Int(this.#readInt());
Expand All @@ -171,7 +170,6 @@ export class NBTReader {
case TAG.COMPOUND: return this.#readCompound();
case TAG.INT_ARRAY: return this.#readIntArray();
case TAG.LONG_ARRAY: return this.#readLongArray();

default: throw new Error(`Encountered unsupported tag type ${type} at byte offset ${this.#byteOffset}`);
}
}
Expand All @@ -181,62 +179,92 @@ export class NBTReader {
}

#readUnsignedByte() {
if (this.#byteOffset + 1 > this.#data.byteLength){
throw new Error("Ran out of bytes to read, unexpectedly reached the end of the buffer");
}
const value = this.#view.getUint8(this.#byteOffset);
this.#byteOffset += 1;
return value;
}

#readByte() {
if (this.#byteOffset + 1 > this.#data.byteLength){
throw new Error("Ran out of bytes to read, unexpectedly reached the end of the buffer");
}
const value = this.#view.getInt8(this.#byteOffset);
this.#byteOffset += 1;
return value;
}

#readUnsignedShort() {
if (this.#byteOffset + 2 > this.#data.byteLength){
throw new Error("Ran out of bytes to read, unexpectedly reached the end of the buffer");
}
const value = this.#view.getUint16(this.#byteOffset,this.#littleEndian);
this.#byteOffset += 2;
return value;
}

#readShort() {
if (this.#byteOffset + 2 > this.#data.byteLength){
throw new Error("Ran out of bytes to read, unexpectedly reached the end of the buffer");
}
const value = this.#view.getInt16(this.#byteOffset,this.#littleEndian);
this.#byteOffset += 2;
return value;
}

#readInt() {
if (this.#byteOffset + 4 > this.#data.byteLength){
throw new Error("Ran out of bytes to read, unexpectedly reached the end of the buffer");
}
const value = this.#view.getInt32(this.#byteOffset,this.#littleEndian);
this.#byteOffset += 4;
return value;
}

#readLong() {
if (this.#byteOffset + 8 > this.#data.byteLength){
throw new Error("Ran out of bytes to read, unexpectedly reached the end of the buffer");
}
const value = this.#view.getBigInt64(this.#byteOffset,this.#littleEndian);
this.#byteOffset += 8;
return value;
}

#readFloat() {
if (this.#byteOffset + 4 > this.#data.byteLength){
throw new Error("Ran out of bytes to read, unexpectedly reached the end of the buffer");
}
const value = this.#view.getFloat32(this.#byteOffset,this.#littleEndian);
this.#byteOffset += 4;
return value;
}

#readDouble() {
if (this.#byteOffset + 8 > this.#data.byteLength){
throw new Error("Ran out of bytes to read, unexpectedly reached the end of the buffer");
}
const value = this.#view.getFloat64(this.#byteOffset,this.#littleEndian);
this.#byteOffset += 8;
return value;
}

#readByteArray() {
const byteLength = this.#readInt();
if (this.#byteOffset + byteLength > this.#data.byteLength){
throw new Error("Ran out of bytes to read, unexpectedly reached the end of the buffer");
}
const value = new Int8Array(this.#data.subarray(this.#byteOffset,this.#byteOffset + byteLength));
this.#byteOffset += byteLength;
return value;
}

#readString() {
const length = this.#readUnsignedShort();
if (this.#byteOffset + length > this.#data.byteLength){
throw new Error("Ran out of bytes to read, unexpectedly reached the end of the buffer");
}
const value = decoder.decode(this.#data.subarray(this.#byteOffset,this.#byteOffset + length));
this.#byteOffset += length;
return value;
Expand Down
2 changes: 1 addition & 1 deletion test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const result = await NBT.read(data);
console.log(result,"\n");

const result2 = await NBT.write(result,{ bedrockLevel: null })
.then(buffer => NBT.read(buffer,{ endian: "big", isNamed: false }));
.then(buffer => NBT.read(buffer,{ endian: "big" }));
console.log(result2,"\n");

const recompile = Buffer.from(await NBT.write(result2));
Expand Down

0 comments on commit ca05acd

Please sign in to comment.