Security: Pdfium: integer overflows in pattern shading |
|||||||||||||||
Issue description
VULNERABILITY DETAILS
This vulnerability relies on several minor oversights in the handling of shading patterns in pdfium, I'll try to detail all of the issues that could be fixed to harden the code against similar issues.
The DrawXShading functions in cpdf_renderstatus.cpp rely on a helper function to compute the number of output components resulting from applying multiple shading functions. Note that all of these functions appear to be vulnerable; the rest of this report discusses the specifics of triggering a heap-overflow using DrawRadialShading.
uint32_t CountOutputs(
const std::vector<std::unique_ptr<CPDF_Function>>& funcs) {
uint32_t total = 0;
for (const auto& func : funcs) {
if (func)
total += func->CountOutputs(); // <-- Issue #1 : integer overflow here
}
return total;
}
The lack of integer overflow checking would not be an issue if the parser enforced the limitations applied by the pdf specification to the functions applied (namely that the /Function section in a radial shading pattern should be either a 1-n function or an array of n 1-1 functions), as these preconditions would preclude any overflow from occuring. However, we can see in the loading code for CPDF_ShadingPattern that there is no such validation.
bool CPDF_ShadingPattern::Load() {
if (m_ShadingType != kInvalidShading)
return true;
CPDF_Dictionary* pShadingDict =
m_pShadingObj ? m_pShadingObj->GetDict() : nullptr;
if (!pShadingDict)
return false;
m_pFunctions.clear();
CPDF_Object* pFunc = pShadingDict->GetDirectObjectFor("Function");
if (pFunc) {
// Issue #2 : we never validate that the signatures of the parsed Function object
// match the expected signatures for the shading type that we're parsing.
if (CPDF_Array* pArray = pFunc->AsArray()) {
m_pFunctions.resize(std::min<size_t>(pArray->GetCount(), 4));
for (size_t i = 0; i < m_pFunctions.size(); ++i)
m_pFunctions[i] = CPDF_Function::Load(pArray->GetDirectObjectAt(i));
} else {
m_pFunctions.push_back(CPDF_Function::Load(pFunc));
}
}
CPDF_Object* pCSObj = pShadingDict->GetDirectObjectFor("ColorSpace");
if (!pCSObj)
return false;
CPDF_DocPageData* pDocPageData = document()->GetPageData();
m_pCS = pDocPageData->GetColorSpace(pCSObj, nullptr);
if (m_pCS)
m_pCountedCS = pDocPageData->FindColorSpacePtr(m_pCS->GetArray());
m_ShadingType = ToShadingType(pShadingDict->GetIntegerFor("ShadingType"));
// We expect to have a stream if our shading type is a mesh.
if (IsMeshShading() && !ToStream(m_pShadingObj.Get()))
return false;
return true;
}
Assuming that we can create function objects with very large output sizes, we can then reach the following code (in cpdf_renderstatus.cpp) when rendering something using the pattern:
void DrawRadialShading(const RetainPtr<CFX_DIBitmap>& pBitmap,
CFX_Matrix* pObject2Bitmap,
CPDF_Dictionary* pDict,
const std::vector<std::unique_ptr<CPDF_Function>>& funcs,
CPDF_ColorSpace* pCS,
int alpha) {
// ... snip ...
uint32_t total_results =
std::max(CountOutputs(funcs), pCS->CountComponents());
// NB: CountOutputs overflows here, result_array will be a stack buffer if we return
// a resulting size less than 16) or a heap buffer if the size is larger.
CFX_FixedBufGrow<float, 16> result_array(total_results);
float* pResults = result_array;
memset(pResults, 0, total_results * sizeof(float));
uint32_t rgb_array[SHADING_STEPS];
for (int i = 0; i < SHADING_STEPS; i++) {
float input = (t_max - t_min) * i / SHADING_STEPS + t_min;
int offset = 0;
for (const auto& func : funcs) {
if (func) {
int nresults;
// Here we've desynchronised the size of the memory pointed to by
// pResults with the actual output size of the functions, so this
// can write outside the allocated buffer.
if (func->Call(&input, 1, pResults + offset, &nresults))
offset += nresults;
}
}
float R = 0.0f;
float G = 0.0f;
float B = 0.0f;
pCS->GetRGB(pResults, &R, &G, &B);
rgb_array[i] =
FXARGB_TODIB(FXARGB_MAKE(alpha, FXSYS_round(R * 255),
FXSYS_round(G * 255), FXSYS_round(B * 255)));
}
Now we need to revisit our earlier assumption, that we can create function objects with large output sizes.
The following code handles parsing of function objects:
bool CPDF_Function::Init(CPDF_Object* pObj) {
CPDF_Stream* pStream = pObj->AsStream();
CPDF_Dictionary* pDict = pStream ? pStream->GetDict() : pObj->AsDictionary();
CPDF_Array* pDomains = pDict->GetArrayFor("Domain");
if (!pDomains)
return false;
m_nInputs = pDomains->GetCount() / 2;
if (m_nInputs == 0)
return false;
m_pDomains = FX_Alloc2D(float, m_nInputs, 2);
for (uint32_t i = 0; i < m_nInputs * 2; i++) {
m_pDomains[i] = pDomains->GetFloatAt(i);
}
CPDF_Array* pRanges = pDict->GetArrayFor("Range");
m_nOutputs = 0;
if (pRanges) {
m_nOutputs = pRanges->GetCount() / 2;
m_pRanges = FX_Alloc2D(float, m_nOutputs, 2); // <-- avoid this call
for (uint32_t i = 0; i < m_nOutputs * 2; i++)
m_pRanges[i] = pRanges->GetFloatAt(i);
}
uint32_t old_outputs = m_nOutputs;
if (!v_Init(pObj))
return false;
if (m_pRanges && m_nOutputs > old_outputs) {
m_pRanges = FX_Realloc(float, m_pRanges, m_nOutputs * 2); // <-- avoid this call
if (m_pRanges) {
memset(m_pRanges + (old_outputs * 2), 0,
sizeof(float) * (m_nOutputs - old_outputs) * 2);
}
}
return true;
}
We can only have 4 functions, so we need m_nOutputs to be pretty large. Ideally we also don't want our pdf file to contain arrays of size 0x100000000 // 4 either, since this will mean multiple-gigabyte pdfs. Note also that any call to the FX_ allocation functions will fail on very large values, so ideally we need to follow the case old_outputs == m_nOutputs == 0, avoiding the final FX_Realloc call and allowing an arbitrarily large m_nOutputs.
It turns out that there is a function subtype that allows this, the exponential interpolation function type implemented in cpdf_expintfunc.cpp
bool CPDF_ExpIntFunc::v_Init(CPDF_Object* pObj) {
CPDF_Dictionary* pDict = pObj->GetDict();
if (!pDict)
return false;
CPDF_Array* pArray0 = pDict->GetArrayFor("C0");
if (m_nOutputs == 0) {
m_nOutputs = 1;
if (pArray0) {
fprintf(stderr, "C0 %zu\n", pArray0->GetCount());
m_nOutputs = pArray0->GetCount();
}
}
CPDF_Array* pArray1 = pDict->GetArrayFor("C1");
m_pBeginValues = FX_Alloc2D(float, m_nOutputs, 2);
m_pEndValues = FX_Alloc2D(float, m_nOutputs, 2);
for (uint32_t i = 0; i < m_nOutputs; i++) {
m_pBeginValues[i] = pArray0 ? pArray0->GetFloatAt(i) : 0.0f;
m_pEndValues[i] = pArray1 ? pArray1->GetFloatAt(i) : 1.0f;
}
m_Exponent = pDict->GetFloatFor("N");
m_nOrigOutputs = m_nOutputs;
if (m_nOutputs && m_nInputs > INT_MAX / m_nOutputs) // <-- can't be *too* large
return false;
m_nOutputs *= m_nInputs; // <-- but it can be pretty large
// Issue #3 : This is probably not the place, but it probably makes sense to
// bound m_nInputs and m_nOutputs to some large-but-not-that-large value in
// CPDF_Function::Init
return true;
}
So, by providing a function object without a /Range object, but with a large /C0 and /Domain elements, we can construct a function object with about INT_MAX outputs.
7 0 obj
<<
/FunctionType 2
/Domain [
0.0 1.0
... repeat many times ...
0.0 1.0
]
/C0 [
0.0
... repeat many times ...
0.0
]
/N 1
>>
endobj
At this point it looks like we have quite an annoying exploitation primitive; we can write a huge amount of data out of bounds, but that data will be calculated as an interpolation between it's input coordinates, and it will be a really, really big memory corruption.
It turns out that the point mentioned earlier at Issue #2 about validating the signatures of the functions is again relevant here, since if we look at the callsite in DrawRadialShading we can see that all of the functions are called with a single input parameter, and if we look at the start of CPDF_Function::Call
bool CPDF_Function::Call(float* inputs,
uint32_t ninputs,
float* results,
int* nresults) const {
if (m_nInputs != ninputs)
return false;
We can see that any attempt to call a function with the wrong number of input parameters will simply fail, letting us control precisely the size and contents of our overflow.
The attached poc will crash under ASAN with the following stack-trace, and without ASAN during the free of the corrupted heap block.
This bug is subject to a 90 day disclosure deadline. After 90 days elapse
or a patch has been made broadly available, the bug report will become
visible to the public.
VERSION
Chrome Version: Version 65.0.3293.0 (Developer Build) (64-bit)
Operating System: Debian
REPRODUCTION CASE
Please include a demonstration of the security bug, such as an attached
HTML or binary file that reproduces the bug when loaded in Chrome. PLEASE
make the file as small as possible and remove any content not required to
demonstrate the bug.
FOR CRASHES, PLEASE INCLUDE THE FOLLOWING ADDITIONAL INFORMATION
Type of crash: pdfium process
Crash State:
=================================================================
==1==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6070000546f4 at pc 0x5602e80904b0 bp 0x7ffef1f5b6e0 sp 0x7ffef1f5b6d8
WRITE of size 4 at 0x6070000546f4 thread T0 (chrome)
==1==WARNING: invalid path to external symbolizer!
==1==WARNING: Failed to use and restart external symbolizer!
#0 0x5602e80904af in CPDF_ExpIntFunc::v_Call(float*, float*) const ./out/Debug/../../third_party/pdfium/core/fpdfapi/page/cpdf_expintfunc.cpp:55:39
#1 0x5602e808de3a in CPDF_Function::Call(float*, unsigned int, float*, int*) const ./out/Debug/../../third_party/pdfium/core/fpdfapi/page/cpdf_function.cpp:116:3
#2 0x5602e839f570 in (anonymous namespace)::DrawRadialShading(fxcrt::RetainPtr<CFX_DIBitmap> const&, CFX_Matrix*, CPDF_Dictionary*, std::__1::vector<std::__1::unique_ptr<CPDF_Function, std::__1::default_delete<CPDF_Function> >, std::__1::allocator<std::__1::unique_ptr<CPDF_Function, std::__1::default_delete<CPDF_Function> > > > const&, CPDF_ColorSpace*, int) ./out/Debug/../../third_party/pdfium/core/fpdfapi/render/cpdf_renderstatus.cpp:232:19
#3 0x5602e839a7b5 in CPDF_RenderStatus::DrawShading(CPDF_ShadingPattern*, CFX_Matrix*, FX_RECT&, int, bool) ./out/Debug/../../third_party/pdfium/core/fpdfapi/render/cpdf_renderstatus.cpp:2124:7
#4 0x5602e83a588b in CPDF_RenderStatus::DrawShadingPattern(CPDF_ShadingPattern*, CPDF_PageObject const*, CFX_Matrix const*, bool) ./out/Debug/../../third_party/pdfium/core/fpdfapi/render/cpdf_renderstatus.cpp:2188:3
#5 0x5602e83ab243 in CPDF_RenderStatus::DrawPathWithPattern(CPDF_PathObject*, CFX_Matrix const*, CPDF_Color const*, bool) ./out/Debug/../../third_party/pdfium/core/fpdfapi/render/cpdf_renderstatus.cpp:2412:5
#6 0x5602e8388450 in CPDF_RenderStatus::ProcessPathPattern(CPDF_PathObject*, CFX_Matrix const*, int&, bool&) ./out/Debug/../../third_party/pdfium/core/fpdfapi/render/cpdf_renderstatus.cpp:2422:7
#7 0x5602e8385fa2 in CPDF_RenderStatus::ProcessPath(CPDF_PathObject*, CFX_Matrix const*) ./out/Debug/../../third_party/pdfium/core/fpdfapi/render/cpdf_renderstatus.cpp:1308:3
#8 0x5602e838252e in CPDF_RenderStatus::ProcessObjectNoClip(CPDF_PageObject*, CFX_Matrix const*) ./out/Debug/../../third_party/pdfium/core/fpdfapi/render/cpdf_renderstatus.cpp:1195:14
#9 0x5602e8382ec1 in CPDF_RenderStatus::ContinueSingleObject(CPDF_PageObject*, CFX_Matrix const*, IFX_PauseIndicator*) ./out/Debug/../../third_party/pdfium/core/fpdfapi/render/cpdf_renderstatus.cpp:1148:5
#10 0x5602e8372691 in CPDF_ProgressiveRenderer::Continue(IFX_PauseIndicator*) ./out/Debug/../../third_party/pdfium/core/fpdfapi/render/cpdf_progressiverenderer.cpp:93:30
#11 0x5602e8370481 in CPDF_ProgressiveRenderer::Start(IFX_PauseIndicator*) ./out/Debug/../../third_party/pdfium/core/fpdfapi/render/cpdf_progressiverenderer.cpp:44:3
#12 0x5602e7dfdecd in (anonymous namespace)::RenderPageImpl(CPDF_PageRenderContext*, CPDF_Page*, CFX_Matrix const&, FX_RECT const&, int, bool, IFSDK_PAUSE_Adapter*) ./out/Debug/../../third_party/pdfium/fpdfsdk/fpdfview.cpp:129:26
#13 0x5602e7dfa98f in FPDF_RenderPage_Retail(CPDF_PageRenderContext*, void*, int, int, int, int, int, int, bool, IFSDK_PAUSE_Adapter*) ./out/Debug/../../third_party/pdfium/fpdfsdk/fpdfview.cpp:1264:3
#14 0x5602e7cecb39 in FPDF_RenderPageBitmap_Start ./out/Debug/../../third_party/pdfium/fpdfsdk/fpdf_progressive.cpp:60:3
#15 0x5602e7bc3db6 in chrome_pdf::PDFiumEngine::ContinuePaint(int, pp::ImageData*) ./out/Debug/../../pdf/pdfium/pdfium_engine.cc:3257:10
#16 0x5602e7bc15f5 in chrome_pdf::PDFiumEngine::Paint(pp::Rect const&, pp::ImageData*, std::__1::vector<pp::Rect, std::__1::allocator<pp::Rect> >*, std::__1::vector<pp::Rect, std::__1::allocator<pp::Rect> >*) ./out/Debug/../../pdf/pdfium/pdfium_engine.cc:1117:11
#17 0x5602e7b527c0 in chrome_pdf::OutOfProcessInstance::OnPaint(std::__1::vector<pp::Rect, std::__1::allocator<pp::Rect> > const&, std::__1::vector<PaintManager::ReadyRect, std::__1::allocator<PaintManager::ReadyRect> >*, std::__1::vector<pp::Rect, std::__1::allocator<pp::Rect> >*) ./out/Debug/../../pdf/out_of_process_instance.cc:1064:16
#18 0x5602e7b883d9 in PaintManager::DoPaint() ./out/Debug/../../pdf/paint_manager.cc:235:12
#19 0x5602e7b86f25 in PaintManager::OnManualCallbackComplete(int) ./out/Debug/../../pdf/paint_manager.cc:345:5
#20 0x5602e7b8ef97 in pp::CompletionCallbackFactory<PaintManager, pp::ThreadSafeThreadTraits>::Dispatcher0<void (PaintManager::*)(int)>::operator()(PaintManager*, int) ./out/Debug/../../ppapi/utility/completion_callback_factory.h:607:9
#21 0x5602e7b8ec24 in pp::CompletionCallbackFactory<PaintManager, pp::ThreadSafeThreadTraits>::CallbackData<pp::CompletionCallbackFactory<PaintManager, pp::ThreadSafeThreadTraits>::Dispatcher0<void (PaintManager::*)(int)> >::Thunk(void*, int) ./out/Debug/../../ppapi/utility/completion_callback_factory.h:584:7
#22 0x7f7b30de9654 in PP_RunCompletionCallback(PP_CompletionCallback*, int) ./out/Debug/../../ppapi/c/pp_completion_callback.h:240:3
#23 0x7f7b30de953a in void ppapi::CallWhileUnlocked<void, PP_CompletionCallback*, int, PP_CompletionCallback*, int>(void (*)(PP_CompletionCallback*, int), PP_CompletionCallback* const&, int const&) ./out/Debug/../../ppapi/shared_impl/proxy_lock.h:135:10
#24 0x7f7b30de5db8 in ppapi::proxy::(anonymous namespace)::CallbackWrapper(PP_CompletionCallback, int) ./out/Debug/../../ppapi/proxy/ppb_core_proxy.cc:52:3
#25 0x7f7b30de8b69 in void base::internal::FunctorTraits<void (*)(PP_CompletionCallback, int), void>::Invoke<PP_CompletionCallback const&, int const&>(void (*)(PP_CompletionCallback, int), PP_CompletionCallback const&, int const&) ./out/Debug/../../base/bind_internal.h:166:12
#26 0x7f7b30de894b in void base::internal::InvokeHelper<false, void>::MakeItSo<void (* const&)(PP_CompletionCallback, int), PP_CompletionCallback const&, int const&>(void (* const&)(PP_CompletionCallback, int), PP_CompletionCallback const&, int const&) ./out/Debug/../../base/bind_internal.h:294:12
#27 0x7f7b30de88ab in void base::internal::Invoker<base::internal::BindState<void (*)(PP_CompletionCallback, int), PP_CompletionCallback, int>, void ()>::RunImpl<void (* const&)(PP_CompletionCallback, int), std::__1::tuple<PP_CompletionCallback, int> const&, 0ul, 1ul>(void (* const&)(PP_CompletionCallback, int), std::__1::tuple<PP_CompletionCallback, int> const&, std::__1::integer_sequence<unsigned long, 0ul, 1ul>) ./out/Debug/../../base/bind_internal.h:368:12
#28 0x7f7b30de8772 in base::internal::Invoker<base::internal::BindState<void (*)(PP_CompletionCallback, int), PP_CompletionCallback, int>, void ()>::Run(base::internal::BindStateBase*) ./out/Debug/../../base/bind_internal.h:350:12
#29 0x7f7b30d25046 in base::RepeatingCallback<void ()>::Run() const & ./out/Debug/../../base/callback.h:94:12
#30 0x7f7b30d22e32 in ppapi::internal::RunWhileLockedHelper<void ()>::CallWhileLocked(std::__1::unique_ptr<ppapi::internal::RunWhileLockedHelper<void ()>, std::__1::default_delete<ppapi::internal::RunWhileLockedHelper<void ()> > >) ./out/Debug/../../ppapi/shared_impl/proxy_lock.h:205:22
#31 0x7f7b30d23c2a in void base::internal::FunctorTraits<void (*)(std::__1::unique_ptr<ppapi::internal::RunWhileLockedHelper<void ()>, std::__1::default_delete<ppapi::internal::RunWhileLockedHelper<void ()> > >), void>::Invoke<std::__1::unique_ptr<ppapi::internal::RunWhileLockedHelper<void ()>, std::__1::default_delete<ppapi::internal::RunWhileLockedHelper<void ()> > > >(void (*)(std::__1::unique_ptr<ppapi::internal::RunWhileLockedHelper<void ()>, std::__1::default_delete<ppapi::internal::RunWhileLockedHelper<void ()> > >), std::__1::unique_ptr<ppapi::internal::RunWhileLockedHelper<void ()>, std::__1::default_delete<ppapi::internal::RunWhileLockedHelper<void ()> > >&&) ./out/Debug/../../base/bind_internal.h:166:12
#32 0x7f7b30d238c3 in void base::internal::InvokeHelper<false, void>::MakeItSo<void (* const&)(std::__1::unique_ptr<ppapi::internal::RunWhileLockedHelper<void ()>, std::__1::default_delete<ppapi::internal::RunWhileLockedHelper<void ()> > >), std::__1::unique_ptr<ppapi::internal::RunWhileLockedHelper<void ()>, std::__1::default_delete<ppapi::internal::RunWhileLockedHelper<void ()> > > >(void (* const&)(std::__1::unique_ptr<ppapi::internal::RunWhileLockedHelper<void ()>, std::__1::default_delete<ppapi::internal::RunWhileLockedHelper<void ()> > >), std::__1::unique_ptr<ppapi::internal::RunWhileLockedHelper<void ()>, std::__1::default_delete<ppapi::internal::RunWhileLockedHelper<void ()> > >&&) ./out/Debug/../../base/bind_internal.h:294:12
#33 0x7f7b30d23667 in void base::internal::Invoker<base::internal::BindState<void (*)(std::__1::unique_ptr<ppapi::internal::RunWhileLockedHelper<void ()>, std::__1::default_delete<ppapi::internal::RunWhileLockedHelper<void ()> > >), base::internal::PassedWrapper<std::__1::unique_ptr<ppapi::internal::RunWhileLockedHelper<void ()>, std::__1::default_delete<ppapi::internal::RunWhileLockedHelper<void ()> > > > >, void ()>::RunImpl<void (* const&)(std::__1::unique_ptr<ppapi::internal::RunWhileLockedHelper<void ()>, std::__1::default_delete<ppapi::internal::RunWhileLockedHelper<void ()> > >), std::__1::tuple<base::internal::PassedWrapper<std::__1::unique_ptr<ppapi::internal::RunWhileLockedHelper<void ()>, std::__1::default_delete<ppapi::internal::RunWhileLockedHelper<void ()> > > > > const&, 0ul>(void (* const&)(std::__1::unique_ptr<ppapi::internal::RunWhileLockedHelper<void ()>, std::__1::default_delete<ppapi::internal::RunWhileLockedHelper<void ()> > >), std::__1::tuple<base::internal::PassedWrapper<std::__1::unique_ptr<ppapi::internal::RunWhileLockedHelper<void ()>, std::__1::default_delete<ppapi::internal::RunWhileLockedHelper<void ()> > > > > const&, std::__1::integer_sequence<unsigned long, 0ul>) ./out/Debug/../../base/bind_internal.h:368:12
#34 0x7f7b30d23472 in base::internal::Invoker<base::internal::BindState<void (*)(std::__1::unique_ptr<ppapi::internal::RunWhileLockedHelper<void ()>, std::__1::default_delete<ppapi::internal::RunWhileLockedHelper<void ()> > >), base::internal::PassedWrapper<std::__1::unique_ptr<ppapi::internal::RunWhileLockedHelper<void ()>, std::__1::default_delete<ppapi::internal::RunWhileLockedHelper<void ()> > > > >, void ()>::Run(base::internal::BindStateBase*) ./out/Debug/../../base/bind_internal.h:350:12
#35 0x7f7b676c708f in base::OnceCallback<void ()>::Run() && ./out/Debug/../../base/callback.h:65:12
#36 0x7f7b677e1a26 in base::debug::TaskAnnotator::RunTask(char const*, base::PendingTask*) ./out/Debug/../../base/debug/task_annotator.cc:55:33
#37 0x7f7b679e3e8a in base::internal::IncomingTaskQueue::RunTask(base::PendingTask*) ./out/Debug/../../base/message_loop/incoming_task_queue.cc:128:19
#38 0x7f7b679ff76e in base::MessageLoop::RunTask(base::PendingTask*) ./out/Debug/../../base/message_loop/message_loop.cc:391:25
#39 0x7f7b67a000cc in base::MessageLoop::DeferOrRunPendingTask(base::PendingTask) ./out/Debug/../../base/message_loop/message_loop.cc:403:5
#40 0x7f7b67a00a30 in base::MessageLoop::DoWork() ./out/Debug/../../base/message_loop/message_loop.cc:447:16
#41 0x7f7b67a23d6b in base::MessagePumpDefault::Run(base::MessagePump::Delegate*) ./out/Debug/../../base/message_loop/message_pump_default.cc:37:31
#42 0x7f7b679fdced in base::MessageLoop::Run(bool) ./out/Debug/../../base/message_loop/message_loop.cc:342:12
#43 0x7f7b67c85c77 in base::RunLoop::Run() ./out/Debug/../../base/run_loop.cc:130:14
#44 0x7f7b4dc05e2e in content::PpapiPluginMain(content::MainFunctionParams const&) ./out/Debug/../../content/ppapi_plugin/ppapi_plugin_main.cc:160:19
#45 0x7f7b58d09dcf in content::RunZygote(content::MainFunctionParams const&, content::ContentMainDelegate*) ./out/Debug/../../content/app/content_main_runner.cc:356:14
#46 0x7f7b58d0b8a9 in content::RunNamedProcessTypeMain(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, content::MainFunctionParams const&, content::ContentMainDelegate*) ./out/Debug/../../content/app/content_main_runner.cc:436:12
#47 0x7f7b58d145d1 in content::ContentMainRunnerImpl::Run() ./out/Debug/../../content/app/content_main_runner.cc:705:12
#48 0x7f7b58cf65b5 in content::ContentServiceManagerMainDelegate::RunEmbedderProcess() ./out/Debug/../../content/app/content_service_manager_main_delegate.cc:51:32
#49 0x7f7b689ec479 in service_manager::Main(service_manager::MainParams const&) ./out/Debug/../../services/service_manager/embedder/main.cc:456:29
#50 0x7f7b58d08cef in content::ContentMain(content::ContentMainParams const&) ./out/Debug/../../content/app/content_main.cc:19:10
#51 0x5602d10516b7 in ChromeMain ./out/Debug/../../chrome/app/chrome_main.cc:127:12
#52 0x5602d105128e in main ./out/Debug/../../chrome/app/chrome_exe_main_aura.cc:17:10
#53 0x7f7b0a8e12b0 in __libc_start_main ??:0:0
0x6070000546f4 is located 0 bytes to the right of 68-byte region [0x6070000546b0,0x6070000546f4)
allocated by thread T0 (chrome) here:
#0 0x5602d1021ea3 in __interceptor_malloc _asan_rtl_:3
#1 0x5602e7cf111c in pdfium::base::PartitionAllocGenericFlags(pdfium::base::PartitionRootGeneric*, int, unsigned long, char const*) ./out/Debug/../../third_party/pdfium/third_party/base/allocator/partition_allocator/partition_alloc.h:786:18
#2 0x5602e7cf0e43 in FX_SafeAlloc(unsigned long, unsigned long) ./out/Debug/../../third_party/pdfium/core/fxcrt/fx_memory.h:46:18
#3 0x5602e7cf0abb in FX_AllocOrDie(unsigned long, unsigned long) ./out/Debug/../../third_party/pdfium/core/fxcrt/fx_memory.h:67:22
#4 0x5602e7ffb112 in CFX_FixedBufGrow<float, 16>::CFX_FixedBufGrow(int) ./out/Debug/../../third_party/pdfium/core/fxcrt/cfx_fixedbufgrow.h:19:25
#5 0x5602e839ee78 in (anonymous namespace)::DrawRadialShading(fxcrt::RetainPtr<CFX_DIBitmap> const&, CFX_Matrix*, CPDF_Dictionary*, std::__1::vector<std::__1::unique_ptr<CPDF_Function, std::__1::default_delete<CPDF_Function> >, std::__1::allocator<std::__1::unique_ptr<CPDF_Function, std::__1::default_delete<CPDF_Function> > > > const&, CPDF_ColorSpace*, int) ./out/Debug/../../third_party/pdfium/core/fpdfapi/render/cpdf_renderstatus.cpp:222:31
#6 0x5602e839a7b5 in CPDF_RenderStatus::DrawShading(CPDF_ShadingPattern*, CFX_Matrix*, FX_RECT&, int, bool) ./out/Debug/../../third_party/pdfium/core/fpdfapi/render/cpdf_renderstatus.cpp:2124:7
#7 0x5602e83a588b in CPDF_RenderStatus::DrawShadingPattern(CPDF_ShadingPattern*, CPDF_PageObject const*, CFX_Matrix const*, bool) ./out/Debug/../../third_party/pdfium/core/fpdfapi/render/cpdf_renderstatus.cpp:2188:3
#8 0x5602e83ab243 in CPDF_RenderStatus::DrawPathWithPattern(CPDF_PathObject*, CFX_Matrix const*, CPDF_Color const*, bool) ./out/Debug/../../third_party/pdfium/core/fpdfapi/render/cpdf_renderstatus.cpp:2412:5
#9 0x5602e8388450 in CPDF_RenderStatus::ProcessPathPattern(CPDF_PathObject*, CFX_Matrix const*, int&, bool&) ./out/Debug/../../third_party/pdfium/core/fpdfapi/render/cpdf_renderstatus.cpp:2422:7
#10 0x5602e8385fa2 in CPDF_RenderStatus::ProcessPath(CPDF_PathObject*, CFX_Matrix const*) ./out/Debug/../../third_party/pdfium/core/fpdfapi/render/cpdf_renderstatus.cpp:1308:3
#11 0x5602e838252e in CPDF_RenderStatus::ProcessObjectNoClip(CPDF_PageObject*, CFX_Matrix const*) ./out/Debug/../../third_party/pdfium/core/fpdfapi/render/cpdf_renderstatus.cpp:1195:14
#12 0x5602e8382ec1 in CPDF_RenderStatus::ContinueSingleObject(CPDF_PageObject*, CFX_Matrix const*, IFX_PauseIndicator*) ./out/Debug/../../third_party/pdfium/core/fpdfapi/render/cpdf_renderstatus.cpp:1148:5
#13 0x5602e8372691 in CPDF_ProgressiveRenderer::Continue(IFX_PauseIndicator*) ./out/Debug/../../third_party/pdfium/core/fpdfapi/render/cpdf_progressiverenderer.cpp:93:30
#14 0x5602e8370481 in CPDF_ProgressiveRenderer::Start(IFX_PauseIndicator*) ./out/Debug/../../third_party/pdfium/core/fpdfapi/render/cpdf_progressiverenderer.cpp:44:3
#15 0x5602e7dfdecd in (anonymous namespace)::RenderPageImpl(CPDF_PageRenderContext*, CPDF_Page*, CFX_Matrix const&, FX_RECT const&, int, bool, IFSDK_PAUSE_Adapter*) ./out/Debug/../../third_party/pdfium/fpdfsdk/fpdfview.cpp:129:26
#16 0x5602e7dfa98f in FPDF_RenderPage_Retail(CPDF_PageRenderContext*, void*, int, int, int, int, int, int, bool, IFSDK_PAUSE_Adapter*) ./out/Debug/../../third_party/pdfium/fpdfsdk/fpdfview.cpp:1264:3
#17 0x5602e7cecb39 in FPDF_RenderPageBitmap_Start ./out/Debug/../../third_party/pdfium/fpdfsdk/fpdf_progressive.cpp:60:3
#18 0x5602e7bc3db6 in chrome_pdf::PDFiumEngine::ContinuePaint(int, pp::ImageData*) ./out/Debug/../../pdf/pdfium/pdfium_engine.cc:3257:10
#19 0x5602e7bc15f5 in chrome_pdf::PDFiumEngine::Paint(pp::Rect const&, pp::ImageData*, std::__1::vector<pp::Rect, std::__1::allocator<pp::Rect> >*, std::__1::vector<pp::Rect, std::__1::allocator<pp::Rect> >*) ./out/Debug/../../pdf/pdfium/pdfium_engine.cc:1117:11
#20 0x5602e7b527c0 in chrome_pdf::OutOfProcessInstance::OnPaint(std::__1::vector<pp::Rect, std::__1::allocator<pp::Rect> > const&, std::__1::vector<PaintManager::ReadyRect, std::__1::allocator<PaintManager::ReadyRect> >*, std::__1::vector<pp::Rect, std::__1::allocator<pp::Rect> >*) ./out/Debug/../../pdf/out_of_process_instance.cc:1064:16
#21 0x5602e7b883d9 in PaintManager::DoPaint() ./out/Debug/../../pdf/paint_manager.cc:235:12
#22 0x5602e7b86f25 in PaintManager::OnManualCallbackComplete(int) ./out/Debug/../../pdf/paint_manager.cc:345:5
#23 0x5602e7b8ef97 in pp::CompletionCallbackFactory<PaintManager, pp::ThreadSafeThreadTraits>::Dispatcher0<void (PaintManager::*)(int)>::operator()(PaintManager*, int) ./out/Debug/../../ppapi/utility/completion_callback_factory.h:607:9
#24 0x5602e7b8ec24 in pp::CompletionCallbackFactory<PaintManager, pp::ThreadSafeThreadTraits>::CallbackData<pp::CompletionCallbackFactory<PaintManager, pp::ThreadSafeThreadTraits>::Dispatcher0<void (PaintManager::*)(int)> >::Thunk(void*, int) ./out/Debug/../../ppapi/utility/completion_callback_factory.h:584:7
#25 0x7f7b30de9654 in PP_RunCompletionCallback(PP_CompletionCallback*, int) ./out/Debug/../../ppapi/c/pp_completion_callback.h:240:3
#26 0x7f7b30de953a in void ppapi::CallWhileUnlocked<void, PP_CompletionCallback*, int, PP_CompletionCallback*, int>(void (*)(PP_CompletionCallback*, int), PP_CompletionCallback* const&, int const&) ./out/Debug/../../ppapi/shared_impl/proxy_lock.h:135:10
#27 0x7f7b30de5db8 in ppapi::proxy::(anonymous namespace)::CallbackWrapper(PP_CompletionCallback, int) ./out/Debug/../../ppapi/proxy/ppb_core_proxy.cc:52:3
#28 0x7f7b30de8b69 in void base::internal::FunctorTraits<void (*)(PP_CompletionCallback, int), void>::Invoke<PP_CompletionCallback const&, int const&>(void (*)(PP_CompletionCallback, int), PP_CompletionCallback const&, int const&) ./out/Debug/../../base/bind_internal.h:166:12
#29 0x7f7b30de894b in void base::internal::InvokeHelper<false, void>::MakeItSo<void (* const&)(PP_CompletionCallback, int), PP_CompletionCallback const&, int const&>(void (* const&)(PP_CompletionCallback, int), PP_CompletionCallback const&, int const&) ./out/Debug/../../base/bind_internal.h:294:12
SUMMARY: AddressSanitizer: heap-buffer-overflow (/usr/local/google/home/markbrand/tmp/asan-linux-debug-523440/chrome+0x1bef94af)
Shadow bytes around the buggy address:
0x0c0e80002880: fa fa fd fd fd fd fd fd fd fd fd fa fa fa fa fa
0x0c0e80002890: fd fd fd fd fd fd fd fd fd fa fa fa fa fa 00 00
0x0c0e800028a0: 00 00 00 00 00 00 00 fa fa fa fa fa fd fd fd fd
0x0c0e800028b0: fd fd fd fd fd fa fa fa fa fa 00 00 00 00 00 00
0x0c0e800028c0: 00 00 00 fa fa fa fa fa 00 00 00 00 00 00 00 00
=>0x0c0e800028d0: 00 fa fa fa fa fa 00 00 00 00 00 00 00 00[04]fa
0x0c0e800028e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c0e800028f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c0e80002900: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c0e80002910: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c0e80002920: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==1==ABORTING
Client ID (if relevant): [see link above]
,
Dec 14 2017
,
Dec 14 2017
,
Dec 14 2017
ClusterFuzz is analyzing your testcase. Developers can follow the progress at https://clusterfuzz.com/testcase?key=5319405025361920.
,
Dec 14 2017
Blame on the helper function seems to indicate this has been around for a while in it's current state, so marking Impact-Stable. The clusterfuzz case is flakey (other PDF cases I've uploaded recently have been as well), but recommended High severity.
,
Dec 15 2017
,
Dec 15 2017
Thanks for the report. Able to reproduce locally with and without asan.
,
Dec 19 2017
The following revision refers to this bug: https://pdfium.googlesource.com/pdfium/+/30ef542b6f631f0ffbcd4110857e7c1a304a8a23 commit 30ef542b6f631f0ffbcd4110857e7c1a304a8a23 Author: Henrique Nakashima <hnakashima@chromium.org> Date: Tue Dec 19 19:49:53 2017 Add parameter validation to CPDF_ShadingPattern. Check if the ColorSpace and the Function params are valid for the shading type. Bug: chromium:794990 Change-Id: I022e976e5489a6b325d95ad16eab056235a8944d Reviewed-on: https://pdfium-review.googlesource.com/21450 Commit-Queue: Henrique Nakashima <hnakashima@chromium.org> Reviewed-by: Lei Zhang <thestig@chromium.org> [modify] https://crrev.com/30ef542b6f631f0ffbcd4110857e7c1a304a8a23/core/fpdfapi/page/cpdf_shadingpattern.h [modify] https://crrev.com/30ef542b6f631f0ffbcd4110857e7c1a304a8a23/core/fpdfapi/page/cpdf_shadingpattern.cpp
,
Dec 19 2017
,
Dec 19 2017
This bug requires manual review: M64 has already been promoted to the beta branch, so this requires manual review Please contact the milestone owner if you have questions. Owners: cmasso@(Android), cmasso@(iOS), kbleicher@(ChromeOS), abdulsyed@(Desktop) For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot
,
Dec 19 2017
,
Dec 20 2017
,
Dec 20 2017
Is this change well tested in Canary? Is this a safe merge overall?
,
Dec 21 2017
It's baking in Canary, so far so good. Let's give it a few days since the change is large?
,
Dec 21 2017
Can we run the PoC through ClusterFuzz with pdfium_test or pdfium_fuzzer in UBSAN mode? When the bug goes public, let's take the PoC, or maybe make a smaller hand crafted PDF as a EmbedderTest.
,
Dec 27 2017
abdulsyed@ - good for 64
,
Dec 28 2017
thanks awhalley@ hnaskashima@ - Can you please confirm how the data looks from Canary? thestig@ - has your suggestion in #15 been done? Is it a requirement for merging this to M64?
,
Jan 2 2018
No crashes from Canary, tested manually so I think we're good for merging. thestig@'s suggestion is to add a test only when the bug goes public in 14 weeks.
,
Jan 2 2018
Great, approved for M64. Branch:3282
,
Jan 2 2018
The following revision refers to this bug: https://pdfium.googlesource.com/pdfium/+/e7a562f725e2ed8d6c0be79a9d9f95745830a556 commit e7a562f725e2ed8d6c0be79a9d9f95745830a556 Author: Henrique Nakashima <hnakashima@chromium.org> Date: Tue Jan 02 19:24:59 2018 [Merge M64] Add parameter validation to CPDF_ShadingPattern. Check if the ColorSpace and the Function params are valid for the shading type. TBR=dsinclair@chromium.org Bug: chromium:794990 Change-Id: I022e976e5489a6b325d95ad16eab056235a8944d Reviewed-on: https://pdfium-review.googlesource.com/21450 Commit-Queue: Henrique Nakashima <hnakashima@chromium.org> Reviewed-by: Lei Zhang <thestig@chromium.org> (cherry picked from commit 30ef542b6f631f0ffbcd4110857e7c1a304a8a23) Reviewed-on: https://pdfium-review.googlesource.com/22030 Reviewed-by: Henrique Nakashima <hnakashima@chromium.org> [modify] https://crrev.com/e7a562f725e2ed8d6c0be79a9d9f95745830a556/core/fpdfapi/page/cpdf_shadingpattern.h [modify] https://crrev.com/e7a562f725e2ed8d6c0be79a9d9f95745830a556/core/fpdfapi/page/cpdf_shadingpattern.cpp
,
Jan 22 2018
,
Mar 27 2018
,
Mar 28 2018
This bug has been closed for more than 14 weeks. Removing security view restrictions. For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot |
|||||||||||||||
►
Sign in to add a comment |
|||||||||||||||
Comment 1 by elawrence@chromium.org
, Dec 14 2017Components: Internals>Plugins>PDF