From e48df7803c7c98b0b2471c94057d32e44a301ad5 Mon Sep 17 00:00:00 2001 From: Lei Zhang Date: Thu, 12 Jan 2023 20:24:54 +0000 Subject: [Backport] CVE-2023-0933: Integer overflow in PDF Manual backport of patch originally reviewed on https://pdfium-review.googlesource.com/c/pdfium/+/103078: Validate the page count. In CountPages(), which recursively calls itself, validate the page count. When any part of the pages tree contains bad data, bail out. Bug: chromium:1404864 Change-Id: Ifdbc14213ec3f963b4b2cb5793b83c15d03336e8 Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/103078 Reviewed-by: Tom Sepez Commit-Queue: Lei Zhang Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/462800 Reviewed-by: Michal Klocek --- .../pdfium/core/fpdfapi/parser/cpdf_document.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_document.cpp b/chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_document.cpp index 62106a7046a..74cf5724574 100644 --- a/chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_document.cpp +++ b/chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_document.cpp @@ -16,13 +16,16 @@ #include "core/fpdfapi/parser/cpdf_reference.h" #include "core/fxcodec/jbig2/JBig2_DocumentContext.h" #include "core/fxcrt/fx_codepage.h" +#include "third_party/base/optional.h" #include "third_party/base/stl_util.h" namespace { const int kMaxPageLevel = 1024; -int CountPages(CPDF_Dictionary* pPages, +// Returns a value in the range [0, `CPDF_Document::kPageMaxNum`), or nullopt on +// error. +pdfium::Optional CountPages(CPDF_Dictionary* pPages, std::set* visited_pages) { int count = pPages->GetIntegerFor("Count"); if (count > 0 && count < CPDF_Document::kPageMaxNum) @@ -39,11 +42,19 @@ int CountPages(CPDF_Dictionary* pPages, // Use |visited_pages| to help detect circular references of pages. pdfium::ScopedSetInsertion local_add(visited_pages, pKid); - count += CountPages(pKid, visited_pages); + pdfium::Optional local_count = + CountPages(pKid, visited_pages); + if (!local_count.has_value()) { + return pdfium::nullopt; // Propagate error. + } + count += local_count.value(); } else { // This page is a leaf node. count++; } + if (count >= CPDF_Document::kPageMaxNum) { + return pdfium::nullopt; // Error: too many pages. + } } pPages->SetNewFor("Count", count); return count; @@ -346,7 +357,7 @@ int CPDF_Document::RetrievePageCount() { std::set visited_pages; visited_pages.insert(pPages); - return CountPages(pPages, &visited_pages); + return CountPages(pPages, &visited_pages).value_or(0); } uint32_t CPDF_Document::GetUserPermissions() const { -- cgit v1.2.1