Skip to content

riscv64: strange behavior of exception handling #47522

Closed
@kxxt

Description

@kxxt

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    riscv64Issues and PRs related to the riscv64 architecture.v8 engineIssues and PRs related to the V8 dependency.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions