From ed1c58049f0c164969946b6ad0ff06d952ab1949 Mon Sep 17 00:00:00 2001 From: Tom Sepez Date: Tue, 19 Jun 2018 16:23:52 +0000 Subject: Speculative fix for segv destroying CPDF_PageObjectHolder::m_GraphicsMap We speculate that the bug that makes the comparison operator irreflexive might be the cause of the segv on windows production code, should a NaN sneak into the GraphicsData struct. In any event, should this happen, the tree won't be correct with some nodes erroneously replaced. Add a test which fails prior to the patch, but alas does not elicit the segv. Also move operator<() methods to .cpp file corresponding to .h file in which they are delcared. Bug: 852273 Change-Id: Ib7929881e7ffbed8b09f6e2c9fb7898cbde58946 Reviewed-on: https://pdfium-review.googlesource.com/35171 Reviewed-by: dsinclair Commit-Queue: Tom Sepez --- .../page/cpdf_pageobjectholder_unittest.cpp | 66 ++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 core/fpdfapi/page/cpdf_pageobjectholder_unittest.cpp (limited to 'core/fpdfapi/page/cpdf_pageobjectholder_unittest.cpp') diff --git a/core/fpdfapi/page/cpdf_pageobjectholder_unittest.cpp b/core/fpdfapi/page/cpdf_pageobjectholder_unittest.cpp new file mode 100644 index 0000000000..ddad795fea --- /dev/null +++ b/core/fpdfapi/page/cpdf_pageobjectholder_unittest.cpp @@ -0,0 +1,66 @@ +// Copyright 2018 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/fpdfapi/page/cpdf_pageobjectholder.h" + +#include + +#include "testing/gtest/include/gtest/gtest.h" + +// See https://crbug.com/852273 +TEST(CPDFPageObjectHolder, GraphicsDataAsKey) { + const float fMin = std::numeric_limits::min(); + const float fMax = std::numeric_limits::max(); + const float fInf = std::numeric_limits::infinity(); + const float fNan = std::numeric_limits::quiet_NaN(); + + // Verify self-comparisions. + for (float c1 : {fMin, 1.0f, 2.0f, fMax, fInf, fNan}) { + for (float c2 : {fMin, 1.0f, 2.0f, fMax, fInf, fNan}) { + for (int c3 : {1, 2}) + EXPECT_FALSE(GraphicsData({c1, c2, c3}) < GraphicsData({c1, c2, c3})); + } + } + + std::map graphics_map; + + // Insert in reverse index permuted order. + size_t x = 0; + for (int c3 : {2, 1}) { + for (float c2 : {fNan, fInf, fMax, 2.0f, 1.0f, fMin}) { + for (float c1 : {fNan, fInf, fMax, 2.0f, 1.0f, fMin}) { + graphics_map[{c1, c2, c3}] = x++; + } + } + } + EXPECT_EQ(72u, x); + EXPECT_EQ(72u, graphics_map.size()); + + // clang-format off + const int expected[72] = { + 71, 35, 65, 29, 59, 23, 53, 17, 47, 11, 41, 5, + 70, 34, 64, 28, 58, 22, 52, 16, 46, 10, 40, 4, + 69, 33, 63, 27, 57, 21, 51, 15, 45, 9, 39, 3, + 68, 32, 62, 26, 56, 20, 50, 14, 44, 8, 38, 2, + 67, 31, 61, 25, 55, 19, 49, 13, 43, 7, 37, 1, + 66, 30, 60, 24, 54, 18, 48, 12, 42, 6, 36, 0 + }; + // clang-format on + + x = 0; + for (const auto& item : graphics_map) { + EXPECT_EQ(expected[x], item.second) << " for position " << x; + ++x; + } + EXPECT_EQ(72u, x); + + // Erase in forward index permuted order. + for (int c3 : {1, 2}) { + for (float c2 : {fMin, 1.0f, 2.0f, fMax, fInf, fNan}) { + for (float c1 : {fMin, 1.0f, 2.0f, fMax, fInf, fNan}) + graphics_map.erase({c1, c2, c3}); + } + } + EXPECT_EQ(0u, graphics_map.size()); +} -- cgit v1.2.3