Skip to content

Commit

Permalink
[ozone/wayland] fuzzer for wayland buffer manager is introduced
Browse files Browse the repository at this point in the history
Change-Id: I5d7944d1bcc9780f072f946387f414ecb0c7d96d
  • Loading branch information
alex-voodoo authored and msisov committed Feb 4, 2019
1 parent 1497249 commit 6ac4d77
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 11 deletions.
26 changes: 22 additions & 4 deletions ui/ozone/platform/wayland/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
visibility = [ "//ui/ozone/*" ]

import("//build/config/linux/pkg_config.gni")
import("//testing/libfuzzer/fuzzer_test.gni")
import("//ui/ozone/platform/wayland/wayland.gni")

pkg_config("wayland-egl") {
Expand Down Expand Up @@ -204,6 +205,7 @@ source_set("test_support") {
"test/test_zwp_text_input_manager.h",
]

defines = [ "WL_HIDE_DEPRECATED" ]
deps = [
"//base:base",
"//skia",
Expand Down Expand Up @@ -256,9 +258,25 @@ source_set("wayland_unittests") {
if (use_xkbcommon) {
deps += [ "//ui/events/keycodes:xkb" ]
}
}

defines = [ "WL_HIDE_DEPRECATED" ]
if (use_wayland_gbm) {
defines += [ "WAYLAND_GBM" ]
}
fuzzer_test("wayland_buffer_fuzzer") {
sources = [
"wayland_buffer_fuzzer.cc"
]
deps = [
":wayland",
":test_support",
"//base/test:test_support",
"//build/config/linux/libdrm",
"//testing/gmock",
"//third_party/wayland:wayland_server",
"//third_party/wayland-protocols:linux_dmabuf_protocol",
"//third_party/wayland-protocols:text_input_protocol",
"//third_party/wayland-protocols:xdg_shell_protocol",
"//ui/gfx:test_support",
"//ui/ozone/common/linux:drm",
"//ui/ozone:platform",
]
}

4 changes: 1 addition & 3 deletions ui/ozone/platform/wayland/test/mock_buffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@ MockBuffer::MockBuffer(wl_resource* resource, std::vector<base::ScopedFD>&& fds)
: ServerObject(resource), fds_(std::move(fds)) {}

MockBuffer::~MockBuffer() {
for (auto& fd : fds_) {
LOG(WARNING) << "Will close FD: " << fd.get();
for (auto& fd : fds_)
fd.reset();
}
}

} // namespace wl
133 changes: 133 additions & 0 deletions ui/ozone/platform/wayland/wayland_buffer_fuzzer.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
// Copyright 2018 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.

// This fuzzer tests browser-side implementation of
// ozone::mojom::WaylandConnection.

#include <memory>
#include <vector>

#include <drm_fourcc.h>
#include <stddef.h>
#include <stdint.h>

#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/test/fuzzed_data_provider.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/ozone/common/linux/drm_util_linux.h"
#include "ui/ozone/platform/wayland/fake_server.h"
#include "ui/ozone/platform/wayland/wayland_connection.h"
#include "ui/ozone/platform/wayland/wayland_window.h"
#include "ui/platform_window/platform_window_delegate.h"
#include "ui/platform_window/platform_window_init_properties.h"

namespace {

// Off-class equivalent of WaylandTest::Sync.
void Sync(wl::FakeServer* server) {
DCHECK(server);

server->Resume();
base::RunLoop().RunUntilIdle();
server->Pause();
}

// Copied from ui/ozone/test/mock_platform_window_delegate.h to avoid
// dependency from the whole library (it causes link problems).
class MockPlatformWindowDelegate : public ui::PlatformWindowDelegate {
public:
MockPlatformWindowDelegate() = default;
~MockPlatformWindowDelegate() = default;

MOCK_METHOD1(OnBoundsChanged, void(const gfx::Rect& new_bounds));
MOCK_METHOD1(OnDamageRect, void(const gfx::Rect& damaged_region));
MOCK_METHOD1(DispatchEvent, void(ui::Event* event));
MOCK_METHOD0(OnCloseRequest, void());
MOCK_METHOD0(OnClosed, void());
MOCK_METHOD1(OnWindowStateChanged, void(ui::PlatformWindowState new_state));
MOCK_METHOD0(OnLostCapture, void());
MOCK_METHOD1(OnAcceleratedWidgetAvailable,
void(gfx::AcceleratedWidget widget));
MOCK_METHOD0(OnAcceleratedWidgetDestroyed, void());
MOCK_METHOD1(OnActivationChanged, void(bool active));

private:
DISALLOW_COPY_AND_ASSIGN(MockPlatformWindowDelegate);
};

} // namespace

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
base::FuzzedDataProvider data_provider(data, size);

std::vector<uint32_t> known_fourccs{
DRM_FORMAT_R8, DRM_FORMAT_GR88, DRM_FORMAT_ABGR8888,
DRM_FORMAT_XBGR8888, DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888,
DRM_FORMAT_XRGB2101010, DRM_FORMAT_XBGR2101010, DRM_FORMAT_RGB565,
DRM_FORMAT_UYVY, DRM_FORMAT_NV12, DRM_FORMAT_YVU420};

base::MessageLoopForUI message_loop;

MockPlatformWindowDelegate delegate;
std::unique_ptr<ui::WaylandConnection> connection =
std::make_unique<ui::WaylandConnection>();
std::unique_ptr<ui::WaylandWindow> window =
std::make_unique<ui::WaylandWindow>(&delegate, connection.get());
gfx::AcceleratedWidget widget = gfx::kNullAcceleratedWidget;

wl::FakeServer server;
CHECK(server.Start(6));
CHECK(connection->Initialize());

EXPECT_CALL(delegate, OnAcceleratedWidgetAvailable(testing::_))
.WillOnce(testing::SaveArg<0>(&widget));
ui::PlatformWindowInitProperties properties;
properties.bounds = gfx::Rect(0, 0, 800, 600);
properties.type = ui::PlatformWindowType::kWindow;
CHECK(window->Initialize(std::move(properties)));
CHECK_NE(widget, gfx::kNullAcceleratedWidget);

base::RunLoop().RunUntilIdle();
server.Pause();

base::FilePath temp_path;
EXPECT_TRUE(base::CreateTemporaryFile(&temp_path));
base::File temp(temp_path,
base::File::FLAG_WRITE | base::File::FLAG_CREATE_ALWAYS);

uint32_t width = data_provider.ConsumeIntegralInRange(1U, 10000U);
uint32_t height = data_provider.ConsumeIntegralInRange(1U, 10000U);
uint32_t planes_count = data_provider.ConsumeIntegralInRange(1U, 10000U);
uint32_t format = known_fourccs[data_provider.ConsumeIntegralInRange(
0UL, known_fourccs.size() - 1)];
std::vector<uint32_t> strides(planes_count);
std::vector<uint32_t> offsets(planes_count);
std::vector<uint64_t> modifiers(planes_count);
for (uint32_t i = 0; i < planes_count; ++i) {
strides[i] = data_provider.ConsumeIntegralInRange(1U, UINT_MAX);
offsets[i] = data_provider.ConsumeIntegralInRange(0U, UINT_MAX);
modifiers[i] =
data_provider.ConsumeIntegralInRange(uint64_t(0), UINT64_MAX);
}

const uint32_t kBufferId = 1;

connection->CreateZwpLinuxDmabuf(std::move(temp), width, height, strides,
offsets, format, modifiers, planes_count,
kBufferId);

Sync(&server);
Sync(&server);

connection->DestroyZwpLinuxDmabuf(kBufferId);

Sync(&server);
Sync(&server);

return 0;
}
8 changes: 6 additions & 2 deletions ui/ozone/platform/wayland/wayland_buffer_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,19 @@ WaylandBufferManager::WaylandBufferManager(
zwp_linux_dmabuf_v1* zwp_linux_dmabuf,
WaylandConnection* connection)
: zwp_linux_dmabuf_(zwp_linux_dmabuf), connection_(connection) {
DCHECK(zwp_linux_dmabuf_);
DCHECK(connection_);

static const zwp_linux_dmabuf_v1_listener dmabuf_listener = {
&WaylandBufferManager::Format, &WaylandBufferManager::Modifiers,
&WaylandBufferManager::Format,
&WaylandBufferManager::Modifiers,
};
zwp_linux_dmabuf_v1_add_listener(zwp_linux_dmabuf_.get(), &dmabuf_listener,
this);

// A roundtrip after binding guarantees that the client has received all
// supported formats.
wl_display_roundtrip(connection->display());
wl_display_roundtrip(connection_->display());
}

WaylandBufferManager::~WaylandBufferManager() {
Expand Down
7 changes: 5 additions & 2 deletions ui/ozone/platform/wayland/wayland_connection.cc
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ WaylandConnection::~WaylandConnection() = default;

bool WaylandConnection::Initialize() {
static const wl_registry_listener registry_listener = {
&WaylandConnection::Global, &WaylandConnection::GlobalRemove,
&WaylandConnection::Global,
&WaylandConnection::GlobalRemove,
};

display_.reset(wl_display_connect(nullptr));
Expand Down Expand Up @@ -193,6 +194,7 @@ void WaylandConnection::CreateZwpLinuxDmabuf(
uint32_t planes_count,
uint32_t buffer_id) {
DCHECK(base::MessageLoopCurrentForUI::IsSet());
DCHECK(buffer_manager_);
if (!buffer_manager_->CreateBuffer(std::move(file), width, height, strides,
offsets, format, modifiers, planes_count,
buffer_id)) {
Expand Down Expand Up @@ -364,7 +366,8 @@ void WaylandConnection::Global(void* data,
const char* interface,
uint32_t version) {
static const wl_seat_listener seat_listener = {
&WaylandConnection::Capabilities, &WaylandConnection::Name,
&WaylandConnection::Capabilities,
&WaylandConnection::Name,
};
static const xdg_shell_listener shell_listener = {
&WaylandConnection::Ping,
Expand Down

0 comments on commit 6ac4d77

Please sign in to comment.