Skip to content
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

src: remove calls to deprecated v8 functions (Uint32Value) #22143

Closed
wants to merge 9 commits into from

Conversation

ryzokuken
Copy link
Contributor

Remove all calls to deprecated v8 functions (here:
Value::Uint32Value) inside the code (src directory only).

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message follows commit guidelines

/cc @addaleax @hashseed

@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. lib / src Issues and PRs related to general changes in the lib or src directory. labels Aug 5, 2018
Local<Context> ctx = env->context();
uint32_t start, end;
if (!args[2]->Uint32Value(ctx).To(&start) ||
!args[3]->Uint32Value(ctx).To(&end))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can use .As<Uint32>() for both arguments here. They are coerced in JS with value >>> 0.

@@ -1003,7 +1009,7 @@ void IndexOfNumber(const FunctionCallbackInfo<Value>& args) {
THROW_AND_RETURN_UNLESS_BUFFER(Environment::GetCurrent(args), args[0]);
SPREAD_BUFFER_ARG(args[0], ts_obj);

uint32_t needle = args[1]->Uint32Value();
uint32_t needle = args[1].As<v8::Uint32>()->Value();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: add using v8::Uint32; at the top of the namespace.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, if you are sure this is a Uint32, modify the CHECK above to IsUint32

static_cast<point_conversion_form_t>(args[0]->Uint32Value());
uint32_t val;
if (!args[0]->Uint32Value(env->context()).To(&val))
return env->ThrowError("Failed to parse argument");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to throw an error here?

static_cast<point_conversion_form_t>(args[2]->Uint32Value());
uint32_t val;
if (!args[2]->Uint32Value(env->context()).To(&val))
return env->ThrowError("Failed to parse argument");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

src/tcp_wrap.cc Outdated
@@ -180,7 +180,7 @@ void TCPWrap::SetKeepAlive(const FunctionCallbackInfo<Value>& args) {
args.Holder(),
args.GetReturnValue().Set(UV_EBADF));
int enable = args[0]->Int32Value();
unsigned int delay = args[1]->Uint32Value();
unsigned int delay = args[1].As<v8::Uint32>()->Value();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This value is not verified in JS

@targos
Copy link
Member

targos commented Sep 1, 2018

Ping. This is ready for review.

@targos
Copy link
Member

targos commented Sep 1, 2018

int value = args[1]->Uint32Value() & 255;
memset(ts_obj_data + start, value, fill_length);
uint32_t val;
if (args[1]->Uint32Value(ctx).To(&val)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fwiw, I still find it easier to read when using the return-on-error style rather than an if (success) { … } block

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Me too. Fixed.

@targos
Copy link
Member

targos commented Sep 2, 2018

ryzokuken and others added 5 commits September 2, 2018 10:38
Remove all calls to deprecated v8 functions (here:
Value::Uint32Value) inside the code (src directory only).
@targos
Copy link
Member

targos commented Sep 2, 2018

It looks like the value is not always an integer... let me check

@targos
Copy link
Member

targos commented Sep 2, 2018

I'm lost here... It seems to me that start and end are guaranteed to be uint32.

I added this just before the binding is called:

process._rawDebug(`${start}, ${end}`);`

Last few lines of output:

16, 32
0, 10
0, 10
./node[25340]: ../src/node_buffer.cc:572:void node::Buffer::{anonymous}::Fill(const v8::FunctionCallbackInfo<v8::Value>&): Assertion `args[2]->IsUint32()' failed.

Here is the relevant code:

node/lib/buffer.js

Lines 869 to 888 in 59e5a39

if (start === undefined) {
start = 0;
end = buf.length;
} else {
// Invalid ranges are not set to a default, so can range check early.
if (end === undefined) {
if (start < 0)
throw new ERR_INDEX_OUT_OF_RANGE();
end = buf.length;
} else {
if (start < 0 || end > buf.length || end < 0)
throw new ERR_INDEX_OUT_OF_RANGE();
end = end >>> 0;
}
start = start >>> 0;
if (start >= end)
return buf;
}
const res = bindingFill(buf, val, start, end, encoding);

@targos
Copy link
Member

targos commented Sep 2, 2018

Here is the failing block:

{
const buf = Buffer.alloc(10, 'abc');
assert.strictEqual(buf.toString(), 'abcabcabca');
buf.fill('է');
assert.strictEqual(buf.toString(), 'էէէէէ');
}

@addaleax
Copy link
Member

addaleax commented Sep 2, 2018

I don’t know if it’s relevant, but there seems to be a bunch of compiler warnings from this PR:

../src/node_zlib.cc: In static member function ‘static void node::{anonymous}::ZCtx::Init(const v8::FunctionCallbackInfo<v8::Value>&)’:
../src/node_zlib.cc:471:119: warning: suggest parentheses around ‘&&’ within ‘||’ [-Wparentheses]
     CHECK((strategy == Z_FILTERED || strategy == Z_HUFFMAN_ONLY ||
                                                                                                                       ^               
In file included from ../src/node_zlib.cc:23:0:
../src/node_buffer.h: In static member function ‘static void node::{anonymous}::ZCtx::Write(const v8::FunctionCallbackInfo<v8::Value>&) [with bool async = true]’:
../src/node_buffer.h:75:3: warning: ‘out_off’ may be used uninitialized in this function [-Wmaybe-uninitialized]
   if (off > max)
   ^~
../src/node_zlib.cc:174:28: note: ‘out_off’ was declared here
     size_t in_off, in_len, out_off, out_len;
                            ^~~~~~~
In file included from ../src/node_zlib.cc:23:0:
../src/node_buffer.h:79:3: warning: ‘out_len’ may be used uninitialized in this function [-Wmaybe-uninitialized]
   if (max - off < len)
   ^~
../src/node_zlib.cc:174:37: note: ‘out_len’ was declared here
     size_t in_off, in_len, out_off, out_len;
                                     ^~~~~~~
../src/node_zlib.cc: In static member function ‘static void node::{anonymous}::ZCtx::Init(const v8::FunctionCallbackInfo<v8::Value>&)’:
../src/node_zlib.cc:471:85: warning: ‘strategy’ may be used uninitialized in this function [-Wmaybe-uninitialized]
     CHECK((strategy == Z_FILTERED || strategy == Z_HUFFMAN_ONLY ||
                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                  ^               
../src/node_zlib.cc:469:14: note: ‘strategy’ was declared here
     uint32_t strategy;
              ^~~~~~~~
In file included from ../src/node_zlib.cc:23:0:
../src/node_buffer.h: In static member function ‘static void node::{anonymous}::ZCtx::Write(const v8::FunctionCallbackInfo<v8::Value>&) [with bool async = false]’:
../src/node_buffer.h:75:3: warning: ‘out_off’ may be used uninitialized in this function [-Wmaybe-uninitialized]
   if (off > max)
   ^~
../src/node_zlib.cc:174:28: note: ‘out_off’ was declared here
     size_t in_off, in_len, out_off, out_len;
                            ^~~~~~~
In file included from ../src/node_zlib.cc:23:0:
../src/node_buffer.h:79:3: warning: ‘out_len’ may be used uninitialized in this function [-Wmaybe-uninitialized]
   if (max - off < len)
   ^~
../src/node_zlib.cc:174:37: note: ‘out_len’ was declared here
     size_t in_off, in_len, out_off, out_len;
                                     ^~~~~~~

@addaleax
Copy link
Member

addaleax commented Sep 2, 2018

@targos I think this is the failing block:

// Testing process.binding. Make sure "start" is properly checked for -1 wrap
// around.
assert.strictEqual(
process.binding('buffer').fill(Buffer.alloc(1), 1, -1, 0, 1), -2);

@targos
Copy link
Member

targos commented Sep 2, 2018

@addaleax Haha of course, thanks!

I think I completely forgot to run the tests locally on this PR (even before making my own changes), sorry.

This should be fixed now.

CI: https://ci.nodejs.org/job/node-test-pull-request/16933/

Copy link
Member

@addaleax addaleax left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still LGTM :)

Environment* env = ctx->env();
Local<Context> context = env->context();

unsigned int flush;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess CI is going to tell us whether it’s a real problem, but at least in theory this would be uint32_t, too

Copy link
Member

@lundibundi lundibundi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.
Though perhaps it's worth adding a macro for converting to uint32?
something like (not sure for the exact macro as I don't have a lot of experience with them and they are quite tricky)

#define CHECKED_TO_UINT32(ctx, from, variable)                               \
  uint32_t variable;                                                         \
  if (!(from)->Uint32Value((ctx)).To(&variable)) return;


CHECKED_TO_UINT32(ctx, args[2], start);

(Though this is not needed if we go with FromMaybe version)

uint32_t start;
if (!args[2]->Uint32Value(ctx).To(&start)) return;
uint32_t end;
if (!args[3]->Uint32Value(ctx).To(&end)) return;
Copy link
Member

@lundibundi lundibundi Sep 2, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure but perhaps FromMaybe version is clearer?

  uint32_t start = args[2]->Uint32Value(ctx).FromMaybe(0);
  uint32_t end = args[3]->Uint32Value(ctx).FromMaybe(0);

Though this will result in function actually continuing execution if provided with invalid value (but wasn't this how it was before - Uint32Value() returns 0 on invalid values AFAIK? )?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though this will result in function actually continuing execution if provided with invalid value

That is the previous behaviour, which is buggy in that it will swallow exceptions if both calls fail.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 shouldn't this then be semver-major to avoid possible breakage?

Also, perhaps we can

  if (!args[2]->IsUint32() || !args[3]->IsUint32())
    return args.GetReturnValue().Set(-2);

  uint32_t start = args[2].As<Uint32>()->Value();
  uint32_t end = args[3].As<Uint32>()->Value();

in this case (tests seem to pass)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only place where we pass in invalid arguments is from a process.binding() test. We could/should probably remove that test in a follow-up PR, and revert 05aa50f (which is pretty close to your suggestion)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I thought that this was expected somewhere else, therefore the test. The suggested commit is even better, with the above I wanted to somehow mitigate that test.

targos pushed a commit that referenced this pull request Sep 2, 2018
Remove all calls to deprecated v8 functions (here:
Value::Uint32Value) inside the code (src directory only).

PR-URL: #22143
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
targos added a commit to targos/node that referenced this pull request Sep 2, 2018
Remove all calls to deprecated v8 functions (here:
Value::Uint32Value) inside the code (src directory only).

Co-authored-by: Michaël Zasso <targos@protonmail.com>
PR-URL: nodejs#22143
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
@targos
Copy link
Member

targos commented Sep 2, 2018

Landed in 167dd36

@targos targos closed this Sep 2, 2018
targos pushed a commit that referenced this pull request Sep 2, 2018
Remove all calls to deprecated v8 functions (here:
Value::Uint32Value) inside the code (src directory only).

PR-URL: #22143
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
targos pushed a commit that referenced this pull request Sep 3, 2018
Remove all calls to deprecated v8 functions (here:
Value::Uint32Value) inside the code (src directory only).

PR-URL: #22143
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
targos pushed a commit that referenced this pull request Sep 6, 2018
Remove all calls to deprecated v8 functions (here:
Value::Uint32Value) inside the code (src directory only).

PR-URL: #22143
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ Issues and PRs that require attention from people who are familiar with C++. lib / src Issues and PRs related to general changes in the lib or src directory.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants