diff --git a/.github/workflows/test-ubsan.yml b/.github/workflows/test-ubsan.yml new file mode 100644 index 00000000000000..ef31c5372c9a13 --- /dev/null +++ b/.github/workflows/test-ubsan.yml @@ -0,0 +1,61 @@ +name: Test UBSan + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + paths-ignore: + - .mailmap + - '**.md' + - AUTHORS + - doc/** + - .github/** + - '!.github/workflows/ubsan-asan.yml' + push: + branches: + - main + - canary + - v[0-9]+.x-staging + - v[0-9]+.x + paths-ignore: + - .mailmap + - '**.md' + - AUTHORS + - doc/** + - .github/** + - '!.github/workflows/ubsan-asan.yml' + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +env: + PYTHON_VERSION: '3.11' + FLAKY_TESTS: keep_retrying + +permissions: + contents: read + +jobs: + test-ubsan: + if: github.event.pull_request.draft == false + runs-on: ubuntu-20.04 + env: + CC: clang + CXX: clang++ + LINK: clang++ + CONFIG_FLAGS: --enable-ubsan + UBSAN_OPTIONS: supressions=supressions.supp:print_stacktrace=1 + steps: + - uses: actions/checkout@v3 + with: + persist-credentials: false + - name: Set up Python ${{ env.PYTHON_VERSION }} + uses: actions/setup-python@v4 + with: + python-version: ${{ env.PYTHON_VERSION }} + - name: Environment Information + run: npx envinfo + - name: Build + run: make build-ci -j2 V=1 + - name: Test + run: make run-ci -j2 V=1 TEST_CI_ARGS="-p actions -t 300 --measure-flakiness 9" diff --git a/common.gypi b/common.gypi index 0ce5c5226d9571..e1fe36ab846530 100644 --- a/common.gypi +++ b/common.gypi @@ -2,6 +2,7 @@ 'variables': { 'configuring_node%': 0, 'asan%': 0, + 'ubsan%': 0, 'werror': '', # Turn off -Werror in V8 build. 'visibility%': 'hidden', # V8's visibility setting 'target_arch%': 'ia32', # set v8's target architecture @@ -369,6 +370,29 @@ }], ], }], + ['ubsan == 1 and OS != "mac" and OS != "zos"', { + 'cflags+': [ + '-fno-omit-frame-pointer', + '-fsanitize=undefined', + ], + 'defines': [ 'UNDEFINED_SANITIZER'], + 'cflags!': [ '-fno-omit-frame-pointer' ], + 'ldflags': [ '-fsanitize=undefined' ], + }], + ['ubsan == 1 and OS == "mac"', { + 'xcode_settings': { + 'OTHER_CFLAGS+': [ + '-fno-omit-frame-pointer', + '-fsanitize=undefined', + '-DUNDEFINED_SANITIZER' + ], + }, + 'target_conditions': [ + ['_type!="static_library"', { + 'xcode_settings': {'OTHER_LDFLAGS': ['-fsanitize=undefined']}, + }], + ], + }], ['v8_enable_pointer_compression == 1', { 'defines': [ 'V8_COMPRESS_POINTERS', diff --git a/configure.py b/configure.py index 4ebb5606be4f6c..49ab382c39cafe 100755 --- a/configure.py +++ b/configure.py @@ -710,6 +710,12 @@ default=None, help='compile for Address Sanitizer to find memory bugs') +parser.add_argument('--enable-ubsan', + action='store_true', + dest='enable_ubsan', + default=None, + help='compile for Undefined Behavior Sanitizer') + parser.add_argument('--enable-static', action='store_true', dest='enable_static', @@ -1407,6 +1413,7 @@ def configure_node(o): o['variables']['library_files'] = options.linked_module o['variables']['asan'] = int(options.enable_asan or 0) + o['variables']['ubsan'] = int(options.enable_ubsan or 0) if options.coverage: o['variables']['coverage'] = 'true' diff --git a/suppresions.supp b/suppresions.supp new file mode 100644 index 00000000000000..0315718c264b63 --- /dev/null +++ b/suppresions.supp @@ -0,0 +1 @@ +undefined-behavior:deps/icu-small/source/common/uloc_tag.cpp