diff options
-rw-r--r-- | fpdfsdk/javascript/Document.cpp | 32 | ||||
-rw-r--r-- | fpdfsdk/javascript/Field.cpp | 6 | ||||
-rw-r--r-- | fpdfsdk/javascript/JS_Define.h | 82 | ||||
-rw-r--r-- | fpdfsdk/javascript/JS_EventHandler.cpp | 30 | ||||
-rw-r--r-- | fpdfsdk/javascript/app.cpp | 11 | ||||
-rw-r--r-- | fxjs/fxjs_v8.cpp | 6 | ||||
-rw-r--r-- | testing/resources/javascript/bug_695826.in | 47 | ||||
-rw-r--r-- | testing/resources/javascript/bug_695826_expected.txt | 1 |
8 files changed, 140 insertions, 75 deletions
diff --git a/fpdfsdk/javascript/Document.cpp b/fpdfsdk/javascript/Document.cpp index 536d654463..6928a061a2 100644 --- a/fpdfsdk/javascript/Document.cpp +++ b/fpdfsdk/javascript/Document.cpp @@ -299,11 +299,13 @@ bool Document::getField(CJS_Runtime* pRuntime, v8::Local<v8::Object> pFieldObj = pRuntime->NewFxDynamicObj(CJS_Field::g_nObjDefnID); + if (pFieldObj.IsEmpty()) + return false; + CJS_Field* pJSField = static_cast<CJS_Field*>(pRuntime->GetObjectPrivate(pFieldObj)); Field* pField = static_cast<Field*>(pJSField->GetEmbedObject()); pField->AttachField(this, wideName); - vRet = CJS_Value(pRuntime, pJSField); return true; } @@ -1111,13 +1113,7 @@ bool Document::getAnnot(CJS_Runtime* pRuntime, CJS_Annot* pJS_Annot = static_cast<CJS_Annot*>(pRuntime->GetObjectPrivate(pObj)); - if (!pJS_Annot) - return false; - Annot* pAnnot = static_cast<Annot*>(pJS_Annot->GetEmbedObject()); - if (!pAnnot) - return false; - pAnnot->SetSDKAnnot(pSDKBAAnnot); vRet = CJS_Value(pRuntime, pJS_Annot); return true; @@ -1155,13 +1151,7 @@ bool Document::getAnnots(CJS_Runtime* pRuntime, CJS_Annot* pJS_Annot = static_cast<CJS_Annot*>(pRuntime->GetObjectPrivate(pObj)); - if (!pJS_Annot) - return false; - Annot* pAnnot = static_cast<Annot*>(pJS_Annot->GetEmbedObject()); - if (!pAnnot) - return false; - pAnnot->SetSDKAnnot(static_cast<CPDFSDK_BAAnnot*>(pSDKAnnotCur.Get())); annots.SetElement(pRuntime, i, CJS_Value(pRuntime, pJS_Annot)); } @@ -1258,13 +1248,7 @@ bool Document::icons(CJS_Runtime* pRuntime, CJS_Icon* pJS_Icon = static_cast<CJS_Icon*>(pRuntime->GetObjectPrivate(pObj)); - if (!pJS_Icon) - return false; - Icon* pIcon = static_cast<Icon*>(pJS_Icon->GetEmbedObject()); - if (!pIcon) - return false; - pIcon->SetIconName(pIconElement->IconName); Icons.SetElement(pRuntime, i++, CJS_Value(pRuntime, pJS_Icon)); } @@ -1297,13 +1281,7 @@ bool Document::getIcon(CJS_Runtime* pRuntime, CJS_Icon* pJS_Icon = static_cast<CJS_Icon*>(pRuntime->GetObjectPrivate(pObj)); - if (!pJS_Icon) - return false; - - Icon* pIcon = (Icon*)pJS_Icon->GetEmbedObject(); - if (!pIcon) - return false; - + Icon* pIcon = static_cast<Icon*>(pJS_Icon->GetEmbedObject()); pIcon->SetIconName(swIconName); vRet = CJS_Value(pRuntime, pJS_Icon); return true; @@ -1473,6 +1451,8 @@ bool Document::getPrintParams(CJS_Runtime* pRuntime, CFX_WideString& sError) { v8::Local<v8::Object> pRetObj = pRuntime->NewFxDynamicObj(CJS_PrintParamsObj::g_nObjDefnID); + if (pRetObj.IsEmpty()) + return false; // Not implemented yet. diff --git a/fpdfsdk/javascript/Field.cpp b/fpdfsdk/javascript/Field.cpp index 92b473b231..f37b3d486b 100644 --- a/fpdfsdk/javascript/Field.cpp +++ b/fpdfsdk/javascript/Field.cpp @@ -2835,7 +2835,8 @@ bool Field::buttonGetIcon(CJS_Runtime* pRuntime, v8::Local<v8::Object> pObj = pRuntime->NewFxDynamicObj(CJS_Icon::g_nObjDefnID); - ASSERT(pObj.IsEmpty() == false); + if (pObj.IsEmpty()) + return false; CJS_Icon* pJS_Icon = static_cast<CJS_Icon*>(pRuntime->GetObjectPrivate(pObj)); vRet = CJS_Value(pRuntime, pJS_Icon); @@ -2966,7 +2967,8 @@ bool Field::getArray(CJS_Runtime* pRuntime, for (const auto& pStr : swSort) { v8::Local<v8::Object> pObj = pRuntime->NewFxDynamicObj(CJS_Field::g_nObjDefnID); - ASSERT(!pObj.IsEmpty()); + if (pObj.IsEmpty()) + return false; CJS_Field* pJSField = static_cast<CJS_Field*>(pRuntime->GetObjectPrivate(pObj)); diff --git a/fpdfsdk/javascript/JS_Define.h b/fpdfsdk/javascript/JS_Define.h index ee7448c649..375ca3ac35 100644 --- a/fpdfsdk/javascript/JS_Define.h +++ b/fpdfsdk/javascript/JS_Define.h @@ -45,6 +45,8 @@ void JSPropGetter(const char* prop_name_string, return; CJS_Object* pJSObj = static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder())); + if (!pJSObj) + return; C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject()); CFX_WideString sError; CJS_PropValue value(pRuntime); @@ -69,6 +71,8 @@ void JSPropSetter(const char* prop_name_string, return; CJS_Object* pJSObj = static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder())); + if (!pJSObj) + return; C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject()); CFX_WideString sError; CJS_PropValue propValue(pRuntime, CJS_Value(pRuntime, value)); @@ -111,6 +115,8 @@ void JSMethod(const char* method_name_string, } CJS_Object* pJSObj = static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder())); + if (!pJSObj) + return; C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject()); CFX_WideString sError; CJS_Value valueRes(pRuntime); @@ -210,33 +216,31 @@ void JSMethod(const char* method_name_string, static JSPropertySpec PropertySpecs[]; \ static JSMethodSpec MethodSpecs[]; -#define IMPLEMENT_JS_CLASS_RICH_PART(js_class_name, class_alternate, \ - class_name) \ - void js_class_name::JSConstructor(CFXJS_Engine* pEngine, \ - v8::Local<v8::Object> obj) { \ - CJS_Object* pObj = new js_class_name(obj); \ - pObj->SetEmbedObject(new class_alternate(pObj)); \ - pEngine->SetObjectPrivate(obj, (void*)pObj); \ - pObj->InitInstance(static_cast<CJS_Runtime*>(pEngine)); \ - } \ - void js_class_name::JSDestructor(CFXJS_Engine* pEngine, \ - v8::Local<v8::Object> obj) { \ - js_class_name* pObj = \ - static_cast<js_class_name*>(pEngine->GetObjectPrivate(obj)); \ - delete pObj; \ - } \ - void js_class_name::DefineProps(CFXJS_Engine* pEngine) { \ - for (size_t i = 0; i < FX_ArraySize(PropertySpecs) - 1; ++i) { \ - pEngine->DefineObjProperty(g_nObjDefnID, PropertySpecs[i].pName, \ - PropertySpecs[i].pPropGet, \ - PropertySpecs[i].pPropPut); \ - } \ - } \ - void js_class_name::DefineMethods(CFXJS_Engine* pEngine) { \ - for (size_t i = 0; i < FX_ArraySize(MethodSpecs) - 1; ++i) { \ - pEngine->DefineObjMethod(g_nObjDefnID, MethodSpecs[i].pName, \ - MethodSpecs[i].pMethodCall); \ - } \ +#define IMPLEMENT_JS_CLASS_RICH_PART(js_class_name, class_alternate, \ + class_name) \ + void js_class_name::JSConstructor(CFXJS_Engine* pEngine, \ + v8::Local<v8::Object> obj) { \ + CJS_Object* pObj = new js_class_name(obj); \ + pObj->SetEmbedObject(new class_alternate(pObj)); \ + pEngine->SetObjectPrivate(obj, (void*)pObj); \ + pObj->InitInstance(static_cast<CJS_Runtime*>(pEngine)); \ + } \ + void js_class_name::JSDestructor(CFXJS_Engine* pEngine, \ + v8::Local<v8::Object> obj) { \ + delete static_cast<js_class_name*>(pEngine->GetObjectPrivate(obj)); \ + } \ + void js_class_name::DefineProps(CFXJS_Engine* pEngine) { \ + for (size_t i = 0; i < FX_ArraySize(PropertySpecs) - 1; ++i) { \ + pEngine->DefineObjProperty(g_nObjDefnID, PropertySpecs[i].pName, \ + PropertySpecs[i].pPropGet, \ + PropertySpecs[i].pPropPut); \ + } \ + } \ + void js_class_name::DefineMethods(CFXJS_Engine* pEngine) { \ + for (size_t i = 0; i < FX_ArraySize(MethodSpecs) - 1; ++i) { \ + pEngine->DefineObjMethod(g_nObjDefnID, MethodSpecs[i].pName, \ + MethodSpecs[i].pMethodCall); \ + } \ } // Special JS classes implement methods, props, and queries, but not consts. @@ -310,12 +314,18 @@ void JSSpecialPropQuery(const char*, const v8::PropertyCallbackInfo<v8::Integer>& info) { CJS_Runtime* pRuntime = CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate()); - v8::String::Utf8Value utf8_value(property); - CFX_WideString propname = CFX_WideString::FromUTF8( - CFX_ByteStringC(*utf8_value, utf8_value.length())); + if (!pRuntime) + return; + CJS_Object* pJSObj = static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder())); + if (!pJSObj) + return; + Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject()); + v8::String::Utf8Value utf8_value(property); + CFX_WideString propname = CFX_WideString::FromUTF8( + CFX_ByteStringC(*utf8_value, utf8_value.length())); bool bRet = pObj->QueryProperty(propname.c_str()); info.GetReturnValue().Set(bRet ? 4 : 0); } @@ -328,8 +338,12 @@ void JSSpecialPropGet(const char* class_name, CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate()); if (!pRuntime) return; + CJS_Object* pJSObj = static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder())); + if (!pJSObj) + return; + Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject()); v8::String::Utf8Value utf8_value(property); CFX_WideString propname = CFX_WideString::FromUTF8( @@ -353,8 +367,12 @@ void JSSpecialPropPut(const char* class_name, CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate()); if (!pRuntime) return; + CJS_Object* pJSObj = static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder())); + if (!pJSObj) + return; + Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject()); v8::String::Utf8Value utf8_value(property); CFX_WideString propname = CFX_WideString::FromUTF8( @@ -375,8 +393,12 @@ void JSSpecialPropDel(const char* class_name, CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate()); if (!pRuntime) return; + CJS_Object* pJSObj = static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder())); + if (!pJSObj) + return; + Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject()); v8::String::Utf8Value utf8_value(property); CFX_WideString propname = CFX_WideString::FromUTF8( diff --git a/fpdfsdk/javascript/JS_EventHandler.cpp b/fpdfsdk/javascript/JS_EventHandler.cpp index cec7735dc1..bd1c8e29d0 100644 --- a/fpdfsdk/javascript/JS_EventHandler.cpp +++ b/fpdfsdk/javascript/JS_EventHandler.cpp @@ -590,22 +590,25 @@ Field* CJS_EventHandler::Source() { CJS_Runtime* pRuntime = m_pJSEventContext->GetJSRuntime(); v8::Local<v8::Object> pDocObj = pRuntime->NewFxDynamicObj(CJS_Document::g_nObjDefnID); - ASSERT(!pDocObj.IsEmpty()); + if (pDocObj.IsEmpty()) + return nullptr; v8::Local<v8::Object> pFieldObj = pRuntime->NewFxDynamicObj(CJS_Field::g_nObjDefnID); - ASSERT(!pFieldObj.IsEmpty()); + if (pFieldObj.IsEmpty()) + return nullptr; CJS_Document* pJSDocument = static_cast<CJS_Document*>(pRuntime->GetObjectPrivate(pDocObj)); - Document* pDocument = (Document*)pJSDocument->GetEmbedObject(); + CJS_Field* pJSField = + static_cast<CJS_Field*>(pRuntime->GetObjectPrivate(pFieldObj)); + + Document* pDocument = static_cast<Document*>(pJSDocument->GetEmbedObject()); pDocument->SetFormFillEnv(m_pTargetFormFillEnv ? m_pTargetFormFillEnv.Get() : m_pJSEventContext->GetFormFillEnv()); - CJS_Field* pJSField = - static_cast<CJS_Field*>(pRuntime->GetObjectPrivate(pFieldObj)); - Field* pField = (Field*)pJSField->GetEmbedObject(); + Field* pField = static_cast<Field*>(pJSField->GetEmbedObject()); pField->AttachField(pDocument, m_strSourceName); return pField; } @@ -614,22 +617,25 @@ Field* CJS_EventHandler::Target_Field() { CJS_Runtime* pRuntime = m_pJSEventContext->GetJSRuntime(); v8::Local<v8::Object> pDocObj = pRuntime->NewFxDynamicObj(CJS_Document::g_nObjDefnID); - ASSERT(!pDocObj.IsEmpty()); + if (pDocObj.IsEmpty()) + return nullptr; v8::Local<v8::Object> pFieldObj = pRuntime->NewFxDynamicObj(CJS_Field::g_nObjDefnID); - ASSERT(!pFieldObj.IsEmpty()); + if (pFieldObj.IsEmpty()) + return nullptr; CJS_Document* pJSDocument = static_cast<CJS_Document*>(pRuntime->GetObjectPrivate(pDocObj)); - Document* pDocument = (Document*)pJSDocument->GetEmbedObject(); + CJS_Field* pJSField = + static_cast<CJS_Field*>(pRuntime->GetObjectPrivate(pFieldObj)); + + Document* pDocument = static_cast<Document*>(pJSDocument->GetEmbedObject()); pDocument->SetFormFillEnv(m_pTargetFormFillEnv ? m_pTargetFormFillEnv.Get() : m_pJSEventContext->GetFormFillEnv()); - CJS_Field* pJSField = - static_cast<CJS_Field*>(pRuntime->GetObjectPrivate(pFieldObj)); - Field* pField = (Field*)pJSField->GetEmbedObject(); + Field* pField = static_cast<Field*>(pJSField->GetEmbedObject()); pField->AttachField(pDocument, m_strTargetName); return pField; } diff --git a/fpdfsdk/javascript/app.cpp b/fpdfsdk/javascript/app.cpp index 0c75f6be4a..3a8bf088f3 100644 --- a/fpdfsdk/javascript/app.cpp +++ b/fpdfsdk/javascript/app.cpp @@ -215,13 +215,11 @@ bool app::activeDocs(CJS_Runtime* pRuntime, CJS_Document* pJSDocument = nullptr; v8::Local<v8::Object> pObj = pRuntime->GetThisObj(); - if (CFXJS_Engine::GetObjDefnID(pObj) == CJS_Document::g_nObjDefnID) { + if (CFXJS_Engine::GetObjDefnID(pObj) == CJS_Document::g_nObjDefnID) pJSDocument = static_cast<CJS_Document*>(pRuntime->GetObjectPrivate(pObj)); - } CJS_Array aDocs; aDocs.SetElement(pRuntime, 0, CJS_Value(pRuntime, pJSDocument)); - if (aDocs.GetLength(pRuntime) > 0) vp << aDocs; else @@ -472,6 +470,9 @@ bool app::setInterval(CJS_Runtime* pRuntime, v8::Local<v8::Object> pRetObj = pRuntime->NewFxDynamicObj(CJS_TimerObj::g_nObjDefnID); + if (pRetObj.IsEmpty()) + return false; + CJS_TimerObj* pJS_TimerObj = static_cast<CJS_TimerObj*>(pRuntime->GetObjectPrivate(pRetObj)); TimerObj* pTimerObj = static_cast<TimerObj*>(pJS_TimerObj->GetEmbedObject()); @@ -504,13 +505,13 @@ bool app::setTimeOut(CJS_Runtime* pRuntime, v8::Local<v8::Object> pRetObj = pRuntime->NewFxDynamicObj(CJS_TimerObj::g_nObjDefnID); + if (pRetObj.IsEmpty()) + return false; CJS_TimerObj* pJS_TimerObj = static_cast<CJS_TimerObj*>(pRuntime->GetObjectPrivate(pRetObj)); - TimerObj* pTimerObj = static_cast<TimerObj*>(pJS_TimerObj->GetEmbedObject()); pTimerObj->SetTimer(timerRef); - vRet = CJS_Value(pRuntime, pRetObj); return true; } diff --git a/fxjs/fxjs_v8.cpp b/fxjs/fxjs_v8.cpp index 053db07d3b..0c211a130a 100644 --- a/fxjs/fxjs_v8.cpp +++ b/fxjs/fxjs_v8.cpp @@ -56,6 +56,12 @@ class CFXJS_ObjDefinition { v8::Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate); fun->InstanceTemplate()->SetInternalFieldCount(2); + fun->SetCallHandler([](const v8::FunctionCallbackInfo<v8::Value>& info) { + v8::Local<v8::Object> holder = info.Holder(); + ASSERT(holder->InternalFieldCount() == 2); + holder->SetAlignedPointerInInternalField(0, nullptr); + holder->SetAlignedPointerInInternalField(1, nullptr); + }); if (eObjType == FXJSOBJTYPE_GLOBAL) { fun->InstanceTemplate()->Set( v8::Symbol::GetToStringTag(isolate), diff --git a/testing/resources/javascript/bug_695826.in b/testing/resources/javascript/bug_695826.in new file mode 100644 index 0000000000..b20908bc79 --- /dev/null +++ b/testing/resources/javascript/bug_695826.in @@ -0,0 +1,47 @@ +{{header}} +{{object 1 0}} << + /Type /Catalog + /Pages 2 0 R + /OpenAction 10 0 R +>> +endobj +{{object 2 0}} << + /Type /Pages + /Count 1 + /Kids [ + 3 0 R + ] +>> +endobj +% Page number 0. +{{object 3 0}} << + /Type /Page + /Parent 2 0 R + /Resources << + /Font <</F1 15 0 R>> + >> + /Contents [21 0 R] + /MediaBox [0 0 612 792] +>> +% OpenAction action +{{object 10 0}} << + /Type /Action + /S /JavaScript + /JS 11 0 R +>> +endobj +% JS program to exexute +{{object 11 0}} << +>> +stream +var obj = new this.constructor; +obj.author = 3; +app.alert('Done!'); +endstream +endobj +{{xref}} +trailer << + /Root 1 0 R +>> +{{startxref}} +%%EOF diff --git a/testing/resources/javascript/bug_695826_expected.txt b/testing/resources/javascript/bug_695826_expected.txt new file mode 100644 index 0000000000..5bb6e85966 --- /dev/null +++ b/testing/resources/javascript/bug_695826_expected.txt @@ -0,0 +1 @@ +Alert: Done! |