Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
ae6ae3c
Move ScopedLocale to core/fxcrt and use in DisplayListDeviceDriver
tsepez Oct 27, 2026
8325c53
Allow for headers with specific versions in fixup_pdf_template.py
LearnPRG-py Oct 27, 2026
17e0465
Add test for PDF 2.0 file save header issue
LearnPRG-py Oct 27, 2026
d36b525
Fix incorrect PDF major version in save header
LearnPRG-py Oct 27, 2026
8e5483c
Use fuzzy float equality in CFX_Path::GetRect()
Oct 27, 2026
b69c9b1
Remove unused buildtools/reclient from DEPS and roll script
ukai Oct 27, 2026
7a364ab
Add CPDFCreatorEmbedderTest for handling free entries
leizleiz Oct 27, 2026
7241409
Teach tools/roll_pdfium_deps.py about libyuv
leizleiz Oct 27, 2026
a5a0f99
Use display lists for FPDFTransformEmbedderTest
tsepez Oct 27, 2026
ac04d23
Roll third_party/libyuv/ eb8eda9c7..1e2e3a359 (8 commits)
leizleiz Oct 27, 2026
87bd487
Use display lists for FPDFEditPathEmbedderTest
tsepez Oct 27, 2026
57e9a26
Use display lists for FPDFEditPageEmbedderTest
tsepez Oct 27, 2026
6876f74
Actually initialize `CPDF_SyntaxParser::pool_`
leizleiz Oct 28, 2026
181518e
Use display lists for blank page checks in pattern and save tests
tsepez Oct 28, 2026
0f3d165
Use display lists for Brotli stream tests
tsepez Oct 28, 2026
efb7202
Convert remaining embedder tests to display list comparisons
tsepez Oct 28, 2026
2dbda71
Remove unused GpStream class and unused GDI+ functions
tsepez Oct 28, 2026
5b8d8c7
Enable Brotli compilation override by default
LearnPRG-py Oct 29, 2026
67cc302
Make non-const kFoo variables truly const
leizleiz Oct 29, 2026
64df52a
Test all 4 ordering variants of /ActualText for an Arabic string
Oct 29, 2026
5dfa486
Add documentation about CI/CQ and build recipes.
leizleiz Oct 29, 2026
009acc7
Fix incorrect documentation in core/fxcrt/zip.h
leizleiz Oct 29, 2026
f96a940
Fix a UNSAFE_TODO() in JpegModule::JpegEncode()
leizleiz Oct 29, 2026
b2b9e0f
Fix three additional embeddertest results on *_skia_rust CQ bots.
tsepez Oct 29, 2026
c0cb3e4
Roll third_party/skia/ 5b1a7f7c0..0abfcf118 (368 commits; 17 trivial …
leizleiz Oct 29, 2026
b435cef
Roll testing/scripts/rust/ 9c16e2f4c..9022dfb9a (1 commit)
leizleiz Oct 29, 2026
864b2eb
Roll third_party/rust/ b8c38a533..79a8603b9 (52 commits)
leizleiz Oct 29, 2026
14b34d9
Pass zero strides to libyuv for single-row operations
tsepez Oct 29, 2026
32aa2c3
Roll base/allocator/partition_allocator/ dc6144ac9..2b864a177 (50 com…
leizleiz Oct 30, 2026
df710bc
Roll abseil, buildtools and libc++
leizleiz Oct 30, 2026
dbd7017
Roll build, tools/clang and tools/rust
leizleiz Oct 30, 2026
83adc17
Fix a nit in CGdiDisplayDriver::GetDIBits()
leizleiz Oct 30, 2026
55ed4ec
[3p freshness] lcms: Roll to 2.19.1 and enable auto-update
msisov Oct 30, 2026
320708b
Enable PartitionAlloc in standalone Skia builds
ArthurSonzogni Oct 30, 2026
f475931
Add generic GCed containers in fxjs/gc/containers.h
tsepez Oct 30, 2026
4e36424
Vectorize scanline-compositor paths
amd-nithyavs Oct 30, 2026
d2c2be2
Make embedder tests more forgiving of missing FT/Skia libraries.
tsepez Oct 30, 2026
4cd9288
Remove pdf_skia_font_manager_target GN argument.
tsepez Oct 30, 2026
5f092b5
Use AutoRestorer to scope script_node_array_ in CFXJSE_Engine
tsepez Oct 30, 2026
1f012c8
Sync S15: merge upstream PDFium up to 5f092b529 (Oct 30 2026)
bobsingor Nov 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ Zhuo Qingliang <zhuo.dev@gmail.com>

# BEGIN organizations section.
Ada Logics Ltd. <*@adalogics.com>
Advanced Micro Devices, Inc. <*@amd.com>
Collabora Ltd. <*@collabora.com>
DocsCorp Pty Ltd. <*@docscorp.com>
Dropbox <*@dropbox.com>
Expand Down
296 changes: 141 additions & 155 deletions DEPS

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -215,10 +215,10 @@ Chromium provides code coverage reports for PDFium
`third_party/pdfium` in Chromium's source code.
This includes code coverage from PDFium's fuzzers.

## Waterfall
## Infrastructure

The current health of the source tree can be found
[here](https://ci.chromium.org/p/pdfium/g/main/console).
See [docs/infra.md](/docs/infra.md) for details about PDFium's continuous
integration and build infrastructure.

## Community

Expand Down
9 changes: 2 additions & 7 deletions build_overrides/pdfium.gni
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ pdf_bundle_freetype_override = true
pdf_enable_freetype_override = true

# Build PDFium with experimental Brotli compression support.
# Default: Brotli support is disabled until PDF 2.0 spec is confirmed.
pdf_enable_brotli_override = false
# Default: Brotli support is compiled in by default.
pdf_enable_brotli_override = true

# Build PDFium either with or without v8 support.
# Default: With V8 support.
Expand All @@ -36,11 +36,6 @@ pdf_use_partition_alloc_override = is_clang
# The default is to use AGG when `pdf_use_skia_override` is false.
pdf_use_skia_override = false

# When building PDFium with Skia enabled, optionally define a custom font
# manager target that is used to override the pre-chosen font manager.
# Default: No override. Use the pre-chosen font manager.
pdf_skia_font_manager_target_override = ""

# Build PDFium with experimental Fontations library support.
# If enabled, coexists in build with FreeType library and the default font
# library is selectable at runtime.
Expand Down
7 changes: 4 additions & 3 deletions core/fpdfapi/edit/cpdf_creator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -506,18 +506,19 @@ CPDF_Creator::Stage CPDF_Creator::WriteDoc_Stage1() {
}
if (stage_ == Stage::kWriteHeader10) {
if (!is_incremental_) {
if (!archive_->WriteString("%PDF-1.")) {
if (!archive_->WriteString("%PDF-")) {
return Stage::kInvalid;
}

int32_t version = 7;
int32_t version = 17;
if (file_version_) {
version = file_version_;
} else if (parser_) {
version = parser_->GetFileVersion();
}

if (!archive_->WriteDWord(version % 10) ||
if (!archive_->WriteDWord(version / 10) || !archive_->WriteString(".") ||
!archive_->WriteDWord(version % 10) ||
!archive_->WriteString("\r\n%\xA1\xB3\xC5\xD7\r\n")) {
return Stage::kInvalid;
}
Expand Down
29 changes: 29 additions & 0 deletions core/fpdfapi/edit/cpdf_creator_embeddertest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,32 @@ TEST_F(CPDFCreatorEmbedderTest, SaveLinearizedInfo) {

EXPECT_THAT(saved_doc, ::testing::HasSubstr("/Info"));
}

TEST_F(CPDFCreatorEmbedderTest, SingleSubsectionXrefWithFreeObjectLinkedList) {
ASSERT_TRUE(OpenDocument("xref_free_objects.pdf"));
ASSERT_TRUE(FPDF_SaveAsCopy(document(), this, 0));

// EmbedPDF(complete-xref): one subsection without gaps (upstream's TODO,
// crbug.com/42271313); objects 1, 3, 5 and 6 are free entries, linked from
// entry 0 in ascending order back to 0.
static constexpr char kExpectedXrefAndTrailerPrefix[] =
"xref\r\n"
"0 8\r\n"
"0000000001 65535 f\r\n"
"0000000003 00000 f\r\n"
"0000000017 00000 n\r\n"
"0000000005 00000 f\r\n"
"0000000066 00000 n\r\n"
"0000000006 00000 f\r\n"
"0000000000 00000 f\r\n"
"0000000122 00000 n\r\n"
"trailer\r\n";

EXPECT_THAT(GetString(), testing::HasSubstr(kExpectedXrefAndTrailerPrefix));

// Also make sure the saved PDF still loads.
ScopedSavedDoc saved_document = OpenScopedSavedDocument();
ASSERT_TRUE(saved_document);
ScopedSavedPage saved_page = LoadScopedSavedPage(0);
EXPECT_TRUE(saved_page);
}
5 changes: 4 additions & 1 deletion core/fpdfapi/parser/cfdf_document.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <utility>

#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_read_validator.h"
#include "core/fpdfapi/parser/cpdf_syntax_parser.h"
#include "core/fpdfapi/parser/fpdf_parser_utility.h"
#include "core/fxcrt/cfx_read_only_span_stream.h"
Expand Down Expand Up @@ -40,7 +41,9 @@ std::unique_ptr<CFDF_Document> CFDF_Document::ParseMemory(

void CFDF_Document::ParseStream(RetainPtr<IFX_SeekableReadStream> pFile) {
file_ = std::move(pFile);
CPDF_SyntaxParser parser(file_);
CPDF_SyntaxParser parser(
pdfium::MakeRetain<CPDF_ReadValidator>(file_, nullptr), 0,
GetByteStringPool());
while (true) {
CPDF_SyntaxParser::WordResult word_result = parser.GetNextWord();
if (word_result.is_number) {
Expand Down
5 changes: 3 additions & 2 deletions core/fpdfapi/parser/cpdf_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,9 @@ bool CPDF_Parser::InitSyntaxParser(RetainPtr<CPDF_ReadValidator> validator) {
return false;
}

syntax_ = std::make_unique<CPDF_SyntaxParser>(std::move(validator),
header_offset.value());
syntax_ = std::make_unique<CPDF_SyntaxParser>(
std::move(validator), header_offset.value(),
objects_holder_->GetByteStringPool());
return ParseFileVersion();
}

Expand Down
9 changes: 8 additions & 1 deletion core/fpdfapi/parser/cpdf_syntax_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,16 @@ CPDF_SyntaxParser::CPDF_SyntaxParser(

CPDF_SyntaxParser::CPDF_SyntaxParser(RetainPtr<CPDF_ReadValidator> validator,
FX_FILESIZE header_offset)
: CPDF_SyntaxParser(std::move(validator), header_offset, /*pool=*/nullptr) {
}

CPDF_SyntaxParser::CPDF_SyntaxParser(RetainPtr<CPDF_ReadValidator> validator,
FX_FILESIZE header_offset,
WeakPtr<ByteStringPool> pool)
: file_access_(std::move(validator)),
header_offset_(header_offset),
file_len_(file_access_->GetSize()) {
file_len_(file_access_->GetSize()),
pool_(std::move(pool)) {
DCHECK_LE(header_offset_, file_len_);
}

Expand Down
3 changes: 3 additions & 0 deletions core/fpdfapi/parser/cpdf_syntax_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ class CPDF_SyntaxParser {
explicit CPDF_SyntaxParser(RetainPtr<IFX_SeekableReadStream> file_access);
CPDF_SyntaxParser(RetainPtr<CPDF_ReadValidator> validator,
FX_FILESIZE header_offset);
CPDF_SyntaxParser(RetainPtr<CPDF_ReadValidator> validator,
FX_FILESIZE header_offset,
WeakPtr<ByteStringPool> pool);
~CPDF_SyntaxParser();

void SetReadBufferSize(uint32_t read_buffer_size) {
Expand Down
4 changes: 1 addition & 3 deletions core/fpdfapi/render/fpdf_render_pattern_embeddertest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#include "public/cpp/fpdf_scopers.h"
#include "public/fpdfview.h"
#include "testing/embedder_test.h"
#include "testing/embedder_test_constants.h"
#include "testing/gtest/include/gtest/gtest.h"

class FPDFRenderPatternEmbedderTest : public EmbedderTest {};
Expand Down Expand Up @@ -48,8 +47,7 @@ TEST_F(FPDFRenderPatternEmbedderTest, LoadError547706) {
ASSERT_TRUE(OpenDocument("bug_547706.pdf"));
ScopedPage page = LoadScopedPage(0);
ASSERT_TRUE(page);
ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
CompareBitmap(bitmap.get(), pdfium::kBlankPage612By792Png);
CompareDisplayList(RenderLoadedPageToDisplayList(page.get()), "bug_547706");
}

TEST_F(FPDFRenderPatternEmbedderTest, ZeroTilingPatternStep509964646) {
Expand Down
5 changes: 4 additions & 1 deletion core/fxcodec/brotli/brotli_decoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,17 @@
#include "core/fxcodec/image_predictors.h"
#include "core/fxcrt/check.h"
#include "core/fxcrt/data_vector.h"
#include "core/fxcrt/epdf_tls.h"
#include "core/fxcrt/fx_extension.h"
#include "core/fxcrt/numerics/safe_conversions.h"
#include "third_party/brotli/include/brotli/decode.h"

namespace {

constexpr size_t kMaxDecodeBytes = 1024 * 1024 * 1024;
bool g_brotli_enabled = false;
// EmbedPDF(thread-confined-globals): per thread, as library start-up runs on
// every thread (rule per-thread-init) and sets it from that thread's config.
EPDF_TLS bool g_brotli_enabled = false;

struct BrotliDecoderStateDeleter {
void operator()(struct BrotliDecoderStateStruct* ptr) const {
Expand Down
46 changes: 9 additions & 37 deletions core/fxcodec/brotli/brotli_embeddertest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

#include "public/fpdfview.h"
#include "testing/embedder_test.h"
#include "testing/embedder_test_constants.h"
#include "testing/embedder_test_environment.h"
#include "testing/gtest/include/gtest/gtest.h"

Expand Down Expand Up @@ -50,38 +49,24 @@ class BrotliV5EmbedderTest : public BrotliEnabledEmbedderTest {

TEST_F(BrotliEnabledEmbedderTest, ManyRectanglesBrotli) {
ASSERT_TRUE(OpenDocument("many_rectangles_brotli.pdf"));

ScopedPage page = LoadScopedPage(0);
ASSERT_TRUE(page);

ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
ASSERT_TRUE(bitmap);

CompareBitmapWithExpectationSuffix(bitmap.get(), pdfium::kManyRectanglesPng);
CompareDisplayList(RenderLoadedPageToDisplayList(page.get()),
"many_rectangles");
}

TEST_F(BrotliEnabledEmbedderTest, SimpleBrotliWithText) {
ASSERT_TRUE(OpenDocument("hello_world_brotli.pdf"));

ScopedPage page = LoadScopedPage(0);
ASSERT_TRUE(page);

ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
ASSERT_TRUE(bitmap);

CompareBitmapWithExpectationSuffix(bitmap.get(), pdfium::kHelloWorldPng);
CompareDisplayList(RenderLoadedPageToDisplayList(page.get()), "hello_world");
}

TEST_F(BrotliEnabledEmbedderTest, BrotliRectangles) {
ASSERT_TRUE(OpenDocument("rectangles_brotli.pdf"));

ScopedPage page = LoadScopedPage(0);
ASSERT_TRUE(page);

ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
ASSERT_TRUE(bitmap);

CompareBitmapWithExpectationSuffix(bitmap.get(), pdfium::kRectanglesPng);
CompareDisplayList(RenderLoadedPageToDisplayList(page.get()), "rectangles");
}

TEST_F(BrotliEnabledEmbedderTest, BrotliDecodeParms) {
Expand All @@ -98,36 +83,23 @@ TEST_F(BrotliEnabledEmbedderTest, BrotliDecodeParms) {

TEST_F(BrotliEnabledEmbedderTest, BrotliWithLength1Argument) {
ASSERT_TRUE(OpenDocument("hello_world_brotli_with_length1.pdf"));

ScopedPage page = LoadScopedPage(0);
ASSERT_TRUE(page);

ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
ASSERT_TRUE(bitmap);

CompareBitmapWithExpectationSuffix(bitmap.get(), pdfium::kHelloWorldPng);
CompareDisplayList(RenderLoadedPageToDisplayList(page.get()), "hello_world");
}

TEST_F(BrotliDisabledEmbedderTest, BrotliDecodeDisabled) {
ASSERT_TRUE(OpenDocument("hello_world_brotli.pdf"));

ScopedPage page = LoadScopedPage(0);
ASSERT_TRUE(page);

ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
ASSERT_TRUE(bitmap);

CompareBitmap(bitmap.get(), "blank_200x200");
CompareDisplayList(RenderLoadedPageToDisplayList(page.get()),
"blank_page_200x200");
}

TEST_F(BrotliV5EmbedderTest, WrongBrotliVersion) {
ASSERT_TRUE(OpenDocument("hello_world_brotli.pdf"));

ScopedPage page = LoadScopedPage(0);
ASSERT_TRUE(page);

ScopedFPDFBitmap bitmap = RenderLoadedPage(page.get());
ASSERT_TRUE(bitmap);

CompareBitmap(bitmap.get(), "blank_200x200");
CompareDisplayList(RenderLoadedPageToDisplayList(page.get()),
"blank_page_200x200");
}
5 changes: 2 additions & 3 deletions core/fxcodec/fx_codec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,8 @@ void ReverseRGB(pdfium::span<uint8_t> pDestBuf,
count);

#if defined(PDF_USE_LIBYUV)
libyuv::RGB24ToRAW(pdfium::as_bytes(src_span).data(), pixels * 3,
pdfium::as_writable_bytes(dst_span).data(), pixels * 3,
pixels, 1);
libyuv::RGB24ToRAW(pdfium::as_bytes(src_span).data(), 0,
pdfium::as_writable_bytes(dst_span).data(), 0, pixels, 1);
#else
if (dst_span.data() == src_span.data()) {
for (auto& pix : dst_span) {
Expand Down
26 changes: 14 additions & 12 deletions core/fxcodec/jpeg/jpegmodule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "core/fxcrt/fx_safe_types.h"
#include "core/fxcrt/numerics/safe_conversions.h"
#include "core/fxcrt/retain_ptr.h"
#include "core/fxcrt/zip.h"
#include "core/fxge/dib/cfx_dibbase.h"
#include "core/fxge/dib/fx_dib.h"
#endif // BUILDFLAG(IS_WIN)
Expand Down Expand Up @@ -130,25 +131,25 @@ bool JpegModule::JpegEncode(const RetainPtr<const CFX_DIBBase>& pSource,
compress_common.common.cinfo.in_color_space = JCS_CMYK;
}

std::unique_ptr<uint8_t, FxFreeDeleter> line_buf;
if (nComponents > 1) {
line_buf.reset(FX_Alloc2D(uint8_t, width, nComponents));
}

if (!jpeg_common_set_defaults(&compress_common.common) ||
!jpeg_common_start_compress(&compress_common.common, TRUE)) {
return false;
}

std::unique_ptr<uint8_t, FxFreeDeleter> line_buf;
if (nComponents > 1) {
line_buf.reset(FX_Alloc2D(uint8_t, width, nComponents));
}

JSAMPROW row_pointer;
JDIMENSION row;
while (compress_common.common.cinfo.next_scanline <
compress_common.common.cinfo.image_height) {
pdfium::span<const uint8_t> src_scan =
pSource->GetScanline(compress_common.common.cinfo.next_scanline);
if (nComponents > 1) {
uint8_t* dest_scan = line_buf.get();
if (nComponents == 3) {
uint8_t* dest_scan = line_buf.get();
UNSAFE_TODO({
for (uint32_t i = 0; i < width; i++) {
ReverseCopy3Bytes(dest_scan, src_scan.data());
Expand All @@ -157,12 +158,13 @@ bool JpegModule::JpegEncode(const RetainPtr<const CFX_DIBBase>& pSource,
}
});
} else {
UNSAFE_TODO({
for (uint32_t i = 0; i < pitch; i++) {
*dest_scan++ = ~src_scan.front();
src_scan = src_scan.subspan<1u>();
}
});
// SAFETY: Matches FX_Alloc2D() call above.
pdfium::span<uint8_t> dest_span = UNSAFE_BUFFERS(
pdfium::span<uint8_t>(line_buf.get(), width * nComponents));
for (auto [in, out] :
fxcrt::Zip(src_scan.first(pitch), dest_span.first(pitch))) {
out = ~in;
}
}
row_pointer = line_buf.get();
} else {
Expand Down
2 changes: 2 additions & 0 deletions core/fxcrt/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,8 @@ source_set("test_support") {
sources = [
"fx_coordinates_test_support.cpp",
"fx_coordinates_test_support.h",
"scoped_locale.cpp",
"scoped_locale.h",
"string_test_support.cpp",
]
configs += [ "../../:pdfium_strict_config" ]
Expand Down
Loading
Loading