Commit ef18ee7f authored by Daniel Hosseinian's avatar Daniel Hosseinian Committed by Commit Bot

Add hb_subset_fuzzer

Add a fuzzer for Chromium that is very closely based off of [1].

Rename harfbuzz_fuzzer to hb_shape_fuzzer. Apply some formatting
changes in hb_shape_fuzzer.cc to adhere to the Chromium style guide.

[1] https://github.com/harfbuzz/harfbuzz/blob/master/test/fuzzing/hb-subset-fuzzer.cc

Bug: 1046803
Change-Id: Ide991e12f95d6733bbd71acc265c444972b8be99
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2032170Reviewed-by: default avatarLei Zhang <thestig@chromium.org>
Reviewed-by: default avatarDominik Röttsches <drott@chromium.org>
Commit-Queue: Daniel Hosseinian <dhoss@chromium.org>
Cr-Commit-Position: refs/heads/master@{#738721}
parent fd2f77c4
...@@ -319,12 +319,22 @@ source_set("hb_scoped_util") { ...@@ -319,12 +319,22 @@ source_set("hb_scoped_util") {
deps = [ "//third_party:freetype_harfbuzz" ] deps = [ "//third_party:freetype_harfbuzz" ]
} }
fuzzer_test("harfbuzz_fuzzer") { fuzzer_test("hb_shape_fuzzer") {
sources = [ "fuzz/harfbuzz_fuzzer.cc" ] sources = [ "fuzz/hb_shape_fuzzer.cc" ]
deps = [ deps = [
":hb_scoped_util", ":hb_scoped_util",
"//base",
"//third_party:freetype_harfbuzz",
]
seed_corpus = "fuzz/seed_corpus"
}
fuzzer_test("hb_subset_fuzzer") {
sources = [ "fuzz/hb_subset_fuzzer.cc" ]
deps = [
":hb_scoped_util",
"//base",
"//third_party:freetype_harfbuzz", "//third_party:freetype_harfbuzz",
] ]
libfuzzer_options = [ "max_len=16800" ]
seed_corpus = "fuzz/seed_corpus" seed_corpus = "fuzz/seed_corpus"
} }
specific_include_rules = {
'hb_.*_fuzzer\.cc': [
'+base',
],
}
...@@ -6,12 +6,20 @@ ...@@ -6,12 +6,20 @@
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
// clang-format off
#include <hb.h> #include <hb.h>
#include <hb-ot.h> #include <hb-ot.h>
// clang-format on
#include "base/stl_util.h"
#include "third_party/harfbuzz-ng/utils/hb_scoped.h" #include "third_party/harfbuzz-ng/utils/hb_scoped.h"
constexpr size_t kMaxInputLength = 16800;
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
if (size > kMaxInputLength)
return 0;
const char* data_ptr = reinterpret_cast<const char*>(data); const char* data_ptr = reinterpret_cast<const char*>(data);
HbScoped<hb_blob_t> blob(hb_blob_create( HbScoped<hb_blob_t> blob(hb_blob_create(
data_ptr, size, HB_MEMORY_MODE_READONLY, nullptr, nullptr)); data_ptr, size, HB_MEMORY_MODE_READONLY, nullptr, nullptr));
...@@ -32,8 +40,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { ...@@ -32,8 +40,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
if (size > sizeof(text32)) { if (size > sizeof(text32)) {
memcpy(text32, data + size - sizeof(text32), sizeof(text32)); memcpy(text32, data + size - sizeof(text32), sizeof(text32));
HbScoped<hb_buffer_t> buffer(hb_buffer_create()); HbScoped<hb_buffer_t> buffer(hb_buffer_create());
size_t text32_len = sizeof(text32) / sizeof(text32[0]); hb_buffer_add_utf32(buffer.get(), text32, base::size(text32), 0, -1);
hb_buffer_add_utf32(buffer.get(), text32, text32_len, 0, -1);
hb_buffer_guess_segment_properties(buffer.get()); hb_buffer_guess_segment_properties(buffer.get());
hb_shape(font.get(), buffer.get(), nullptr, 0); hb_shape(font.get(), buffer.get(), nullptr, 0);
} }
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stddef.h>
#include <stdint.h>
#include <string.h>
// clang-format off
#include <hb.h>
#include <hb-subset.h>
// clang-format on
#include "base/logging.h"
#include "base/stl_util.h"
#include "third_party/harfbuzz-ng/utils/hb_scoped.h"
namespace {
void TrySubset(hb_face_t* face,
const hb_codepoint_t text[],
const int text_length,
const uint8_t flags) {
bool drop_hints = flags & (1 << 0);
bool drop_layout = flags & (1 << 1);
bool retain_gids = flags & (1 << 2);
HbScoped<hb_subset_input_t> input(hb_subset_input_create_or_fail());
hb_subset_input_set_drop_hints(input.get(), drop_hints);
hb_subset_input_set_retain_gids(input.get(), retain_gids);
hb_set_t* codepoints = hb_subset_input_unicode_set(input.get());
if (!drop_layout) {
hb_set_del(hb_subset_input_drop_tables_set(input.get()),
HB_TAG('G', 'S', 'U', 'B'));
hb_set_del(hb_subset_input_drop_tables_set(input.get()),
HB_TAG('G', 'P', 'O', 'S'));
hb_set_del(hb_subset_input_drop_tables_set(input.get()),
HB_TAG('G', 'D', 'E', 'F'));
}
for (int i = 0; i < text_length; i++) {
hb_set_add(codepoints, text[i]);
}
HbScoped<hb_face_t> result(hb_subset(face, input.get()));
HbScoped<hb_blob_t> blob(hb_face_reference_blob(result.get()));
uint32_t length;
const char* data = hb_blob_get_data(blob.get(), &length);
// Access all the blob data
uint32_t bytes_count = 0;
if (data) {
for (uint32_t i = 0; i < length; ++i) {
if (data[i])
++bytes_count;
}
}
CHECK(bytes_count || !length);
}
} // namespace
constexpr size_t kMaxInputLength = 16800;
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
if (size > kMaxInputLength)
return 0;
const char* data_ptr = reinterpret_cast<const char*>(data);
HbScoped<hb_blob_t> blob(hb_blob_create(
data_ptr, size, HB_MEMORY_MODE_READONLY, nullptr, nullptr));
HbScoped<hb_face_t> face(hb_face_create(blob.get(), 0));
// Test hb_set API
{
HbScoped<hb_set_t> output(hb_set_create());
hb_face_collect_unicodes(face.get(), output.get());
}
uint8_t subset_flags = 0;
const hb_codepoint_t text[] = {'A', 'B', 'C', 'D', 'E', 'X', 'Y',
'Z', '1', '2', '3', '@', '_', '%',
'&', ')', '*', '$', '!'};
TrySubset(face.get(), text, base::size(text), subset_flags);
hb_codepoint_t text_from_data[16];
if (size > sizeof(text_from_data) + 1) {
memcpy(text_from_data, data + size - sizeof(text_from_data),
sizeof(text_from_data));
subset_flags = data[size - sizeof(text_from_data) - 1];
size_t text_size = base::size(text_from_data);
TrySubset(face.get(), text_from_data, text_size, subset_flags);
}
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment