Commit 74b8bba7 authored by Daniel Hosseinian's avatar Daniel Hosseinian Committed by Commit Bot

Scope Harfbuzz objects in fuzzers

Create a header, hb_scoped.h, which contains std::unique_ptr wrappings
of commonly used Harfbuzz objects that clean up the objects when they
go out of scope. Subsequently, remove calls of hb_*_destroy() functions
in harfbuzz_fuzzer.cc.

Bug: 1046803
Change-Id: Icbc13201f77336fe3f7e0f6c9191a0e52c2f76cf
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2034111
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: default avatarBen Wagner <bungeman@chromium.org>
Reviewed-by: default avatarDominik Röttsches <drott@chromium.org>
Cr-Commit-Position: refs/heads/master@{#738447}
parent 141ee7b1
...@@ -314,9 +314,17 @@ if (use_system_harfbuzz) { ...@@ -314,9 +314,17 @@ if (use_system_harfbuzz) {
} }
} }
source_set("hb_scoped_util") {
sources = [ "utils/hb_scoped.h" ]
deps = [ "//third_party:freetype_harfbuzz" ]
}
fuzzer_test("harfbuzz_fuzzer") { fuzzer_test("harfbuzz_fuzzer") {
sources = [ "fuzz/harfbuzz_fuzzer.cc" ] sources = [ "fuzz/harfbuzz_fuzzer.cc" ]
deps = [ "//third_party:freetype_harfbuzz" ] deps = [
":hb_scoped_util",
"//third_party:freetype_harfbuzz",
]
libfuzzer_options = [ "max_len=16800" ] libfuzzer_options = [ "max_len=16800" ]
seed_corpus = "fuzz/seed_corpus" seed_corpus = "fuzz/seed_corpus"
} }
...@@ -9,38 +9,34 @@ ...@@ -9,38 +9,34 @@
#include <hb.h> #include <hb.h>
#include <hb-ot.h> #include <hb-ot.h>
// Entry point for LibFuzzer. #include "third_party/harfbuzz-ng/utils/hb_scoped.h"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
const char* dataPtr = reinterpret_cast<const char*>(data); const char* data_ptr = reinterpret_cast<const char*>(data);
hb_blob_t* blob = hb_blob_create(dataPtr, size, HB_MEMORY_MODE_READONLY, NULL, HbScoped<hb_blob_t> blob(hb_blob_create(
NULL); data_ptr, size, HB_MEMORY_MODE_READONLY, nullptr, nullptr));
hb_face_t* face = hb_face_create(blob, 0); HbScoped<hb_face_t> face(hb_face_create(blob.get(), 0));
hb_font_t* font = hb_font_create(face); HbScoped<hb_font_t> font(hb_font_create(face.get()));
hb_ot_font_set_funcs(font); hb_ot_font_set_funcs(font.get());
hb_font_set_scale(font, 12, 12); hb_font_set_scale(font.get(), 12, 12);
{ {
const char text[] = "ABCDEXYZ123@_%&)*$!"; const char text[] = "ABCDEXYZ123@_%&)*$!";
hb_buffer_t* buffer = hb_buffer_create(); HbScoped<hb_buffer_t> buffer(hb_buffer_create());
hb_buffer_add_utf8(buffer, text, -1, 0, -1); hb_buffer_add_utf8(buffer.get(), text, -1, 0, -1);
hb_buffer_guess_segment_properties(buffer); hb_buffer_guess_segment_properties(buffer.get());
hb_shape(font, buffer, NULL, 0); hb_shape(font.get(), buffer.get(), nullptr, 0);
hb_buffer_destroy(buffer);
} }
uint32_t text32[16] = { 0 }; uint32_t text32[16] = {0};
if (size > sizeof(text32)) { if (size > sizeof(text32)) {
memcpy(text32, data + size - sizeof(text32), sizeof(text32)); memcpy(text32, data + size - sizeof(text32), sizeof(text32));
hb_buffer_t* buffer = hb_buffer_create(); HbScoped<hb_buffer_t> buffer(hb_buffer_create());
size_t text32len = sizeof(text32) / sizeof(text32[0]); size_t text32_len = sizeof(text32) / sizeof(text32[0]);
hb_buffer_add_utf32(buffer, text32, text32len, 0, -1); hb_buffer_add_utf32(buffer.get(), text32, text32_len, 0, -1);
hb_buffer_guess_segment_properties(buffer); hb_buffer_guess_segment_properties(buffer.get());
hb_shape(font, buffer, NULL, 0); hb_shape(font.get(), buffer.get(), nullptr, 0);
hb_buffer_destroy(buffer);
} }
hb_font_destroy(font);
hb_face_destroy(face);
hb_blob_destroy(blob);
return 0; return 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.
#ifndef THIRD_PARTY_HARFBUZZ_NG_UTILS_HB_SCOPED_H_
#define THIRD_PARTY_HARFBUZZ_NG_UTILS_HB_SCOPED_H_
// clang-format off
#include <hb.h>
#include <hb-subset.h>
// clang-format on
#include <memory>
#include <type_traits>
template <typename T>
struct always_false : std::false_type {};
template <class T>
struct HbSpecializedDeleter {
inline void operator()(T* obj) {
static_assert(always_false<T>::value,
"HbScoped is only allowed for HarfBuzz types that have a "
"deleter specialization.");
}
};
// Defines a scoped pointer type HbScoped based on std::unique_ptr, using the
// corresponsing HarfBuzz destructors to commonly used public HarfBuzz types.
// The interface of HbScoped is the same as that of std::unique_ptr.
//
// void MyFunction() {
// HbScoped<hb_blob_t> scoped_harfbuzz_blob(
// hb_blob_create(mydata, mylength));
//
// DoSomethingWithBlob(scoped_harfbuzz_blob.get());
// }
//
// When |scoped_harfbuzz_buffer| goes out of scope, hb_blob_destroy() is called
// for the hb_blob_t* created from hb_blob_create().
template <class T>
using HbScoped = std::unique_ptr<T, HbSpecializedDeleter<T>>;
#define SPECIALIZED_DELETER_FOR_HARFBUZZ_TYPE(TYPE, DESTRUCTOR) \
template <> \
struct HbSpecializedDeleter<TYPE> { \
inline void operator()(TYPE* obj) { DESTRUCTOR(obj); } \
};
#define HB_TYPE_DESTRUCTOR_PAIRS_REPEAT(F) \
F(hb_blob_t, hb_blob_destroy) \
F(hb_buffer_t, hb_buffer_destroy) \
F(hb_face_t, hb_face_destroy) \
F(hb_font_t, hb_font_destroy) \
F(hb_set_t, hb_set_destroy) \
F(hb_subset_input_t, hb_subset_input_destroy)
HB_TYPE_DESTRUCTOR_PAIRS_REPEAT(SPECIALIZED_DELETER_FOR_HARFBUZZ_TYPE)
#endif // THIRD_PARTY_HARFBUZZ_NG_UTILS_HB_SCOPED_H_
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