Sitelet https://github.com/nodejs/node/issues/54472
Skip to content

Assigning a value to Array.prototype[1] will result in an error :node:internal/process/task_queues:77 callback(); #54472

Description

@LoongZP

Version

v20.14.0

Platform

Microsoft Windows NT 10.0.22631.0
x64

Subsystem

No response

What steps will reproduce the bug?

code:
Array.prototype[1] = 2
console.log(Array.prototype);

result:
image

How often does it reproduce? Is there a required condition?

When I knew that Array.prototype was an Array, I tried to assign a value to Array.prototype[x].
Assigning only Array.prototype[1] results in an error that will occur when reading Array.prototype.

What is the expected behavior? Why is that the expected behavior?

In Chrome, you will get the following results:

Array.prototype[1] = 2
console.log(Array.prototype);

result:
[1: 2, at: ƒ, concat: ƒ, copyWithin: ƒ, fill: ƒ, find: ƒ, …]

image

What do you see instead?

code:
Array.prototype[1] = 2
console.log(Array.prototype);

result:
Object(2) [ <1 empty item>, 2 ]
node:internal/process/task_queues:77
callback();
^
TypeError: callback is not a function
at process.processTicksAndRejections (node:internal/process/task_queues:77:11)

Node.js v20.14.0

image

Additional information

No response

Activity

  1. avivkeller commented on Aug 21, 2024

    @avivkeller
    Member

    I'm unable to reproduce in v22.6.0, but I haven't tested in v20. @LoongZP can you reproduce in the latest version of v20? (v20.16.0)

    ➜  ~ node
    Welcome to Node.js v22.6.0.
    Type ".help" for more information.
    > Array.prototype[1] = 2
    2
    > console.log(Array.prototype);
    Object(2) [ <1 empty item>, 2 ]
    undefined
    >
  2. LoongZP commented on Aug 21, 2024

    @LoongZP
    Author

    @redyetidev
    The strange thing is that I also have no error when executing in interactive mode in node, it only occurs when node xx.js, which I also found in v22.3.0.

  3. avivkeller commented on Aug 21, 2024

    @avivkeller
    Member

    I'll retest later, but for now could you try to reproduce in the latest version of those release lines?

    v22.6.0
    v20.16.0

  4. LoongZP commented on Aug 21, 2024

    @LoongZP
    Author

    @redyetidev
    I also tried it in ubuntu (node v20.11.1.) and found this issue as well.

  5. LoongZP commented on Aug 21, 2024

    @LoongZP
    Author

    @redyetidev
    I've tried the following:

      os node  version result
    my coputer Microsoft Windows NT 10.0.22631.0   x64 22.6.0 x
    my coputer Microsoft Windows NT 10.0.22631.0   x64 22.3.0 x
    my coputer Microsoft Windows NT 10.0.22631.0   x64 20.14.0 x
    other's coputer Linux version 5.15.0-118-generic (buildd@lcy02-amd64-103) (gcc (Ubuntu 9.4.0-1ubuntu120.04.2) 9.4.0, GNU ld (GNU Binutils for Ubuntu) 2.34) #12820.04.1-Ubuntu SMP Wed Jul 17 13:41:17 UTC 2024 20.11.1 x
    other's coputer Microsoft Windows NT 10.0.22631.0   x64 20.9.9 x

    NOTE:
    It's strange that there is no problem with assigning a value to Array.prototype[0/2/3/4...].

  6. avivkeller commented on Aug 21, 2024

    @avivkeller
    Member
    Array.prototype[1] = 2;
    console.log(Array.prototype);
    $ node repro.js
    Object(2) [ <1 empty item>, 2 ]
    node:internal/process/task_queues:77
              callback();
              ^
    
    TypeError: callback is not a function
        at process.processTicksAndRejections (node:internal/process/task_queues:77:11)
    
    Node.js v22.6.0

    Array.prototype[0] = 2;
    console.log(Array.prototype);
    $ node repro.js
    Object(1) [ 2 ]
  7. LoongZP commented on Aug 21, 2024

    @LoongZP
    Author

    @redyetidev
    So what is the reason, it's a very strange mistake.

  8. added
    consoleIssues and PRs related to the console subsystem.
    on Aug 21, 2024
  9. moorthid2023 commented on Aug 21, 2024

    @moorthid2023

    I think leaving first index cause the issue

    Array.prototype[0]=2;
    let problem = Array.prototype;
    console.log(problem);

    C:\Users\Moorthi\De
    Object(1) [ 2 ]

  10. LoongZP commented on Aug 21, 2024

    @LoongZP
    Author

    I think leaving first index cause the issue

    Array.prototype[0]=2; let problem = Array.prototype; console.log(problem);

    C:\Users\Moorthi\De Object(1) [ 2 ]

    No, you can try the code below:

    Array.prototype[2] = 2;
    let problem = Array.prototype;
    console.log(problem);

  11. avivkeller commented on Aug 21, 2024

    @avivkeller
    Member

    Array.prototype[2] = 2;
    let problem = Array.prototype;
    console.log(problem);

    The failing line is:

    So something is calling that line incorrectly when Array.prototype[1] isn't what it should be...

    I've added the console label, as this isn't reproducible without calling console.log.


    The following prefixes each behave differently:

    // Crashes
    Array.prototype[1] = 1;
    // Hangs
    Array.prototype[1] = null;
    // Works normally
    Array.prototype[1] = undefined;

    The error can be reproduced without console (but this function is called from the console.log call):

    process.nextTick(()=>{});
  12. added
    processIssues and PRs related to the process subsystem.
    and removed
    consoleIssues and PRs related to the console subsystem.
    on Aug 21, 2024
  13. avivkeller commented on Aug 21, 2024

    @avivkeller
    Member

    @nodejs/process

  14. 15 remaining items

  15. jakecastelli commented on Aug 23, 2024

    @jakecastelli
    Member

    Just thought asking about the "out of bound access issue here" - the this.list will be kSize here which is 2048 when initialised. And this line here with bit mask should prevent the out of bound access issue.

  16. benjamingr commented on Aug 23, 2024

    @benjamingr
    Member

    We totally should fix the one Antoine pointed out (where node core dumps). Even if we don't do primordials everywhere for readability/performance we totally still should in error paths so users can tell why their code failed.

  17. joyeecheung commented on Aug 23, 2024

    @joyeecheung
    Member

    new Array() doesn't actually initialize it, it'll need to be filled or otherwise it's still an out-of-bound access that leads to prototype lookup.

  18. joyeecheung commented on Aug 23, 2024

    @joyeecheung
    Member

    Actually, this rings a bell - we should probably just forbid new Array with the linter. I made a similar argument against holey arrays in #52058 (comment) (it can also lead to worse performance in array accesses).

  19. targos commented on Aug 24, 2024

    @targos
    Member

    we should probably just forbid new Array with the linter.

    I agree. #54281 fixed a similar issue.

  20. jakecastelli commented on Aug 24, 2024

    @jakecastelli
    Member

    it's still an out-of-bound access that leads to prototype lookup.

    Much appreciated! Now I understood 🙏

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

    async_hooksIssues and PRs related to the async hooks subsystem.confirmed-bugIssues and PRs for confirmed bugs.processIssues and PRs related to the process subsystem.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions