From f29479d47156d180c0b71f6c98aa4de37c2a7ee2 Mon Sep 17 00:00:00 2001 From: Tom Sepez Date: Fri, 8 Jun 2018 18:22:24 +0000 Subject: Fix issue with resolveNodes() not found off global proxy object. We used to assume that a global proxy object could be distinguished by it not having two internal fields, but that invariant isn't correct. Instead, flag it as such so the block of code at line 126 will check the prototype to find an actual object. Squeeze some bytes out of the tags while were at it, no reason for them to be wide. Also remove GetGlobalObjectFromContext() helper, for transparency into what's really going on in v8. This then shows a needless retrieval of an object we already have in one case. Bug: pdfium:1097 Change-Id: Iafc356373166fe5fda76ea7d64193826ee69a6c3 Reviewed-on: https://pdfium-review.googlesource.com/34630 Reviewed-by: dsinclair Commit-Queue: Tom Sepez --- fxjs/README | 8 +++++--- fxjs/cfxjse_context.cpp | 38 +++++++++++++++++++------------------- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/fxjs/README b/fxjs/README index 6590b58e3c..a1cfe322bf 100644 --- a/fxjs/README +++ b/fxjs/README @@ -20,7 +20,8 @@ To distinguish these cases, we use two internal slots for all bound objects, regardless of the FXJS/FXJSE distinction. Slot 0 is the tag and contains either: kPerObjectDataTag for FXJS objects, or - g_FXJSETagString for FXJSE Host objects, or + g_FXJSEHostObjectTag for FXJSE Host objects, or + g_FXJSEProxyObjectTag for a global proxy object under FXJSE, or One of 4 specific FXJSE_CLASS_DESCRIPTOR globals for FXJSE classes: GlobalClassDescriptor NormalClassDescriptor @@ -29,9 +30,10 @@ tag and contains either: Slot 1's contents are determined by these tags: kPerObjectDataTag means an aligned pointer to CFXJS_PerObjectData. - g_FXJSETagString means an aligned pointer to CFXJSE_HostObject. + g_FXJSEHostObjectTag means an aligned pointer to CFXJSE_HostObject. + g_FXJSEProxyObjectTag means nullptr, and to check the prototype instead. A FXJSE_CLASS_DESCRIPTOR pointer means to expect an actual v8 function - object, and not an aligned pointer. + object (or a string naming that function), and not an aligned pointer. Because PDFium uses V8 for various unrelated purposes, there may be up to four v8::Contexts (JS Global Objects) associated with each document. One is diff --git a/fxjs/cfxjse_context.cpp b/fxjs/cfxjse_context.cpp index e9297e5bb2..7ee561095b 100644 --- a/fxjs/cfxjse_context.cpp +++ b/fxjs/cfxjse_context.cpp @@ -42,7 +42,9 @@ const char szCompatibleModeScript[] = " }\n" "}(this, {String: ['substr', 'toUpperCase']}));"; -wchar_t g_FXJSETagString[] = L"FXJSE_HostObject"; +// Only address matters, values are for humans debuging here. +char g_FXJSEHostObjectTag[] = "FXJSE Host Object"; +char g_FXJSEProxyObjectTag[] = "FXJSE Proxy Object"; v8::Local CreateReturnValue(v8::Isolate* pIsolate, v8::TryCatch& trycatch) { @@ -85,11 +87,6 @@ v8::Local CreateReturnValue(v8::Isolate* pIsolate, return hReturnValue; } -v8::Local GetGlobalObjectFromContext( - v8::Local hContext) { - return hContext->Global()->GetPrototype().As(); -} - class CFXJSE_ScopeUtil_IsolateHandleContext { public: explicit CFXJSE_ScopeUtil_IsolateHandleContext(CFXJSE_Context* pContext) @@ -106,13 +103,20 @@ class CFXJSE_ScopeUtil_IsolateHandleContext { v8::Context::Scope m_cscope; }; +void FXJSE_UpdateProxyBinding(v8::Local& hObject) { + ASSERT(!hObject.IsEmpty()); + ASSERT(hObject->InternalFieldCount() == 2); + hObject->SetAlignedPointerInInternalField(0, g_FXJSEProxyObjectTag); + hObject->SetAlignedPointerInInternalField(1, nullptr); +} + } // namespace void FXJSE_UpdateObjectBinding(v8::Local& hObject, CFXJSE_HostObject* lpNewBinding) { ASSERT(!hObject.IsEmpty()); ASSERT(hObject->InternalFieldCount() == 2); - hObject->SetAlignedPointerInInternalField(0, g_FXJSETagString); + hObject->SetAlignedPointerInInternalField(0, g_FXJSEHostObjectTag); hObject->SetAlignedPointerInInternalField(1, lpNewBinding); } @@ -123,7 +127,8 @@ CFXJSE_HostObject* FXJSE_RetrieveObjectBinding(v8::Local hJSObject, return nullptr; v8::Local hObject = hJSObject; - if (hObject->InternalFieldCount() != 2) { + if (hObject->InternalFieldCount() != 2 || + hObject->GetAlignedPointerFromInternalField(0) == g_FXJSEProxyObjectTag) { v8::Local hProtoObject = hObject->GetPrototype(); if (hProtoObject.IsEmpty() || !hProtoObject->IsObject()) return nullptr; @@ -132,8 +137,9 @@ CFXJSE_HostObject* FXJSE_RetrieveObjectBinding(v8::Local hJSObject, if (hObject->InternalFieldCount() != 2) return nullptr; } - if (hObject->GetAlignedPointerFromInternalField(0) != g_FXJSETagString) + if (hObject->GetAlignedPointerFromInternalField(0) != g_FXJSEHostObjectTag) return nullptr; + if (lpClass) { v8::Local hClass = v8::Local::New( @@ -175,21 +181,14 @@ std::unique_ptr CFXJSE_Context::Create( v8::Context::New(pIsolate, nullptr, hObjectTemplate); v8::Local pThisProxy = hNewContext->Global(); - ASSERT(pThisProxy->InternalFieldCount() == 2); - pThisProxy->SetAlignedPointerInInternalField(0, nullptr); - pThisProxy->SetAlignedPointerInInternalField(1, nullptr); + FXJSE_UpdateProxyBinding(pThisProxy); v8::Local pThis = pThisProxy->GetPrototype().As(); - ASSERT(pThis->InternalFieldCount() == 2); - pThis->SetAlignedPointerInInternalField(0, nullptr); - pThis->SetAlignedPointerInInternalField(1, nullptr); + FXJSE_UpdateObjectBinding(pThis, pGlobalObject); v8::Local hRootContext = v8::Local::New( pIsolate, CFXJSE_RuntimeData::Get(pIsolate)->m_hRootContext); hNewContext->SetSecurityToken(hRootContext->GetSecurityToken()); - - v8::Local hGlobalObject = GetGlobalObjectFromContext(hNewContext); - FXJSE_UpdateObjectBinding(hGlobalObject, pGlobalObject); pContext->m_hContext.Reset(pIsolate, hNewContext); return pContext; } @@ -203,7 +202,8 @@ std::unique_ptr CFXJSE_Context::GetGlobalObject() { CFXJSE_ScopeUtil_IsolateHandleContext scope(this); v8::Local hContext = v8::Local::New(m_pIsolate, m_hContext); - v8::Local hGlobalObject = GetGlobalObjectFromContext(hContext); + v8::Local hGlobalObject = + hContext->Global()->GetPrototype().As(); pValue->ForceSetValue(hGlobalObject); return pValue; } -- cgit v1.2.3