-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use ProtoDef skipChecks
flag to allow full NBT array size support
#91
Conversation
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
They may be allowed to be 32bit length, but doing so will take up very large amounts of memory and it's usually indicative of invalid NBT data, or reading with the wrong encoding (little/big endain/etc). So I think this may make more sense behind a flag. Otherwise there is really no need to have the checks in protodef in the first place. |
@extremeheat do you have a recommended approach on this then? If I add a flag, it looks like I will need to add it to many of the functions that are exported here ( We could also consider some sort of global setting toggle, but I am not sure I like that pattern. |
Yes, you would need to propagate options to all the methods. Global is not good. |
👍 I will work on that over the next few days and update here when it's complete and tested. I agree that a global setting would be worse. |
@extremeheat this is ready for re-review. Passes all the tests and it worked when I included it as the package for my project. |
@extremeheat Hey! What's the status with the review? Do you need anything from me? |
nbt.js
Outdated
const protosSkipChecks = { | ||
big: createProto('big', { skipChecks: true }), | ||
little: createProto('little', { skipChecks: true }), | ||
littleVarint: createProto('littleVarint', { skipChecks: true }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems pretty ugly. Perhaps a better way would be to pass the arguments down along with .createPacketBuffer() or .parsePacketBuffer() as opposed to creating these "instances" for every option permutation.
This might be possible to implement taking advantage of ProtoDef variables introduced in ProtoDef-io/node-protodef#125 if ((arraySize > safeSize) && !ctx.noArraySizeCheck) throw Error(...) with usage like https://github.com/ProtoDef-io/node-protodef/blob/master/examples/variable.js#L17 |
e3b6756
to
19dfdb4
Compare
I don't know if the global state approach is good. What you can probably do instead is add to Eg -function parseUncompressed (data, proto = 'big') {
+function parseUncompressed (data, proto = 'big', noArraySizeCheck) {
if (proto === true) proto = 'little'
+ protos[proto].setVariable('noArraySizeCheck', noArraySizeCheck)
return protos[proto].parsePacketBuffer('nbt', data, data.startOffset).data
} |
@extremeheat won't your proposal still set What are your thoughts on something like this? function parseUncompressed (data, proto = 'big', noArraySizeCheck) {
if (proto === true) proto = 'little'
protos[proto].setVariable('noArraySizeCheck', noArraySizeCheck)
const data = protos[proto].parsePacketBuffer('nbt', data, data.startOffset).data
// Remove the previously set variable so it doesn't persist globally for `proto`
protos[proto].setVariable('noArraySizeCheck', undefined)
return data;
} |
As long as the |
typings/index.d.ts
Outdated
|
||
export function parse(data: Buffer, nbtType?: NBTFormat): Promise<{parsed: NBT, type: NBTFormat, metadata: Metadata}>; | ||
export function parse(data: Buffer, nbtType?: NBTFormat, _?: never, options?: ParseOptions): Promise<{parsed: NBT, type: NBTFormat, metadata: Metadata}>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I typed this with a _
variable because we still need to support the deprecated callback
parameter. Eventually when the deprecated functions are removed in a major version we could remove it from the typing.
I don't know why you made the PR so much more complex. The old code was fine and setting the variable to undefined is OK in JavaScript as it's a falsy condition. There's no need to update the parse() method really, the callback mechanism should probably be removed but it's a breaking change. |
@extremeheat Is there a contributors guide that outlines coding practices you expect in Prismarine repos? If you would prefer to rely on JavaScript's falsy behavior, we can go with your original suggestion. I was immediately unsetting the variable because it was making a permanent change to the declared proto and it's unclear what affects that could have on other functions in the library. Is the plan to fully remove I kept it in |
There isn't a guideline, but we can rely on the expected behaviors of JavaScript for the most part. I think the more important thing is making sure the code is as readable as possible and in general having less code and less unnecessary checks helps a lot there. The parse() function logic is pretty complex currently to support callbacks and promises so adding more arguments to it will make it even more complex. I'd just leave that as is. As you added an options object please add that to the API doc |
I updated the API doc to include details about the new options object. |
Lint is failing |
This reverts commit 867b301.
@extremeheat lint fixed. Before merging, note we will need to merge and release #154 so we can use the update package here. |
Missing a test, would be great to add one. Merging |
/makerelease |
NBT arrays are allowed a length up to 32 bits, so there needs to be a way to skip checks to allow full NBT support. Adding an optional object allows this to happen.
https://minecraft.wiki/w/NBT_format#Binary_format
Based on this required PR: ProtoDef-io/node-protodef#154
Addresses: ProtoDef-io/node-protodef#150 and #85