[PDF Ink Signatures] Add pdf_ink_reader_fuzzer to fuzz libtess2 code
Add a new fuzzer using FUZZ_TEST to indirectly fuzz libtess2 code. Since the production code in pdfium_ink_reader.cc executes libtess2 code by calling ink::CreateMeshFromPolyline(), try to fuzz that. Except the code has some trouble with extreme float point values. To avoid that, add a CreateInkMeshFromPolyline() wrapper, which rejects extreme values, and use that inside of pdfium_ink_reader.cc. Then expose it in pdfium_ink_reader.h as CreateInkMeshFromPolylineForTesting(), and fuzz that. Bug: 339682315 Low-Coverage-Reason: COVERAGE_UNDERREPORTED Fuzzer not being counted? Change-Id: Ic9b2327f56e07d249901d4f587d8c881eb01fe60 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5992141 Commit-Queue: Lei Zhang <thestig@chromium.org> Reviewed-by: Adrian Taylor <adetaylor@google.com> Reviewed-by: Paul Semel <paulsemel@chromium.org> Reviewed-by: Alan Screen <awscreen@chromium.org> Cr-Commit-Position: refs/heads/main@{#1379811}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
c1eeb671c5
commit
b8162a9b38
12
pdf/BUILD.gn
12
pdf/BUILD.gn
@ -554,6 +554,18 @@ if (enable_pdf) {
|
||||
"//base",
|
||||
]
|
||||
}
|
||||
|
||||
if (enable_pdf_ink2) {
|
||||
test("pdf_ink_reader_fuzzer") {
|
||||
fuzztests = [ "PdfInkReaderFuzzer.CreateMeshFromPolylineDoesntCrash" ]
|
||||
sources = [ "pdfium/pdfium_ink_reader_fuzzer.cc" ]
|
||||
deps = [
|
||||
":internal",
|
||||
"//third_party/fuzztest:fuzztest_gtest_main",
|
||||
"//third_party/ink",
|
||||
]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
# Dummy groups when PDF support is disabled so targets can unconditionally
|
||||
# depend on it.
|
||||
|
@ -12,6 +12,12 @@ namespace chrome_pdf {
|
||||
// Signature for "V2" PDF page objects. Do not change.
|
||||
inline constexpr char kInkAnnotationIdentifierKeyV2[] = "GOOG:INKIsInker";
|
||||
|
||||
// Since PDFium does not support UserUnit, this is the maximum possible PDF
|
||||
// dimension.
|
||||
// TODO(crbug.com/42271703): If the bug gets fixed, update the code that assumes
|
||||
// this is the limit.
|
||||
inline constexpr int kMaxPdfDimensionInches = 200;
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
||||
#endif // PDF_PDF_INK_CONSTANTS_H_
|
||||
|
@ -6,3 +6,9 @@ include_rules = [
|
||||
"+ui/accessibility",
|
||||
"+ui/gfx/codec",
|
||||
]
|
||||
|
||||
specific_include_rules = {
|
||||
".*_fuzzer\.cc": [
|
||||
"+third_party/fuzztest",
|
||||
],
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "pdf/pdf_ink_conversions.h"
|
||||
#include "pdf/pdf_ink_transform.h"
|
||||
#include "pdf/pdfium/pdfium_api_wrappers.h"
|
||||
#include "printing/units.h"
|
||||
#include "third_party/ink/src/ink/geometry/mesh.h"
|
||||
#include "third_party/ink/src/ink/geometry/modeled_shape.h"
|
||||
#include "third_party/ink/src/ink/geometry/point.h"
|
||||
@ -63,6 +64,30 @@ ink::Point GetTransformedInkPoint(const gfx::AxisTransform2d& transform,
|
||||
return InkPointFromGfxPoint(transform.MapPoint(point));
|
||||
}
|
||||
|
||||
// Wrapper around ink::CreateMeshFromPolyline() to convert `polyline` into an
|
||||
// ink::Mesh. It applies an additional check to make sure the points in
|
||||
// `polyline` have sane values.
|
||||
std::optional<ink::Mesh> CreateInkMeshFromPolyline(
|
||||
const std::vector<ink::Point>& polyline) {
|
||||
// Limit for ink::Point values in pixels. It is divided by 2 because the limit
|
||||
// extends half way in the negative range.
|
||||
constexpr int kInkPointDimensionLimit =
|
||||
kMaxPdfDimensionInches * printing::kPixelsPerInch / 2;
|
||||
for (const auto& pt : polyline) {
|
||||
if (pt.x < -kInkPointDimensionLimit || pt.x > kInkPointDimensionLimit ||
|
||||
pt.y < -kInkPointDimensionLimit || pt.y > kInkPointDimensionLimit) {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
auto mesh = ink::CreateMeshFromPolyline(polyline);
|
||||
if (!mesh.ok()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return *mesh;
|
||||
}
|
||||
|
||||
// Creates an ink::Mesh from `polyline`. If it is valid, append it to `meshes`.
|
||||
void AppendPolylineToMeshesList(std::vector<ink::Mesh>& meshes,
|
||||
const std::vector<ink::Point>& polyline) {
|
||||
@ -170,4 +195,9 @@ std::vector<ReadV2InkPathResult> ReadV2InkPathsFromPageAsModeledShapes(
|
||||
return results;
|
||||
}
|
||||
|
||||
std::optional<ink::Mesh> CreateInkMeshFromPolylineForTesting( // IN-TEST
|
||||
const std::vector<ink::Point>& polyline) {
|
||||
return CreateInkMeshFromPolyline(polyline);
|
||||
}
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
@ -5,10 +5,13 @@
|
||||
#ifndef PDF_PDFIUM_PDFIUM_INK_READER_H_
|
||||
#define PDF_PDFIUM_PDFIUM_INK_READER_H_
|
||||
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include "pdf/buildflags.h"
|
||||
#include "third_party/ink/src/ink/geometry/mesh.h"
|
||||
#include "third_party/ink/src/ink/geometry/modeled_shape.h"
|
||||
#include "third_party/ink/src/ink/geometry/point.h"
|
||||
#include "third_party/pdfium/public/fpdfview.h"
|
||||
|
||||
static_assert(BUILDFLAG(ENABLE_PDF_INK2), "ENABLE_PDF_INK2 not set to true");
|
||||
@ -32,6 +35,10 @@ struct ReadV2InkPathResult {
|
||||
std::vector<ReadV2InkPathResult> ReadV2InkPathsFromPageAsModeledShapes(
|
||||
FPDF_PAGE page);
|
||||
|
||||
// Exposes internal CreateInkMeshFromPolyline() for testing.
|
||||
std::optional<ink::Mesh> CreateInkMeshFromPolylineForTesting(
|
||||
const std::vector<ink::Point>& polyline);
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
||||
#endif // PDF_PDFIUM_PDFIUM_INK_READER_H_
|
||||
|
31
pdf/pdfium/pdfium_ink_reader_fuzzer.cc
Normal file
31
pdf/pdfium/pdfium_ink_reader_fuzzer.cc
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2024 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "pdf/pdfium/pdfium_ink_reader.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "third_party/fuzztest/src/fuzztest/fuzztest.h"
|
||||
#include "third_party/ink/src/ink/geometry/point.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
namespace {
|
||||
|
||||
fuzztest::Domain<ink::Point> FiniteInkPoint() {
|
||||
return fuzztest::StructOf<ink::Point>(fuzztest::Finite<float>(),
|
||||
fuzztest::Finite<float>());
|
||||
}
|
||||
|
||||
void CreateMeshFromPolylineDoesntCrash(
|
||||
const std::vector<ink::Point>& polyline) {
|
||||
auto mesh = CreateInkMeshFromPolylineForTesting(polyline);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
FUZZ_TEST(PdfInkReaderFuzzer, CreateMeshFromPolylineDoesntCrash)
|
||||
.WithDomains(fuzztest::VectorOf(FiniteInkPoint()));
|
||||
|
||||
} // namespace chrome_pdf
|
Reference in New Issue
Block a user