diff options
author | Lei Zhang <thestig@chromium.org> | 2023-01-12 20:24:54 +0000 |
---|---|---|
committer | Michael BrĂ¼ning <michael.bruning@qt.io> | 2023-02-27 09:13:05 +0000 |
commit | 0cccf37c322f7ff7deeb0b24232f1d7336344450 (patch) | |
tree | d0b220e991c3565d2884d900177a61b901534d7b | |
parent | d6c67784d8988b889e77f3e4d3772685809595c6 (diff) | |
download | qtwebengine-chromium-0cccf37c322f7ff7deeb0b24232f1d7336344450.tar.gz |
[Backport] CVE-2023-0933: Integer overflow in PDF
Manual cherry-pick 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 <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/462769
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
-rw-r--r-- | chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_document.cpp | 17 |
1 files 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 44fa2a1009e..8179db37a3b 100644 --- a/chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_document.cpp +++ b/chromium/third_party/pdfium/core/fpdfapi/parser/cpdf_document.cpp @@ -20,6 +20,7 @@ #include "core/fxcrt/fx_codepage.h" #include "core/fxcrt/scoped_set_insertion.h" #include "core/fxcrt/stl_util.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/base/check.h" #include "third_party/base/containers/contains.h" @@ -27,7 +28,9 @@ namespace { const int kMaxPageLevel = 1024; -int CountPages(CPDF_Dictionary* pPages, +// Returns a value in the range [0, `CPDF_Document::kPageMaxNum`), or nullopt on +// error. +absl::optional<int> CountPages(CPDF_Dictionary* pPages, std::set<CPDF_Dictionary*>* visited_pages) { int count = pPages->GetIntegerFor("Count"); if (count > 0 && count < CPDF_Document::kPageMaxNum) @@ -43,11 +46,19 @@ int CountPages(CPDF_Dictionary* pPages, if (pKid->KeyExist("Kids")) { // Use |visited_pages| to help detect circular references of pages. ScopedSetInsertion<CPDF_Dictionary*> local_add(visited_pages, pKid); - count += CountPages(pKid, visited_pages); + absl::optional<int> local_count = + CountPages(pKid, visited_pages); + if (!local_count.has_value()) { + return absl::nullopt; // Propagate error. + } + count += local_count.value(); } else { // This page is a leaf node. count++; } + if (count >= CPDF_Document::kPageMaxNum) { + return absl::nullopt; // Error: too many pages. + } } pPages->SetNewFor<CPDF_Number>("Count", count); return count; @@ -366,7 +377,7 @@ int CPDF_Document::RetrievePageCount() { std::set<CPDF_Dictionary*> 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 { |