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

riscv64: strange behavior of exception handling #47522

Closed
kxxt opened this issue Apr 12, 2023 · 4 comments
Closed

riscv64: strange behavior of exception handling #47522

kxxt opened this issue Apr 12, 2023 · 4 comments
Labels
riscv64 Issues and PRs related to the riscv64 architecture. v8 engine Issues and PRs related to the V8 dependency.

Comments

@kxxt
Copy link
Contributor

kxxt commented Apr 12, 2023

Version

v19.8.1

Platform

Linux kxxt 6.2.10-arch1-1 #1 SMP PREEMPT_DYNAMIC Fri, 07 Apr 2023 02:10:43 +0000 riscv64 GNU/Linux

Subsystem

No response

What steps will reproduce the bug?

  1. Setup an arch linux RISC-V development environment following this article: https://github.com/felixonmars/archriscv-packages/wiki/Setup-Arch-Linux-RISC-V-Development-Environment
  2. Start the arch rv64 container and switch to a non-root user
  3. Install necessary dependencies via pacman: pacman -S base-devel asp npm nodejs
  4. Checkout the gitea repo(v1.18): git clone https://github.com/go-gitea/gitea -b release/v1.18 --depth=1 && cd gitea
  5. Install dependencies via npm: npm i
  6. Run lessc: npx lessc web_src/less/index.less out

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

100%. No condition is required.

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

The generated css can be found in file out and lessc exit with code 0.

This is the behavior on x86_64 platform so it is the expected behavior.

What do you see instead?

SyntaxError: Cannot create property '_fileInfo' on string '!important' in /home/kxxt/gitea/web_src/less/_tribute.less on line 4, column 3:
3 .tribute-container {
4   box-shadow: 0 .25rem .5rem rgba(0, 0, 0, .25);
5   border-radius: .25rem;

Additional information

By adding some logging :

  1. In node_modules/less/lib/less/less-error.js to show the stack trace.
var LessError = function (e, fileContentMap, currentFilename) {
    Error.call(this);
    var filename = e.filename || currentFilename;
    this.message = e.message;
    this.stack = e.stack;
    if (fileContentMap && filename) {
+       console.log("Trace: ", e.stack);
  1. In node_modules/less/lib/less/parser/parser.js
var Parser = function Parser(context, imports, fileInfo) {
    ...
    function parseNode(str, parseList, currentIndex, fileInfo, callback) {
        var result;
        var returnNodes = [];
        var parser = parserInput;
        try {
            parser.start(str, false, function fail(msg, index) {
                callback({
                    message: msg,
                    index: index + currentIndex
                });
            });
            for (var x = 0, p = void 0, i = void 0; (p = parseList[x]); x++) {
                i = parser.i;
                result = parsers[p]();
                if (result) {
                    try {
+                       console.log("The result is", result);
                        result._index = i + currentIndex;
                        result._fileInfo = fileInfo;
+                       console.log("OK");
                    }
                    catch (e) {
+                       console.log("Caught exception", e);
                    }
                    returnNodes.push(result);
                }
                else {
                    returnNodes.push(null);
                }
            }
            var endInfo = parser.end();
            if (endInfo.isFinished) {
                callback(null, returnNodes);
            }
            else {
                callback(true, null);
            }
        }
        catch (e) {
            throw new less_error_1.default({
                index: e.index + currentIndex,
                message: e.message
            }, imports, fileInfo.filename);
        }
    }

We can get the following output:

Output
The result is [
  Node {
    extendList: undefined,
    condition: undefined,
    evaldCondition: true,
    _index: 1,
    _fileInfo: {
      rewriteUrls: false,
      entryPath: '/home/kxxt/gitea/web_src/less/',
      rootpath: '',
      rootFilename: '/home/kxxt/gitea/web_src/less/index.less',
      currentDirectory: '/home/kxxt/gitea/web_src/less/',
      filename: '/home/kxxt/gitea/web_src/less/helpers.less'
    },
    elements: [ [Node] ],
    mixinElements_: undefined
  }
]
OK
The result is [
  Node {
    extendList: undefined,
    condition: undefined,
    evaldCondition: true,
    _index: 1,
    _fileInfo: {
      rewriteUrls: false,
      entryPath: '/home/kxxt/gitea/web_src/less/',
      rootpath: '',
      rootFilename: '/home/kxxt/gitea/web_src/less/index.less',
      currentDirectory: '/home/kxxt/gitea/web_src/less/',
      filename: '/home/kxxt/gitea/web_src/less/helpers.less'
    },
    elements: [ [Node] ],
    mixinElements_: undefined
  }
]
OK
The result is [
  Node {
    extendList: undefined,
    condition: undefined,
    evaldCondition: true,
    _index: 1,
    _fileInfo: {
      rewriteUrls: false,
      entryPath: '/home/kxxt/gitea/web_src/less/',
      rootpath: '',
      rootFilename: '/home/kxxt/gitea/web_src/less/index.less',
      currentDirectory: '/home/kxxt/gitea/web_src/less/',
      filename: '/home/kxxt/gitea/web_src/less/helpers.less'
    },
    elements: [ [Node] ],
    mixinElements_: undefined
  }
]
OK
The result is [
  Node {
    extendList: undefined,
    condition: undefined,
    evaldCondition: true,
    _index: 1,
    _fileInfo: {
      rewriteUrls: false,
      entryPath: '/home/kxxt/gitea/web_src/less/',
      rootpath: '',
      rootFilename: '/home/kxxt/gitea/web_src/less/index.less',
      currentDirectory: '/home/kxxt/gitea/web_src/less/',
      filename: '/home/kxxt/gitea/web_src/less/helpers.less'
    },
    elements: [ [Node] ],
    mixinElements_: undefined
  }
]
OK
The result is [
  Node {
    extendList: undefined,
    condition: undefined,
    evaldCondition: true,
    _index: 1,
    _fileInfo: {
      rewriteUrls: false,
      entryPath: '/home/kxxt/gitea/web_src/less/',
      rootpath: '',
      rootFilename: '/home/kxxt/gitea/web_src/less/index.less',
      currentDirectory: '/home/kxxt/gitea/web_src/less/',
      filename: '/home/kxxt/gitea/web_src/less/helpers.less'
    },
    elements: [ [Node] ],
    mixinElements_: undefined
  }
]
OK
The result is [
  Node {
    extendList: undefined,
    condition: undefined,
    evaldCondition: true,
    _index: 1,
    _fileInfo: {
      rewriteUrls: false,
      entryPath: '/home/kxxt/gitea/web_src/less/',
      rootpath: '',
      rootFilename: '/home/kxxt/gitea/web_src/less/index.less',
      currentDirectory: '/home/kxxt/gitea/web_src/less/',
      filename: '/home/kxxt/gitea/web_src/less/helpers.less'
    },
    elements: [ [Node] ],
    mixinElements_: undefined
  }
]
OK
The result is [
  Node {
    extendList: undefined,
    condition: undefined,
    evaldCondition: true,
    _index: 1,
    _fileInfo: {
      rewriteUrls: false,
      entryPath: '/home/kxxt/gitea/web_src/less/',
      rootpath: '',
      rootFilename: '/home/kxxt/gitea/web_src/less/index.less',
      currentDirectory: '/home/kxxt/gitea/web_src/less/',
      filename: '/home/kxxt/gitea/web_src/less/helpers.less'
    },
    elements: [ [Node] ],
    mixinElements_: undefined
  }
]
OK
The result is [
  Node {
    extendList: undefined,
    condition: undefined,
    evaldCondition: true,
    _index: 1,
    _fileInfo: {
      rewriteUrls: false,
      entryPath: '/home/kxxt/gitea/web_src/less/',
      rootpath: '',
      rootFilename: '/home/kxxt/gitea/web_src/less/index.less',
      currentDirectory: '/home/kxxt/gitea/web_src/less/',
      filename: '/home/kxxt/gitea/web_src/less/helpers.less'
    },
    elements: [ [Node] ],
    mixinElements_: undefined
  }
]
OK
The result is [
  Node {
    extendList: undefined,
    condition: undefined,
    evaldCondition: true,
    _index: 1,
    _fileInfo: {
      rewriteUrls: false,
      entryPath: '/home/kxxt/gitea/web_src/less/',
      rootpath: '',
      rootFilename: '/home/kxxt/gitea/web_src/less/index.less',
      currentDirectory: '/home/kxxt/gitea/web_src/less/',
      filename: '/home/kxxt/gitea/web_src/less/helpers.less'
    },
    elements: [ [Node] ],
    mixinElements_: undefined
  }
]
OK
The result is [
  Node {
    extendList: undefined,
    condition: undefined,
    evaldCondition: true,
    _index: 1,
    _fileInfo: {
      rewriteUrls: false,
      entryPath: '/home/kxxt/gitea/web_src/less/',
      rootpath: '',
      rootFilename: '/home/kxxt/gitea/web_src/less/index.less',
      currentDirectory: '/home/kxxt/gitea/web_src/less/',
      filename: '/home/kxxt/gitea/web_src/less/helpers.less'
    },
    elements: [ [Node] ],
    mixinElements_: undefined
  }
]
OK
The result is [
  Node {
    extendList: undefined,
    condition: undefined,
    evaldCondition: true,
    _index: 1,
    _fileInfo: {
      rewriteUrls: false,
      entryPath: '/home/kxxt/gitea/web_src/less/',
      rootpath: '',
      rootFilename: '/home/kxxt/gitea/web_src/less/index.less',
      currentDirectory: '/home/kxxt/gitea/web_src/less/',
      filename: '/home/kxxt/gitea/web_src/less/helpers.less'
    },
    elements: [ [Node] ],
    mixinElements_: undefined
  }
]
OK
The result is [
  Node {
    extendList: undefined,
    condition: undefined,
    evaldCondition: true,
    _index: 1,
    _fileInfo: {
      rewriteUrls: false,
      entryPath: '/home/kxxt/gitea/web_src/less/',
      rootpath: '',
      rootFilename: '/home/kxxt/gitea/web_src/less/index.less',
      currentDirectory: '/home/kxxt/gitea/web_src/less/',
      filename: '/home/kxxt/gitea/web_src/less/helpers.less'
    },
    elements: [ [Node] ],
    mixinElements_: undefined
  }
]
OK
The result is [
  Node {
    extendList: undefined,
    condition: undefined,
    evaldCondition: true,
    _index: 1,
    _fileInfo: {
      rewriteUrls: false,
      entryPath: '/home/kxxt/gitea/web_src/less/',
      rootpath: '',
      rootFilename: '/home/kxxt/gitea/web_src/less/index.less',
      currentDirectory: '/home/kxxt/gitea/web_src/less/',
      filename: '/home/kxxt/gitea/web_src/less/helpers.less'
    },
    elements: [ [Node] ],
    mixinElements_: undefined
  }
]
OK
The result is [
  Node {
    extendList: undefined,
    condition: undefined,
    evaldCondition: true,
    _index: 1,
    _fileInfo: {
      rewriteUrls: false,
      entryPath: '/home/kxxt/gitea/web_src/less/',
      rootpath: '',
      rootFilename: '/home/kxxt/gitea/web_src/less/index.less',
      currentDirectory: '/home/kxxt/gitea/web_src/less/',
      filename: '/home/kxxt/gitea/web_src/less/helpers.less'
    },
    elements: [ [Node] ],
    mixinElements_: undefined
  }
]
OK
The result is [
  Node {
    extendList: undefined,
    condition: undefined,
    evaldCondition: true,
    _index: 1,
    _fileInfo: {
      rewriteUrls: false,
      entryPath: '/home/kxxt/gitea/web_src/less/',
      rootpath: '',
      rootFilename: '/home/kxxt/gitea/web_src/less/index.less',
      currentDirectory: '/home/kxxt/gitea/web_src/less/',
      filename: '/home/kxxt/gitea/web_src/less/helpers.less'
    },
    elements: [ [Node] ],
    mixinElements_: undefined
  }
]
OK
The result is [
  Node {
    extendList: undefined,
    condition: undefined,
    evaldCondition: true,
    _index: 1,
    _fileInfo: {
      rewriteUrls: false,
      entryPath: '/home/kxxt/gitea/web_src/less/',
      rootpath: '',
      rootFilename: '/home/kxxt/gitea/web_src/less/index.less',
      currentDirectory: '/home/kxxt/gitea/web_src/less/',
      filename: '/home/kxxt/gitea/web_src/less/helpers.less'
    },
    elements: [ [Node] ],
    mixinElements_: undefined
  }
]
OK
The result is Node { value: [ Node { value: [Array], noSpacing: undefined } ] }
OK
The result is !important
OK
The result is Node { value: [ Node { value: [Array], noSpacing: undefined } ] }
OK
The result is !important
OK
The result is Node { value: [ Node { value: [Array], noSpacing: undefined } ] }
OK
The result is Node { value: [ Node { value: [Array], noSpacing: undefined } ] }
OK
Trace:  TypeError: Cannot create property '_fileInfo' on string '!important'
    at Object.parseNode (/home/kxxt/gitea/node_modules/less/lib/less/parser/parser.js:103:42)
    at Ruleset.transformDeclaration (/home/kxxt/gitea/node_modules/less/lib/less/tree/ruleset.js:322:32)
    at Ruleset.parseValue (/home/kxxt/gitea/node_modules/less/lib/less/tree/ruleset.js:343:41)
    at Ruleset.variable (/home/kxxt/gitea/node_modules/less/lib/less/tree/ruleset.js:300:25)
    at Array.<anonymous> (/home/kxxt/gitea/node_modules/less/lib/less/tree/variable.js:26:27)
    at Variable.find (/home/kxxt/gitea/node_modules/less/lib/less/tree/variable.js:54:21)
    at Variable.eval (/home/kxxt/gitea/node_modules/less/lib/less/tree/variable.js:25:25)
    at Operation.eval (/home/kxxt/gitea/node_modules/less/lib/less/tree/operation.js:20:34)
    at Expression.eval (/home/kxxt/gitea/node_modules/less/lib/less/tree/expression.js:40:41)
    at Value.eval (/home/kxxt/gitea/node_modules/less/lib/less/tree/value.js:25:34)
[31mSyntaxError: Cannot create property '_fileInfo' on string '!important'[39m�[31m in [39m/home/kxxt/gitea/web_src/less/_tribute.less�[90m on line 4, column 3:[39m
[90m3 .tribute-container {[39m
4   [7m�[31m�[1mb�[22mox-shadow: 0 .25rem .5rem rgba(0, 0, 0, .25);[39m�[27m
[90m5   border-radius: .25rem;[39m�[0m�[0m

It seems that

  1. the catch in node_modules/less/lib/less/parser/parser.js didn't catch the exception because there are no "Caught Exception" in the log.
  2. the attempt to create property _fileInfo on string "!important" seems to be successful because "OK" is logged.

There are some failed jstest on riscv64 due to Missing expected exception. Maybe it is caused by the same error.

The nodejs build recipe used on arch riscv64

The nodejs-v8-jit-fix.patch is equivalient to #47399

# Maintainer: Felix Yan <[email protected]>
# Contributor  Bartłomiej Piotrowski <[email protected]>
# Contributor: Thomas Dziedzic < gostrc at gmail >
# Contributor: James Campos <[email protected]>
# Contributor: BlackEagle < ike DOT devolder AT gmail DOT com >
# Contributor: Dongsheng Cai <dongsheng at moodle dot com>
# Contributor: Masutu Subric <masutu.arch at googlemail dot com>
# Contributor: TIanyi Cui <[email protected]>

pkgname=nodejs
pkgver=19.8.1
_commit=e808076389ed1ad8235177562f6dadcd616eb81b
pkgrel=1
pkgdesc='Evented I/O for V8 javascript'
arch=(x86_64 riscv64)
url='https://nodejs.org/'
license=('MIT')
options=(!lto)
depends=('brotli' 'openssl' 'zlib' 'icu' 'libuv' 'libnghttp2' 'c-ares') # 'http-parser' 'v8')
makedepends=('git' 'python' 'procps-ng')
optdepends=('npm: nodejs package manager')
source=("git+https://github.com/nodejs/node.git#commit=$_commit"
        "nodejs-v8-jit-fix.patch")
sha512sums=('SKIP'
            'fb4fa53b99e69ab7ae9c7d1483bb73169e2adba36edfc4e76e2edbcce7f054d17580405977d02e34f712696be7770d3dfde01501b507f92383c6e44ec899c74f')

prepare() {
  cd node
  patch -Np1 -i ../nodejs-v8-jit-fix.patch
}

build() {
  cd node

  ./configure \
    --prefix=/usr \
    --with-intl=system-icu \
    --without-npm \
    --shared \
    --shared-openssl \
    --shared-zlib \
    --shared-libuv \
    --experimental-http-parser \
    --shared-nghttp2 \
    --shared-cares \
    --shared-brotli
    # --shared-v8
    # --shared-http-parser

  # -fno-strict-aliasing for gcc>=10: https://github.com/nodejs/node/issues/33899
  make CFLAGS="-fno-strict-aliasing $CFLAGS" CXXFLAGS="-fno-strict-aliasing $CXXFLAGS"
}

check() {
  cd node
  make CFLAGS="-fno-strict-aliasing $CFLAGS" CXXFLAGS="-fno-strict-aliasing $CXXFLAGS" test || :
}

package() {
  cd node
  make DESTDIR="$pkgdir" install
  install -Dm644 LICENSE -t "$pkgdir"/usr/share/licenses/nodejs/

  cd "$pkgdir"/usr/lib
  ln -s libnode.so.* libnode.so
}
# vim:set ts=2 sw=2 et:

This issue is also reproducible with JIT disabled: NODE_OPTIONS=--jitless npx lessc web_src/less/index.less out

@kxxt
Copy link
Contributor Author

kxxt commented Apr 12, 2023

cc @luyahan

@VoltrexKeyva VoltrexKeyva added the riscv64 Issues and PRs related to the riscv64 architecture. label Apr 12, 2023
@bnoordhuis bnoordhuis added the v8 engine Issues and PRs related to the V8 dependency. label Apr 15, 2023
@bnoordhuis
Copy link
Member

I'll leave the issue open for a few days so @luyahan can chime in but, as this is a bug in V8's riscv backend, Node's bug tracker isn't really the right place to report or discuss it.

@kxxt
Copy link
Contributor Author

kxxt commented Apr 19, 2023

@kxxt kxxt closed this as completed Apr 19, 2023
@thesamesam
Copy link
Contributor

thesamesam commented Jul 28, 2024

Hi! At least part of this issue, possibly the whole thing, was debugged by @WhatAmISupposedToPutHere and reported at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116057.

It appears it wasn't an issue in the V8 backend for a specific platform, but rather a miscompilation by GCC of V8. It's still not completely clear whether there may be either UB or ill-advised code in V8, but GCC's fixed it on their side. As of writing, it's not yet been backported. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
riscv64 Issues and PRs related to the riscv64 architecture. v8 engine Issues and PRs related to the V8 dependency.
Projects
None yet
Development

No branches or pull requests

4 participants