chromium/testing/libfuzzer/fuzzers/BUILD.gn

# Copyright 2015 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# Individual libfuzzer tests that didn't find their home yet.

import("//build/config/features.gni")
import("//testing/libfuzzer/fuzzer_test.gni")
import("//third_party/protobuf/proto_library.gni")
import("//ui/gl/features.gni")
import("//v8/gni/v8.gni")

# root BUILD depends on this target. Needed for package discovery
group("fuzzers") {
}

fuzzer_test("empty_fuzzer") {
  sources = [ "empty_fuzzer.cc" ]
  additional_configs = [ "//testing/libfuzzer:no_clusterfuzz" ]
}

fuzzer_test("string_compare_fuzzer") {
  sources = [ "string_compare_fuzzer.cc" ]
  additional_configs = [ "//testing/libfuzzer:no_clusterfuzz" ]
}

fuzzer_test("string_compare_proto_fuzzer") {
  sources = [ "string_compare_proto_fuzzer.cc" ]
  deps = [
    "//testing/libfuzzer/proto:string_compare_proto",
    "//third_party/libprotobuf-mutator",
  ]
  additional_configs = [ "//testing/libfuzzer:no_clusterfuzz" ]
}

fuzzer_test("snappy_compress_fuzzer") {
  sources = [ "snappy_compress_fuzzer.cc" ]
  deps = [ "//third_party/snappy:snappy" ]
  seed_corpus = "//third_party/snappy/src/testdata"
}

fuzzer_test("snappy_uncompress_fuzzer") {
  sources = [ "snappy_uncompress_fuzzer.cc" ]
  deps = [ "//third_party/snappy:snappy" ]
  seed_corpus = "//third_party/snappy/src/testdata"
}

fuzzer_test("template_url_parser_fuzzer") {
  sources = [ "template_url_parser_fuzzer.cc" ]
  deps = [
    "//base",
    "//base:i18n",
    "//components/search_engines",
    "//mojo/core/embedder",
    "//services/data_decoder/public/cpp",
    "//services/data_decoder/public/cpp:test_support",
    "//third_party/libxml:libxml",
  ]
  dict = "//third_party/libxml/fuzz/xml.dict"
  libfuzzer_options = [ "max_len=4096" ]
}

fuzzer_test("url_parse_proto_fuzzer") {
  sources = [ "url_parse_proto_fuzzer.cc" ]
  deps = [
    "//base",
    "//base:i18n",
    "//testing/libfuzzer/proto:url_proto",
    "//third_party/libprotobuf-mutator",
    "//url:url",
  ]
}

fuzzer_test("libsrtp_fuzzer") {
  sources = [ "libsrtp_fuzzer.cc" ]
  deps = [ "//third_party/libsrtp" ]
  libfuzzer_options = [ "max_len=1500" ]
}

libpng_seed_corpuses = [
  "//components/test/data/viz",
  "//third_party/blink/web_tests/images/png-suite/samples",
  "//third_party/blink/web_tests/images/resources/pngfuzz",
]

fuzzer_test("gfx_png_image_fuzzer") {
  sources = [ "gfx_png_image_fuzzer.cc" ]
  deps = [
    "//base",
    "//ui/base",
    "//ui/gfx",
  ]
  dict = "dicts/png.dict"
  seed_corpuses = libpng_seed_corpuses
}

fuzzer_test("libxml_xml_read_memory_fuzzer") {
  sources = [ "libxml_xml_read_memory_fuzzer.cc" ]
  deps = [ "//third_party/libxml:libxml" ]
  dict = "//third_party/libxml/fuzz/xml.dict"
  seed_corpus = "//third_party/libxml/fuzz/seed_corpus"
}

fuzzer_test("libpng_progressive_read_fuzzer") {
  sources = [ "libpng_read_fuzzer.cc" ]
  deps = [
    "//base",
    "//third_party/libpng",
  ]
  dict = "dicts/png.dict"
  seed_corpuses = libpng_seed_corpuses
}

template("v8_fuzzer") {
  if (defined(invoker.v8_dep)) {
    _deps = [ "//v8:${invoker.v8_dep}" ]
  } else {
    _deps = [ "//v8:${target_name}" ]
  }

  fuzzer_test("v8_${target_name}") {
    forward_variables_from(invoker,
                           "*",
                           [
                             "v8_dep",
                             "max_len",
                           ])

    sources = []
    deps = _deps
    if (defined(invoker.max_len)) {
      if (!defined(libfuzzer_options)) {
        libfuzzer_options = []
      }
      libfuzzer_options += [ "max_len=${invoker.max_len}" ]
    }

    asan_options = [
      "allow_user_segv_handler=1",
      "handle_sigtrap=1",
    ]
    msan_options = [ "handle_sigtrap=1" ]
    ubsan_options = [
      "handle_sigtrap=1",
      "handle_segv=1",
    ]
    environment_variables = [ "AFL_DRIVER_DONT_DEFER=1" ]
  }
}

v8_fuzzer("script_parser_fuzzer") {
  v8_dep = "parser_fuzzer"
  dict = "dicts/generated/javascript.dict"
  seed_corpus = "//v8/test/mjsunit/regress/"
  libfuzzer_options = [ "only_ascii=1" ]
}

v8_inspector_fuzzer_corpus_dir = "$target_gen_dir/v8_inspector_fuzzer_corpus"

action("generate_v8_inspector_fuzzer_corpus") {
  script = "generate_v8_inspector_fuzzer_corpus.py"
  sources = [ "generate_v8_inspector_fuzzer_corpus.py" ]
  args = [
    rebase_path("//v8/test/inspector/", root_build_dir),
    rebase_path(v8_inspector_fuzzer_corpus_dir, root_build_dir),
  ]
  outputs = [ v8_inspector_fuzzer_corpus_dir ]
}

v8_fuzzer("inspector_fuzzer") {
  dict = "dicts/generated/javascript.dict"
  seed_corpus = v8_inspector_fuzzer_corpus_dir
  seed_corpus_deps = [ ":generate_v8_inspector_fuzzer_corpus" ]

  # The fuzzer is able to handle any input, but since the input is interpreted
  # as JS code, restricting to ascii only will increase fuzzing efficiency.
  libfuzzer_options = [ "only_ascii=1" ]
}

v8_fuzzer("json_parser_fuzzer") {
  v8_dep = "json_fuzzer"
  dict = "dicts/json.dict"
}

v8_fuzzer("regexp_parser_fuzzer") {
  v8_dep = "regexp_fuzzer"
  dict = "dicts/regexp.dict"
  seed_corpus = "//v8/test/fuzzer/regexp/"
  libfuzzer_options = [ "max_len=64" ]
}

if (v8_enable_webassembly) {
  v8_fuzzer("multi_return_fuzzer") {
  }

  v8_fuzzer("wasm_code_fuzzer") {
    max_len = 500
  }

  v8_fuzzer("wasm_fuzzer") {
    max_len = 500
    seed_corpus = "//testing/libfuzzer/fuzzers/wasm_corpus/"
  }

  v8_fuzzer("wasm_async_fuzzer") {
    max_len = 500
    seed_corpus = "//testing/libfuzzer/fuzzers/wasm_corpus/"
  }

  v8_fuzzer("wasm_streaming_fuzzer") {
    max_len = 500
    seed_corpus = "//testing/libfuzzer/fuzzers/wasm_corpus/"
  }

  # These fuzzers are not supported in official builds as they depend on
  # functionality in the v8 library that is skipped in official builds for
  # binary size reasons.
  if (!is_official_build) {
    v8_fuzzer("wasm_compile_all_fuzzer") {
      max_len = 500
    }

    v8_fuzzer("wasm_compile_fuzzer") {
      max_len = 500
    }

    v8_fuzzer("wasm_compile_simd_fuzzer") {
      max_len = 500
    }

    v8_fuzzer("wasm_compile_wasmgc_fuzzer") {
      max_len = 500
    }

    v8_fuzzer("wasm_init_expr_fuzzer") {
      max_len = 500
    }

    v8_fuzzer("wasm_deopt_fuzzer") {
      max_len = 500
    }
  }
}

fuzzer_test("convert_woff2ttf_fuzzer") {
  sources = [ "convert_woff2ttf_fuzzer.cc" ]
  deps = [ "//third_party/woff2:woff2_dec" ]
  seed_corpus = "//testing/libfuzzer/fuzzers/woff2_corpus"
  libfuzzer_options = [ "max_len=803500" ]
}

fuzzer_test("flatbuffers_verifier_fuzzer") {
  sources = [ "flatbuffers_verifier_fuzzer.cc" ]
  deps = [
    "//third_party/flatbuffers",
    "//third_party/flatbuffers:flatbuffers_samplebuffer",
  ]
  libfuzzer_options = [ "max_len=1024" ]
  seed_corpus = "//testing/libfuzzer/fuzzers/flatbuffers_corpus"
}

fuzzer_test("skia_path_fuzzer") {
  sources = [
    "skia_path_common.cc",
    "skia_path_common.h",
    "skia_path_fuzzer.cc",
  ]
  deps = [
    "//base",
    "//skia",
  ]
  libfuzzer_options = [ "max_len=256" ]
  if (is_debug) {
    # Disabled due to crashing on SkASSERT (crbug.com/642750, crbug.com/643275).
    additional_configs = [ "//testing/libfuzzer:no_clusterfuzz" ]
  }
}

fuzzer_test("skia_pathop_fuzzer") {
  sources = [
    "skia_path_common.cc",
    "skia_path_common.h",
    "skia_pathop_fuzzer.cc",
  ]
  deps = [
    "//base",
    "//skia",
  ]
  libfuzzer_options = [ "max_len=512" ]
  if (is_debug) {
    # Disabled due to crashing on SkASSERT (crbug.com/642750, crbug.com/643275).
    additional_configs = [ "//testing/libfuzzer:no_clusterfuzz" ]
  }
}

fuzzer_test("prtime_fuzzer") {
  sources = [ "prtime_fuzzer.cc" ]
  deps = [ "//base" ]
  dict = "dicts/prtime.dict"
  libfuzzer_options = [ "max_len=1024" ]
}

fuzzer_test("angle_translator_fuzzer") {
  sources = []
  deps = [ "//third_party/angle:translator_fuzzer" ]
  libfuzzer_options = [ "max_len=1000" ]
  dict = "dicts/webgl-glsl.dict"
}

fuzzer_test("sha1_fuzzer") {
  sources = [ "sha1_fuzzer.cc" ]
  deps = [ "//base" ]
}

fuzzer_test("hash_fuzzer") {
  sources = [ "hash_fuzzer.cc" ]
  deps = [ "//base" ]
}

action("gen_javascript_parser_proto") {
  # Only targets in this file and the top-level visibility target can
  # depend on this.
  visibility = [ ":*" ]

  script = "generate_javascript_parser_proto.py"

  sources = [ "dicts/javascript_parser_proto.dict" ]

  outputs = [
    "$target_gen_dir/javascript_parser.proto",
    "$target_gen_dir/javascript_parser_proto_to_string.cc",
  ]

  args = rebase_path(outputs, root_build_dir) +
         rebase_path(sources, root_build_dir)
}

proto_library("javascript_parser_proto") {
  sources = [ "$target_gen_dir/javascript_parser.proto" ]
  proto_deps = [ ":gen_javascript_parser_proto" ]
  proto_out_dir = ""
}

fuzzer_test("javascript_parser_proto_fuzzer") {
  generated_sources = [ "$target_gen_dir/javascript_parser_proto_to_string.cc" ]
  sources = [
    "javascript_parser_proto_fuzzer.cc",
    "javascript_parser_proto_to_string.h",
  ]
  deps = [
    ":gen_javascript_parser_proto",
    ":javascript_parser_proto",
    "//base",
    "//third_party/libprotobuf-mutator",
    "//v8:v8",
    "//v8:v8_libplatform",
  ]
}

fuzzer_test("v8_fully_instrumented_fuzzer") {
  sources = [ "v8_fuzzer.cc" ]
  deps = [
    "//base",
    "//v8:v8",
    "//v8:v8_libplatform",
  ]
  dict = "dicts/generated/javascript.dict"
  asan_options = [
    "allow_user_segv_handler=1",
    "handle_sigtrap=1",
  ]
  msan_options = [ "handle_sigtrap=1" ]
  ubsan_options = [
    "handle_sigtrap=1",
    "handle_segv=1",
  ]
  libfuzzer_options = [ "only_ascii=1" ]
}

fuzzer_test("skia_image_filter_proto_fuzzer") {
  sources = [ "skia_image_filter_proto_fuzzer.cc" ]

  deps = [
    "//base",
    "//base/test:test_support",
    "//skia",
    "//testing/libfuzzer/proto:skia_image_filter_converter",
    "//testing/libfuzzer/proto:skia_image_filter_proto",
    "//third_party/libprotobuf-mutator",
  ]
}

# We build the libyuv_scale_fuzzer both for fuzztest
# and libfuzzer, for education/comparison purposes.
# Abstract the common parts:
source_set("libyuv_scale_fuzzer_common") {
  testonly = true
  sources = [
    "libyuv_scale_fuzzer.cc",
    "libyuv_scale_fuzzer.h",
  ]

  public_deps = [ "//third_party/libyuv" ]
}

# The libfuzzer version (which also works with other compatible
# frameworks, e.g. centipede)
fuzzer_test("libyuv_scale_fuzzer") {
  sources = [ "libyuv_scale_fuzzer_libfuzzer.cc" ]
  deps = [ ":libyuv_scale_fuzzer_common" ]
}

# This is a fuzztest fuzzer, which (for now) means we build this as
# a unit test rather than using a fuzzing gn template such as
# fuzzer_test.
# This executable can be run in four modes:
# modes:
# ./libyuv_scale_fuzzer - runs a small amount of fuzzing as if
#    to fit in with a unit test framework, just to look for
#    egregious bugs
# With the enable_fuzztest_fuzz gn arg:
#   ./libyuv_scale_fuzzer -fuzz=    - fuzzes properly.
# With the use_centipede gn arg:
#   centipede --binary=libyuv_scale_fuzzer - fuzzes using centipede
# With the use_libfuzzer gn arg:
#   ./libyuv_scale_fuzzer - runs in a libfuzzer-compatible way
# Note that right now this is using the plain 'test' template.
# In time, we may choose a different option here.
test("libyuv_scale_fuzztest") {
  sources = [ "libyuv_scale_fuzztest.cc" ]
  fuzztests = [ "ScaleFuzz.ScaleDoesNotCrash" ]

  deps = [
    ":libyuv_scale_fuzzer_common",
    "//third_party/fuzztest:fuzztest_gtest_main",
  ]
}

test("paint_vector_icon_fuzztest") {
  sources = [ "paint_vector_icon_fuzztest.cc" ]
  fuzztests = [ "PaintVectorIconFuzzTest.PaintVectorIcon" ]

  deps = [
    "//base",
    "//skia:skia_switches",
    "//third_party/fuzztest:fuzztest_gtest_main",
    "//ui/gfx:gfx",
  ]
}

proto_library("command_buffer_lpm_fuzzer_proto") {
  sources = [ "command_buffer_lpm_fuzzer/cmd_buf_lpm_fuzz.proto" ]

  use_protobuf_full = true
  deps = [ "//third_party/protobuf:protobuf_full" ]
}

if (!is_win) {
  fuzzer_test("command_buffer_lpm_fuzzer") {
    sources = [
      "command_buffer_lpm_fuzzer/cmd_buf_lpm_fuzz.cc",
      "command_buffer_lpm_fuzzer/cmd_buf_lpm_fuzz.h",
      "command_buffer_lpm_fuzzer/webgpu_support.cc",
      "command_buffer_lpm_fuzzer/webgpu_support.h",
    ]

    # This is a hack. These files should be pulled in as a result of the
    # dependency on //gpu:webgpu which has a public dependency on
    # //gpu/command_buffer/client:webgpu_sources, but for some reason these files
    # get dropped in component builds, so manually add them to the sources here.
    if (is_component_build) {
      sources += [
        "//gpu/command_buffer/client/webgpu_implementation.cc",
        "//gpu/command_buffer/client/webgpu_implementation.h",
      ]

      if (use_dawn) {
        sources += [
          "//gpu/command_buffer/client/dawn_client_memory_transfer_service.cc",
          "//gpu/command_buffer/client/dawn_client_memory_transfer_service.h",
          "//gpu/command_buffer/client/dawn_client_serializer.cc",
          "//gpu/command_buffer/client/dawn_client_serializer.h",
        ]
      }
    }

    deps = [
      ":command_buffer_lpm_fuzzer_proto",
      "//base",
      "//base/test:test_support",
      "//build:chromeos_buildflags",
      "//components/viz/common:shared_image_format",
      "//components/viz/test:test_support",  # TODO: huge; is there something
                                             # more

      # targeted?
      "//content/public/common:static_switches",
      "//gpu:gles2",
      "//gpu:gpu",
      "//gpu:test_support",
      "//gpu:webgpu",
      "//gpu/command_buffer/client",
      "//gpu/command_buffer/client:gles2_c_lib",
      "//gpu/command_buffer/client:gles2_implementation",
      "//gpu/command_buffer/common",
      "//gpu/command_buffer/common:gles2_utils",
      "//gpu/command_buffer/service",
      "//gpu/config",
      "//gpu/ipc:gl_in_process_context",
      "//gpu/ipc/client",
      "//gpu/ipc/common",
      "//gpu/ipc/host",
      "//gpu/ipc/service:service",
      "//gpu/webgpu:common",
      "//mojo/core/embedder",
      "//mojo/core/embedder",
      "//mojo/public/cpp/bindings",
      "//testing/gmock",
      "//testing/gtest:gtest",
      "//third_party/libprotobuf-mutator",
      "//ui/gfx:gfx",
      "//ui/gl:gl",
      "//ui/gl:test_support",
      "//ui/gl/init:init",
      "//url",
    ]

    if (use_dawn) {
      deps += [
        "//third_party/dawn/include/dawn:cpp_headers",
        "//third_party/dawn/src/dawn:proc",
        "//third_party/dawn/src/dawn/native",
      ]
    }

    libfuzzer_options = [ "max_len=16384" ]
  }
}