Skip to content

n-api: napi_get_value_int64() needs a strict version #26323

Closed

Description

@jorangreef

I am working on several n-api modules.

We need to enforce that integer arguments are really integers.

This is critical for avoiding buffer overflow and dangerous behavior.

Unfortunately, at present, napi_get_value_int64() and friends are lax.

For example, from the documentation:

Non-finite number values (NaN, +Infinity, or -Infinity) set the result to zero.

I can understand this from a performance perspective, and have been involved in these performance discussions before, but there should also be a way to test for non-integers (including floats), e.g. napi_get_value_int64_strict().

I don't know if this already exists?

Activity

  1. addaleax commented on Feb 26, 2019

    @addaleax
    Member

    See also the (very recent) discussion in nodejs/node-addon-examples#91.

    Is there a reason that napi_get_value_double + a manual integer check doesn’t work for you?

  2. added
    node-apiIssues and PRs related to Node-API.
    feature requestIssues requesting new Node.js features.
    on Feb 26, 2019
  3. jorangreef commented on Feb 27, 2019

    @jorangreef
    Author

    Thanks for the pointer to that discussion.

    I hadn't thought of napi_get_value_double().

    napi_get_value_double() could work for floats, but would it work for NaN?

  4. jorangreef commented on Feb 27, 2019

    @jorangreef
    Author

    I am trying to prevent the situation where a user dereferences a JS object property which doesn't exist, while adding it to another integer as part of passing an offset or size value to a native addon.

    e.g. Passing an offset of object.HEADER + 10 where object.HEADER is a typo and should have been object.HEADING.

    This will end up passing an offset of NaN, which the native addon will receive as 0, which could potentially lead to a misdirected read/write in a native addon, with the user being none the wiser.

  5. legendecas commented on Feb 27, 2019

    @legendecas
    Member

    napi_get_value_double() could work for floats, but would it work for NaN?

    AFAIK, there is an NAN defined in math.h. napi_get_value_double would return the NAN if the js value is NaN.

  6. addaleax commented on Feb 27, 2019

    @addaleax
    Member

    I think static_cast<double>(static_cast<int64_t>(double_value)) == double_value would be a simple and valid check that correctly accounts for Infinity/-Infinity and NaN.

    It doesn’t work for integers larger than ±2**63, but chances are you’re interested in checking whether the value is smaller than that anyway? You may want to adjust int64_t to the actual integer type you’ll end up using.

  7. jorangreef commented on Feb 27, 2019

    @jorangreef
    Author

    Thanks @legendecas and @addaleax for the tips!

    Would (double)((int64_t)(double_value)) == double_value be completely safe in C?

  8. jorangreef commented on Feb 27, 2019

    @jorangreef
    Author

    In other words, would this not lead to undefined behavior if the double represented NaN or Infinity?

  9. addaleax commented on Feb 27, 2019

    @addaleax
    Member

    @jorangreef I think the result of the cast-to-integer is undefined in those cases, but that doesn’t matter because whatever the result, it is an integer and so it won’t compare equal to the original value.

    Casting to integer and then to double and seeing if the result is the same is also what V8 does when we call Number::New() and it has to decide whether to represent the result as an integer or not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature requestIssues requesting new Node.js features.node-apiIssues and PRs related to Node-API.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions