nodejs / node

Node.js JavaScript runtime ✨🐢🚀✨
https://nodejs.org
Other
106.74k stars 29.12k forks source link

Bug with ~ operator #38832

Closed nikelborm closed 3 years ago

nikelborm commented 3 years ago

What steps will reproduce the bug?

nikel@nikel-PC:~$ cat test.js 
console.log(process);

let arr = [ 28, 29, 30, 31, 32, 33, 34, 35 ];
for ( k of arr) {
        const base = 2**k;
        const less = base - 2;
        const more = base + 2;

        const strBase = base.toString();
        const strLess = less.toString();
        const strMore = more.toString();

        const baseTilda = ~~strBase;
        const lessTilda = ~~strLess;
        const moreTilda = ~~strMore;

        const basePlus = +strBase;
        const lessPlus = +strLess;
        const morePlus = +strMore;

        console.log( { k, base, less, more, strBase, strLess, strMore, baseTilda, lessTilda, moreTilda, basePlus, lessPlus, morePlus } );
}
nikel@nikel-PC:~$ node test.js 
process {
  version: 'v16.1.0',
  versions: {
    node: '16.1.0',
    v8: '9.0.257.24-node.11',
    uv: '1.41.0',
    zlib: '1.2.11',
    brotli: '1.0.9',
    ares: '1.17.1',
    modules: '93',
    nghttp2: '1.42.0',
    napi: '8',
    llhttp: '6.0.1',
    openssl: '1.1.1k+quic',
    cldr: '39.0',
    icu: '69.1',
    tz: '2021a',
    unicode: '13.0',
    ngtcp2: '0.1.0-DEV',
    nghttp3: '0.1.0-DEV'
  },
  arch: 'x64',
  platform: 'linux',
  release: {
    name: 'node',
    sourceUrl: 'https://nodejs.org/download/release/v16.1.0/node-v16.1.0.tar.gz',
    headersUrl: 'https://nodejs.org/download/release/v16.1.0/node-v16.1.0-headers.tar.gz'
  },
  _rawDebug: [Function: _rawDebug],
  moduleLoadList: [
    'Internal Binding native_module',
    'Internal Binding errors',
    'NativeModule internal/errors',
    'Internal Binding config',
    'Internal Binding constants',
    'Internal Binding util',
    'Internal Binding types',
    'NativeModule internal/util',
    'NativeModule internal/util/types',
    'NativeModule internal/assert',
    'NativeModule internal/validators',
    'Internal Binding icu',
    'NativeModule internal/util/inspect',
    'NativeModule events',
    'Internal Binding buffer',
    'Internal Binding string_decoder',
    'NativeModule internal/buffer',
    'NativeModule internal/encoding',
    'Internal Binding symbols',
    'Internal Binding messaging',
    'NativeModule internal/worker/js_transferable',
    'NativeModule internal/blob',
    'NativeModule buffer',
    'NativeModule internal/process/per_thread',
    'Internal Binding process_methods',
    'Internal Binding credentials',
    'Internal Binding async_wrap',
    'Internal Binding task_queue',
    'NativeModule internal/async_hooks',
    'NativeModule async_hooks',
    'NativeModule internal/process/promises',
    'NativeModule internal/fixed_queue',
    'NativeModule internal/process/task_queues',
    'Internal Binding trace_events',
    'NativeModule internal/constants',
    'NativeModule internal/console/constructor',
    'NativeModule internal/console/global',
    'NativeModule internal/util/inspector',
    'Internal Binding inspector',
    'NativeModule internal/querystring',
    'NativeModule path',
    'Internal Binding url',
    'NativeModule internal/url',
    'NativeModule internal/util/debuglog',
    'NativeModule util',
    'NativeModule internal/event_target',
    'NativeModule internal/abort_controller',
    'Internal Binding worker',
    'NativeModule internal/streams/destroy',
    'NativeModule internal/streams/utils',
    'NativeModule internal/streams/pipeline',
    'NativeModule internal/streams/end-of-stream',
    'NativeModule internal/streams/legacy',
    'NativeModule internal/streams/add-abort-signal',
    'NativeModule internal/streams/buffer_list',
    'NativeModule internal/streams/state',
    'NativeModule internal/streams/readable',
    'NativeModule internal/streams/writable',
    'NativeModule internal/streams/duplex',
    'NativeModule internal/streams/transform',
    'NativeModule internal/streams/passthrough',
    'NativeModule stream',
    'NativeModule internal/worker/io',
    'Internal Binding timers',
    'NativeModule internal/linkedlist',
    'NativeModule internal/priority_queue',
    'NativeModule internal/timers',
    'NativeModule timers',
    'NativeModule internal/process/execution',
    'NativeModule internal/process/warning',
    'Internal Binding fs',
    'NativeModule internal/fs/utils',
    'Internal Binding fs_dir',
    'NativeModule internal/fs/dir',
    'NativeModule fs',
    'Internal Binding serdes',
    'Internal Binding profiler',
    'Internal Binding heap_utils',
    'Internal Binding stream_wrap',
    'Internal Binding uv',
    'NativeModule internal/stream_base_commons',
    'NativeModule internal/heap_utils',
    'Internal Binding v8',
    'NativeModule v8',
    'NativeModule internal/process/signal',
    'Internal Binding options',
    'NativeModule internal/options',
    'NativeModule internal/bootstrap/pre_execution',
    'NativeModule internal/inspector_async_hook',
    'Internal Binding report',
    'NativeModule internal/process/report',
    'NativeModule internal/util/iterable_weak_map',
    'NativeModule internal/modules/cjs/helpers',
    'NativeModule internal/source_map/source_map_cache',
    'Internal Binding contextify',
    'NativeModule vm',
    'NativeModule internal/idna',
    'NativeModule url',
    'NativeModule internal/modules/package_json_reader',
    'Internal Binding module_wrap',
    ... 26 more items
  ],
  binding: [Function: binding],
  _linkedBinding: [Function: _linkedBinding],
  _events: [Object: null prototype] {
    newListener: [Function: startListeningIfSignal],
    removeListener: [Function: stopListeningIfSignal],
    warning: [Function: onWarning],
    SIGWINCH: [Function (anonymous)]
  },
  _eventsCount: 4,
  _maxListeners: undefined,
  domain: null,
  _exiting: false,
  config: [Getter/Setter],
  dlopen: [Function: dlopen],
  uptime: [Function: uptime],
  _getActiveRequests: [Function: _getActiveRequests],
  _getActiveHandles: [Function: _getActiveHandles],
  reallyExit: [Function: reallyExit],
  _kill: [Function: _kill],
  cpuUsage: [Function: cpuUsage],
  resourceUsage: [Function: resourceUsage],
  memoryUsage: [Function: memoryUsage] { rss: [Function: rss] },
  kill: [Function: kill],
  exit: [Function: exit],
  openStdin: [Function (anonymous)],
  getuid: [Function: getuid],
  geteuid: [Function: geteuid],
  getgid: [Function: getgid],
  getegid: [Function: getegid],
  getgroups: [Function: getgroups],
  allowedNodeEnvironmentFlags: [Getter/Setter],
  assert: [Function: deprecated],
  features: {
    inspector: true,
    debug: false,
    uv: true,
    ipv6: true,
    tls_alpn: true,
    tls_sni: true,
    tls_ocsp: true,
    tls: true,
    cached_builtins: [Getter]
  },
  _fatalException: [Function (anonymous)],
  setUncaughtExceptionCaptureCallback: [Function: setUncaughtExceptionCaptureCallback],
  hasUncaughtExceptionCaptureCallback: [Function: hasUncaughtExceptionCaptureCallback],
  emitWarning: [Function: emitWarning],
  nextTick: [Function: nextTick],
  _tickCallback: [Function: runNextTicks],
  _debugProcess: [Function: _debugProcess],
  _debugEnd: [Function: _debugEnd],
  _startProfilerIdleNotifier: [Function (anonymous)],
  _stopProfilerIdleNotifier: [Function (anonymous)],
  stdout: [Getter],
  stdin: [Getter],
  stderr: [Getter],
  abort: [Function: abort],
  umask: [Function: wrappedUmask],
  chdir: [Function: wrappedChdir],
  cwd: [Function: wrappedCwd],
  initgroups: [Function: initgroups],
  setgroups: [Function: setgroups],
  setegid: [Function (anonymous)],
  seteuid: [Function (anonymous)],
  setgid: [Function (anonymous)],
  setuid: [Function (anonymous)],
  env: {
    SHELL: '/bin/bash',
    WINDOWID: '113246215',
    QT_ACCESSIBILITY: '1',
    KDED_STARTED_BY_KDEINIT: '1',
    COLORTERM: 'truecolor',
    XDG_CONFIG_DIRS: '/etc/xdg/xdg-plasma:/etc/xdg:/usr/share/kubuntu-default-settings/kf5-settings',
    XDG_SESSION_PATH: '/org/freedesktop/DisplayManager/Session0',
    NVM_INC: '/home/nikel/.nvm/versions/node/v16.1.0/include/node',
    GTK_IM_MODULE: 'ibus',
    LANGUAGE: '',
    MANDATORY_PATH: '/usr/share/gconf/plasma.mandatory.path',
    SSH_AUTH_SOCK: '/tmp/ssh-sVDZIE0zfevt/agent.999',
    SHELL_SESSION_ID: '72ba8790815d46deb44a6885ef5d113c',
    XMODIFIERS: '@im=ibus',
    DESKTOP_SESSION: 'plasma',
    SSH_AGENT_PID: '1080',
    GTK_RC_FILES: '/etc/gtk/gtkrc:/home/nikel/.gtkrc:/home/nikel/.config/gtkrc',
    XCURSOR_SIZE: '24',
    XDG_SEAT: 'seat0',
    PWD: '/home/nikel',
    XDG_SESSION_DESKTOP: 'KDE',
    LOGNAME: 'nikel',
    XDG_SESSION_TYPE: 'x11',
    GPG_AGENT_INFO: '/run/user/1000/gnupg/S.gpg-agent:0:1',
    XAUTHORITY: '/home/nikel/.Xauthority',
    GTK2_RC_FILES: '/etc/gtk-2.0/gtkrc:/home/nikel/.gtkrc-2.0:/home/nikel/.config/gtkrc-2.0',
    HOME: '/home/nikel',
    LANG: 'en_US.UTF-8',
    LS_COLORS: 'rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:',
    XDG_CURRENT_DESKTOP: 'KDE',
    KONSOLE_DBUS_SERVICE: ':1.359',
    KONSOLE_DBUS_SESSION: '/Sessions/1',
    PROFILEHOME: '',
    XDG_SEAT_PATH: '/org/freedesktop/DisplayManager/Seat0',
    KONSOLE_VERSION: '201203',
    CLUTTER_IM_MODULE: 'ibus',
    KDE_SESSION_UID: '1000',
    NVM_DIR: '/home/nikel/.nvm',
    LESSCLOSE: '/usr/bin/lesspipe %s %s',
    XDG_SESSION_CLASS: 'user',
    TERM: 'xterm-256color',
    DEFAULTS_PATH: '/usr/share/gconf/plasma.default.path',
    LESSOPEN: '| /usr/bin/lesspipe %s',
    USER: 'nikel',
    COLORFGBG: '15;0',
    KDE_SESSION_VERSION: '5',
    DISPLAY: ':0',
    SHLVL: '1',
    NVM_CD_FLAGS: '',
    QT_IM_MODULE: 'ibus',
    XDG_VTNR: '1',
    XDG_SESSION_ID: '1',
    XDG_RUNTIME_DIR: '/run/user/1000',
    QT_AUTO_SCREEN_SCALE_FACTOR: '0',
    XCURSOR_THEME: 'capitaine-cursors-light',
    XDG_DATA_DIRS: '/usr/share/plasma:/usr/local/share:/usr/share:/var/lib/snapd/desktop',
    KDE_FULL_SESSION: 'true',
    PATH: '/home/nikel/.nvm/versions/node/v16.1.0/bin:/home/nikel/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin',
    DBUS_SESSION_BUS_ADDRESS: 'unix:path=/run/user/1000/bus',
    KDE_APPLICATIONS_AS_SCOPE: '1',
    NVM_BIN: '/home/nikel/.nvm/versions/node/v16.1.0/bin',
    KONSOLE_DBUS_WINDOW: '/Windows/1',
    _: '/home/nikel/.nvm/versions/node/v16.1.0/bin/node'
  },
  title: 'node',
  argv: [
    '/home/nikel/.nvm/versions/node/v16.1.0/bin/node',
    '/home/nikel/test.js'
  ],
  execArgv: [],
  pid: 12495,
  ppid: 10953,
  execPath: '/home/nikel/.nvm/versions/node/v16.1.0/bin/node',
  debugPort: 9229,
  hrtime: [Function: hrtime] { bigint: [Function: hrtimeBigInt] },
  argv0: 'node',
  _preload_modules: [],
  mainModule: Module {
    id: '.',
    path: '/home/nikel',
    exports: {},
    filename: '/home/nikel/test.js',
    loaded: false,
    children: [],
    paths: [
      '/home/nikel/node_modules',
      '/home/node_modules',
      '/node_modules'
    ]
  },
  [Symbol(kCapture)]: false
}
{
  k: 28,
  base: 268435456,
  less: 268435454,
  more: 268435458,
  strBase: '268435456',
  strLess: '268435454',
  strMore: '268435458',
  baseTilda: 268435456,
  lessTilda: 268435454,
  moreTilda: 268435458,
  basePlus: 268435456,
  lessPlus: 268435454,
  morePlus: 268435458
}
{
  k: 29,
  base: 536870912,
  less: 536870910,
  more: 536870914,
  strBase: '536870912',
  strLess: '536870910',
  strMore: '536870914',
  baseTilda: 536870912,
  lessTilda: 536870910,
  moreTilda: 536870914,
  basePlus: 536870912,
  lessPlus: 536870910,
  morePlus: 536870914
}
{
  k: 30,
  base: 1073741824,
  less: 1073741822,
  more: 1073741826,
  strBase: '1073741824',
  strLess: '1073741822',
  strMore: '1073741826',
  baseTilda: 1073741824,
  lessTilda: 1073741822,
  moreTilda: 1073741826,
  basePlus: 1073741824,
  lessPlus: 1073741822,
  morePlus: 1073741826
}
{
  k: 31,
  base: 2147483648,
  less: 2147483646,
  more: 2147483650,
  strBase: '2147483648',
  strLess: '2147483646',
  strMore: '2147483650',
  baseTilda: -2147483648,
  lessTilda: 2147483646,
  moreTilda: -2147483646,
  basePlus: 2147483648,
  lessPlus: 2147483646,
  morePlus: 2147483650
}
{
  k: 32,
  base: 4294967296,
  less: 4294967294,
  more: 4294967298,
  strBase: '4294967296',
  strLess: '4294967294',
  strMore: '4294967298',
  baseTilda: 0,
  lessTilda: -2,
  moreTilda: 2,
  basePlus: 4294967296,
  lessPlus: 4294967294,
  morePlus: 4294967298
}
{
  k: 33,
  base: 8589934592,
  less: 8589934590,
  more: 8589934594,
  strBase: '8589934592',
  strLess: '8589934590',
  strMore: '8589934594',
  baseTilda: 0,
  lessTilda: -2,
  moreTilda: 2,
  basePlus: 8589934592,
  lessPlus: 8589934590,
  morePlus: 8589934594
}
{
  k: 34,
  base: 17179869184,
  less: 17179869182,
  more: 17179869186,
  strBase: '17179869184',
  strLess: '17179869182',
  strMore: '17179869186',
  baseTilda: 0,
  lessTilda: -2,
  moreTilda: 2,
  basePlus: 17179869184,
  lessPlus: 17179869182,
  morePlus: 17179869186
}
{
  k: 35,
  base: 34359738368,
  less: 34359738366,
  more: 34359738370,
  strBase: '34359738368',
  strLess: '34359738366',
  strMore: '34359738370',
  baseTilda: 0,
  lessTilda: -2,
  moreTilda: 2,
  basePlus: 34359738368,
  lessPlus: 34359738366,
  morePlus: 34359738370
}

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

What is the expected behavior?

What do you see instead?

Additional information

nikelborm commented 3 years ago
{
  k: 30,
  base: 1073741824,
  less: 1073741822,
  more: 1073741826,
  strBase: '1073741824',
  strLess: '1073741822',
  strMore: '1073741826',
  baseTilda: 1073741824,
  lessTilda: 1073741822,
  moreTilda: 1073741826,
  basePlus: 1073741824,
  lessPlus: 1073741822,
  morePlus: 1073741826
}
{
  k: 31,
  base: 2147483648,
  less: 2147483646,
  more: 2147483650,
  strBase: '2147483648',
  strLess: '2147483646',
  strMore: '2147483650',
  baseTilda: -2147483648,
  lessTilda: 2147483646,
  moreTilda: -2147483646,
  basePlus: 2147483648,
  lessPlus: 2147483646,
  morePlus: 2147483650
}
{
  k: 32,
  base: 4294967296,
  less: 4294967294,
  more: 4294967298,
  strBase: '4294967296',
  strLess: '4294967294',
  strMore: '4294967298',
  baseTilda: 0,
  lessTilda: -2,
  moreTilda: 2,
  basePlus: 4294967296,
  lessPlus: 4294967294,
  morePlus: 4294967298
}
{
  k: 33,
  base: 8589934592,
  less: 8589934590,
  more: 8589934594,
  strBase: '8589934592',
  strLess: '8589934590',
  strMore: '8589934594',
  baseTilda: 0,
  lessTilda: -2,
  moreTilda: 2,
  basePlus: 8589934592,
  lessPlus: 8589934590,
  morePlus: 8589934594
}
ghost commented 3 years ago

it works only for integers up to 2^31-1. for larger integers use bigint

devsnek commented 3 years ago

to expand on this, bitwise operations on the Number type truncate to 32 bits. bitwise operations on the BigInt type do not.