src: unify implementations of Utf8Value, TwoByteValue, etc.#6357
src: unify implementations of Utf8Value, TwoByteValue, etc.#6357addaleax wants to merge 1 commit intonodejs:masterfrom
Conversation
src/util.h
Outdated
There was a problem hiding this comment.
Style: space after template and can you call the second parameter kStackStorageSize?
|
Mostly LGTM. I like how it gets rid of the duplication. |
|
Updated this with @bnoordhuis’ suggestions. I lifted |
|
Nice! I'd been hoping to get around to doing something similar but you beat me to it! LGTM if CI is green and @bnoordhuis and @trevnorris are happy! |
|
Clearing this from v6.0.0 since it doesn't appear to be a breaking change. Edit: Sounds like this is a bug in v6 |
src/util.cc
Outdated
There was a problem hiding this comment.
I'm missing why you're adding 1 above, but no where else.
There was a problem hiding this comment.
@trevnorris In the other places, it’s added too, but rather to the length when determining the possibly necessary buffer size.
The only reason for that is that string->WriteUtf8 and string->Write return the actual length, so the calculations for the position of the trailing 0 byte don’t have to involve the “old” pre-computed buffer size there.
I can change this to align it with the other classes if you prefer, but I personally would find having to write memcpy(…, len - 1); the weirder of two choices.
|
Great work. Don't have time at the moment to give this as thorough a review as I'd like, but I'll pick this up again tonight. |
7da4fd4 to
c7066fb
Compare
src/util.cc
Outdated
There was a problem hiding this comment.
Style: space after template.
|
Updated this with nits addressed and using |
src/util.h
Outdated
There was a problem hiding this comment.
Could you add length_ = sizeof(T) * storage, then do something like CHECK_LE(length_, length) in SetLength()? Just an extra sanity check to make sure we're never accidentally allowing the writable length to be greater than the allocated memory.
a7aa94f to
14c7a02
Compare
|
Rebased, squashed and updated with @trevnorris’ recent suggestions |
Unify the common code of `Utf8Value`, `TwoByteValue`, `BufferValue`
and `StringBytes::InlineDecoder` into one class. Always make the
result zero-terminated for the first three.
This fixes two problems in passing:
* When the conversion of the input value to String fails,
make the buffer zero-terminated anyway. Previously, this would
have resulted in possibly reading uninitialized data in multiple
places in the code. An instance of that problem can be reproduced
by running e.g.
`valgrind node -e 'net.isIP({ toString() { throw Error() } })'`.
* Previously, `BufferValue` copied one byte too much from the source,
possibly resulting in an out-of-bounds memory access.
This can be reproduced by running e.g.
`valgrind node -e \
'fs.openSync(Buffer.from("node".repeat(8192)), "r")'`.
Further minor changes:
* This lifts the `out()` method of `StringBytes::InlineDecoder`
to the common class so that it can be used when using the
overloaded `operator*` does not seem appropiate.
* Hopefully clearer variable names.
* Add checks to make sure the length of the data does not exceed
the allocated storage size, including the possible null terminator.
PR-URL: #6357
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Unify the common code of `Utf8Value`, `TwoByteValue`, `BufferValue`
and `StringBytes::InlineDecoder` into one class. Always make the
result zero-terminated for the first three.
This fixes two problems in passing:
* When the conversion of the input value to String fails,
make the buffer zero-terminated anyway. Previously, this would
have resulted in possibly reading uninitialized data in multiple
places in the code. An instance of that problem can be reproduced
by running e.g.
`valgrind node -e 'net.isIP({ toString() { throw Error() } })'`.
* Previously, `BufferValue` copied one byte too much from the source,
possibly resulting in an out-of-bounds memory access.
This can be reproduced by running e.g.
`valgrind node -e \
'fs.openSync(Buffer.from("node".repeat(8192)), "r")'`.
Further minor changes:
* This lifts the `out()` method of `StringBytes::InlineDecoder`
to the common class so that it can be used when using the
overloaded `operator*` does not seem appropiate.
* Hopefully clearer variable names.
* Add checks to make sure the length of the data does not exceed
the allocated storage size, including the possible null terminator.
PR-URL: nodejs#6357
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
|
@addaleax lts? |
|
@thealphanerd I think the change here depends on too much other stuff but I’ll make a backport PR with one of the bugfixes here. |
Make sure dereferencing a `Utf8Value` instance always returns a zero-terminated string, even if the conversion to string failed. The corresponding bugfix in the master branch happened in 44a4032 (nodejs#6357).
Make sure dereferencing a `Utf8Value` instance always returns a zero-terminated string, even if the conversion to string failed. The corresponding bugfix in the master branch happened in 44a4032 (#6357). Ref: #6357 PR-URL: #7101 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Myles Borins <myles.borins@gmail.com>
Make sure dereferencing a `Utf8Value` instance always returns a zero-terminated string, even if the conversion to string failed. The corresponding bugfix in the master branch happened in 44a4032 (#6357). Ref: #6357 PR-URL: #7101 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Myles Borins <myles.borins@gmail.com>
Make sure dereferencing a `Utf8Value` instance always returns a zero-terminated string, even if the conversion to string failed. The corresponding bugfix in the master branch happened in 44a4032 (#6357). Ref: #6357 PR-URL: #7101 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Myles Borins <myles.borins@gmail.com>
Unify the common code of `Utf8Value`, `TwoByteValue`, `BufferValue`
and `StringBytes::InlineDecoder` into one class. Always make the
result zero-terminated for the first three.
This fixes two problems in passing:
* When the conversion of the input value to String fails,
make the buffer zero-terminated anyway. Previously, this would
have resulted in possibly reading uninitialized data in multiple
places in the code. An instance of that problem can be reproduced
by running e.g.
`valgrind node -e 'net.isIP({ toString() { throw Error() } })'`.
* Previously, `BufferValue` copied one byte too much from the source,
possibly resulting in an out-of-bounds memory access.
This can be reproduced by running e.g.
`valgrind node -e \
'fs.openSync(Buffer.from("node".repeat(8192)), "r")'`.
Further minor changes:
* This lifts the `out()` method of `StringBytes::InlineDecoder`
to the common class so that it can be used when using the
overloaded `operator*` does not seem appropiate.
* Hopefully clearer variable names.
* Add checks to make sure the length of the data does not exceed
the allocated storage size, including the possible null terminator.
PR-URL: nodejs#6357
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Unify the common code of `Utf8Value`, `TwoByteValue`, `BufferValue`
and `StringBytes::InlineDecoder` into one class. Always make the
result zero-terminated for the first three.
This fixes two problems in passing:
* When the conversion of the input value to String fails,
make the buffer zero-terminated anyway. Previously, this would
have resulted in possibly reading uninitialized data in multiple
places in the code. An instance of that problem can be reproduced
by running e.g.
`valgrind node -e 'net.isIP({ toString() { throw Error() } })'`.
* Previously, `BufferValue` copied one byte too much from the source,
possibly resulting in an out-of-bounds memory access.
This can be reproduced by running e.g.
`valgrind node -e \
'fs.openSync(Buffer.from("node".repeat(8192)), "r")'`.
Further minor changes:
* This lifts the `out()` method of `StringBytes::InlineDecoder`
to the common class so that it can be used when using the
overloaded `operator*` does not seem appropiate.
* Hopefully clearer variable names.
* Add checks to make sure the length of the data does not exceed
the allocated storage size, including the possible null terminator.
PR-URL: #6357
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Unify the common code of `Utf8Value`, `TwoByteValue`, `BufferValue`
and `StringBytes::InlineDecoder` into one class. Always make the
result zero-terminated for the first three.
This fixes two problems in passing:
* When the conversion of the input value to String fails,
make the buffer zero-terminated anyway. Previously, this would
have resulted in possibly reading uninitialized data in multiple
places in the code. An instance of that problem can be reproduced
by running e.g.
`valgrind node -e 'net.isIP({ toString() { throw Error() } })'`.
* Previously, `BufferValue` copied one byte too much from the source,
possibly resulting in an out-of-bounds memory access.
This can be reproduced by running e.g.
`valgrind node -e \
'fs.openSync(Buffer.from("node".repeat(8192)), "r")'`.
Further minor changes:
* This lifts the `out()` method of `StringBytes::InlineDecoder`
to the common class so that it can be used when using the
overloaded `operator*` does not seem appropiate.
* Hopefully clearer variable names.
* Add checks to make sure the length of the data does not exceed
the allocated storage size, including the possible null terminator.
PR-URL: #6357
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Unify the common code of `Utf8Value`, `TwoByteValue`, `BufferValue`
and `StringBytes::InlineDecoder` into one class. Always make the
result zero-terminated for the first three.
This fixes two problems in passing:
* When the conversion of the input value to String fails,
make the buffer zero-terminated anyway. Previously, this would
have resulted in possibly reading uninitialized data in multiple
places in the code. An instance of that problem can be reproduced
by running e.g.
`valgrind node -e 'net.isIP({ toString() { throw Error() } })'`.
* Previously, `BufferValue` copied one byte too much from the source,
possibly resulting in an out-of-bounds memory access.
This can be reproduced by running e.g.
`valgrind node -e \
'fs.openSync(Buffer.from("node".repeat(8192)), "r")'`.
Further minor changes:
* This lifts the `out()` method of `StringBytes::InlineDecoder`
to the common class so that it can be used when using the
overloaded `operator*` does not seem appropiate.
* Hopefully clearer variable names.
* Add checks to make sure the length of the data does not exceed
the allocated storage size, including the possible null terminator.
PR-URL: #6357
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Unify the common code of `Utf8Value`, `TwoByteValue`, `BufferValue`
and `StringBytes::InlineDecoder` into one class. Always make the
result zero-terminated for the first three.
This fixes two problems in passing:
* When the conversion of the input value to String fails,
make the buffer zero-terminated anyway. Previously, this would
have resulted in possibly reading uninitialized data in multiple
places in the code. An instance of that problem can be reproduced
by running e.g.
`valgrind node -e 'net.isIP({ toString() { throw Error() } })'`.
* Previously, `BufferValue` copied one byte too much from the source,
possibly resulting in an out-of-bounds memory access.
This can be reproduced by running e.g.
`valgrind node -e \
'fs.openSync(Buffer.from("node".repeat(8192)), "r")'`.
Further minor changes:
* This lifts the `out()` method of `StringBytes::InlineDecoder`
to the common class so that it can be used when using the
overloaded `operator*` does not seem appropiate.
* Hopefully clearer variable names.
* Add checks to make sure the length of the data does not exceed
the allocated storage size, including the possible null terminator.
PR-URL: #6357
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Checklist
Affected core subsystem(s)
src
Description of change
Unify the common code of
Utf8Value,TwoByteValue,BufferValueandStringBytes::InlineDecoderinto one class. Always make the result zero-terminated for the first three.This fixes two problems in passing:
valgrind node -e 'net.isIP({ toString() { throw Error() } })'. (Most other places whereUtf8ValueorTwoByteValuecan possibly receive non-strings work too, there’s nothing special aboutisIP.)BufferValuecopied one byte too much from the source, possibly resulting in an out-of-bounds memory access. This can be reproduced by running e.g.valgrind node -e 'fs.openSync(Buffer.from("node".repeat(8192)), "r")'.If you don’t like the code changes by themselves because they don’t really modify behaviour in any way, I’d still like to see these issues fixed. Since I don’t see any reason why the latter one can’t occur in real life and bite users of the Buffer-accepting
fsAPI in v6 with a segfault, I’m marking this with the 6.0.0 milestone./cc @bnoordhuis @jasnell