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

Add support for recognizing crashes in native extensions #737

Open
PaDarochek opened this issue Dec 26, 2023 · 0 comments
Open

Add support for recognizing crashes in native extensions #737

PaDarochek opened this issue Dec 26, 2023 · 0 comments

Comments

@PaDarochek
Copy link

PaDarochek commented Dec 26, 2023

Description

I tried to apply Jazzer.js to fuzzing JS code extended with C++ code. C++ code was binded to JS code via Napi and was instrumented with sanitizers (e.g. ASan). I've found out that even if reports from sanitizers are displayed, these crashes are not considered to be crashes and are not saved to any files.

Screenshot from 2023-12-26 16-54-10
Screenshot from 2023-12-26 16-54-27

Could you please support recognizing these crashes the same way as JS crashes?

Steps to reproduce

  • Create fuzz target (native_fuzzer.js) from the code:
    #!/usr/bin/env -S npx jazzer
    
    const native_lib = require('bindings')('native')
    
    function fuzz(data) {
        if (data[0] > 'x') {
            native_lib.foo(5);
        } else if (data[1] > 'x') {
            native_lib.foo(2);
        }
    }
    
    module.exports.fuzz = function (data /*: Buffer */) {
        const fuzzerData = data.toString();
        fuzz(fuzzerData);
    };
  • Create native library file:
    #include <napi.h>
    #include <stdio.h>
    
    void
    foo(const Napi::CallbackInfo& info)
    {
        Napi::Env env = info.Env();
        if (info.Length() < 1)
        {
            Napi::TypeError::New(env, "Wrong number of arguments")
                .ThrowAsJavaScriptException();
        }
        if (!info[0].IsNumber())
        {
            Napi::TypeError::New(env, "Wrong arguments")
                .ThrowAsJavaScriptException();
        }
        uint32_t idx = info[0].As<Napi::Number>().Uint32Value();
    
        uint8_t buf[] = {1, 2, 3};
        Napi::Buffer<uint8_t> arr = Napi::Buffer<uint8_t>::New(env, &buf[0], 3);
    
        arr[idx] = 1;
        printf("Number: %u\n", arr[idx]);
    }
    
    Napi::Object
    init(Napi::Env env, Napi::Object exports)
    {
        exports.Set(Napi::String::New(env, "foo"), Napi::Function::New(env, foo));
        return exports;
    };
    
    NODE_API_MODULE(native, init);
  • Create binding file:
    {
        "targets": [
            {
                "cflags": [ "-fexceptions -fsanitize=address,fuzzer-no-link,undefined -O0 -g -fPIC" ],
                "cflags_cc": [ "-fexceptions -fsanitize=address,fuzzer-no-link,undefined -O0 -g -fPIC" ],
                "include_dirs" : ["<!@(node -p \"require('node-addon-api').include\")"],
                "target_name": "native",
                "sources": [ "native.cpp" ],
                'defines': [ 'NAPI_CPP_EXCEPTIONS' ]
            }
        ]
    }
  • Install required packages and build fuzz target in the current directory:
    CC=clang CXX=clang++ npm init -y
    npm install node-addon-api bindings
    CC=clang CXX=clang++ node install .
  • Launch Jazzer.js with the following arguments:
      ASAN_OPTIONS="abort_on_error=1,allocator_may_return_null=1,detect_leaks=0,hard_rss_limit_mb=0,malloc_context_size=0" LD_PRELOAD="$(clang++ -print-file-name=libclang_rt.asan-x86_64.so)" ./native_fuzzer.js ./corpus -- -artifact_prefix=./crashes/ -use_value_profile=1 -verbosity=2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant