Do not access form_fill_env_ until after last re-entrant JS call. Follow-on from https://pdfium-review.googlesource.com/c/pdfium/+/147790, but again this should not be reachable unless an embedder is doing some unexpected cleanup. Change-Id: Ibdc3ec6e97e5c5c4fe534ad95778e04050844256 Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/147930 Commit-Queue: Tom Sepez <tsepez@chromium.org> Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/fxjs/cjs_document.cpp b/fxjs/cjs_document.cpp index 0b8e0f9..338d319 100644 --- a/fxjs/cjs_document.cpp +++ b/fxjs/cjs_document.cpp
@@ -166,12 +166,15 @@ CJS_Result CJS_Document::set_dirty(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) { + const bool is_dirty = pRuntime->ToBooleanReentrant(vp); if (!form_fill_env_) { return CJS_Result::Failure(JSMessage::kBadObjectError); } - - pRuntime->ToBooleanReentrant(vp) ? form_fill_env_->SetChangeMark() - : form_fill_env_->ClearChangeMark(); + if (is_dirty) { + form_fill_env_->SetChangeMark(); + } else { + form_fill_env_->ClearChangeMark(); + } return CJS_Result::Success(); } @@ -199,12 +202,12 @@ CJS_Result CJS_Document::set_page_num(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) { + int iPageNum = pRuntime->ToInt32Reentrant(vp); if (!form_fill_env_) { return CJS_Result::Failure(JSMessage::kBadObjectError); } int iPageCount = form_fill_env_->GetPageCount(); - int iPageNum = pRuntime->ToInt32Reentrant(vp); if (iPageNum >= 0 && iPageNum < iPageCount) { form_fill_env_->JS_docgotoPage(iPageNum); } else if (iPageNum >= iPageCount) { @@ -255,11 +258,11 @@ return CJS_Result::Failure(JSMessage::kParamError); } + WideString wideName = pRuntime->ToWideStringReentrant(params[0]); if (!form_fill_env_) { return CJS_Result::Failure(JSMessage::kBadObjectError); } - WideString wideName = pRuntime->ToWideStringReentrant(params[0]); CPDF_InteractiveForm* pPDFForm = GetCoreInteractiveForm(); if (pPDFForm->CountFields(wideName) <= 0) { return CJS_Result::Success(pRuntime->NewUndefined()); @@ -288,15 +291,16 @@ if (params.size() != 1) { return CJS_Result::Failure(JSMessage::kParamError); } - if (!form_fill_env_) { - return CJS_Result::Failure(JSMessage::kBadObjectError); - } int nIndex = pRuntime->ToInt32Reentrant(params[0]); if (nIndex < 0) { return CJS_Result::Failure(JSMessage::kValueError); } + if (!form_fill_env_) { + return CJS_Result::Failure(JSMessage::kBadObjectError); + } + CPDF_InteractiveForm* pPDFForm = GetCoreInteractiveForm(); CPDF_FormField* pField = pPDFForm->GetField(nIndex, WideString()); if (!pField) { @@ -329,10 +333,6 @@ CJS_Result CJS_Document::mailDoc(CJS_Runtime* pRuntime, pdfium::span<v8::Local<v8::Value>> params) { - if (!form_fill_env_) { - return CJS_Result::Failure(JSMessage::kBadObjectError); - } - v8::LocalVector<v8::Value> newParams = ExpandKeywordParams( pRuntime, params, 6, "bUI", "cTo", "cCc", "cBcc", "cSubject", "cMsg"); @@ -366,6 +366,10 @@ cMsg = pRuntime->ToWideStringReentrant(newParams[5]); } + if (!form_fill_env_) { + return CJS_Result::Failure(JSMessage::kBadObjectError); + } + pRuntime->BeginBlock(); form_fill_env_->JS_docmailForm(pdfium::span<const uint8_t>(), bUI, cTo, cSubject, cCc, cBcc, cMsg); @@ -378,21 +382,6 @@ // comment: need reader supports CJS_Result CJS_Document::mailForm(CJS_Runtime* pRuntime, pdfium::span<v8::Local<v8::Value>> params) { - if (!form_fill_env_) { - return CJS_Result::Failure(JSMessage::kBadObjectError); - } - - using pdfium::access_permissions::kExtractForAccessibility; - if (!form_fill_env_->HasPermissions(kExtractForAccessibility)) { - return CJS_Result::Failure(JSMessage::kPermissionError); - } - - CPDFSDK_InteractiveForm* pInteractiveForm = GetSDKInteractiveForm(); - ByteString sTextBuf = pInteractiveForm->ExportFormToFDFTextBuf(); - if (sTextBuf.IsEmpty()) { - return CJS_Result::Failure(WideString::FromASCII("Bad FDF format.")); - } - v8::LocalVector<v8::Value> newParams = ExpandKeywordParams( pRuntime, params, 6, "bUI", "cTo", "cCc", "cBcc", "cSubject", "cMsg"); @@ -426,6 +415,21 @@ cMsg = pRuntime->ToWideStringReentrant(newParams[5]); } + if (!form_fill_env_) { + return CJS_Result::Failure(JSMessage::kBadObjectError); + } + + using pdfium::access_permissions::kExtractForAccessibility; + if (!form_fill_env_->HasPermissions(kExtractForAccessibility)) { + return CJS_Result::Failure(JSMessage::kPermissionError); + } + + CPDFSDK_InteractiveForm* pInteractiveForm = GetSDKInteractiveForm(); + ByteString sTextBuf = pInteractiveForm->ExportFormToFDFTextBuf(); + if (sTextBuf.IsEmpty()) { + return CJS_Result::Failure(WideString::FromASCII("Bad FDF format.")); + } + pRuntime->BeginBlock(); form_fill_env_->JS_docmailForm(sTextBuf.unsigned_span(), bUI, cTo, cSubject, cCc, cBcc, cMsg); @@ -502,17 +506,17 @@ if (params.size() != 1) { return CJS_Result::Failure(JSMessage::kParamError); } + WideString sFieldName = pRuntime->ToWideStringReentrant(params[0]); + if (!form_fill_env_) { return CJS_Result::Failure(JSMessage::kBadObjectError); } - if (!form_fill_env_->HasPermissions( pdfium::access_permissions::kModifyContent | pdfium::access_permissions::kModifyAnnotation)) { return CJS_Result::Failure(JSMessage::kPermissionError); } - WideString sFieldName = pRuntime->ToWideStringReentrant(params[0]); CPDFSDK_InteractiveForm* pInteractiveForm = GetSDKInteractiveForm(); std::vector<ObservedPtr<CPDFSDK_Widget>> widgets; pInteractiveForm->GetWidgets(sFieldName, &widgets); @@ -590,7 +594,9 @@ if (!aFields.empty()) { pPDFForm->ResetForm(aFields, true); - form_fill_env_->SetChangeMark(); + if (form_fill_env_) { + form_fill_env_->SetChangeMark(); + } } return CJS_Result::Success(); @@ -614,10 +620,6 @@ if (nSize < 1) { return CJS_Result::Failure(JSMessage::kParamError); } - if (!form_fill_env_) { - return CJS_Result::Failure(JSMessage::kBadObjectError); - } - CJS_EventContext* pHandler = pRuntime->GetCurrentEventContext(); if (!pHandler->IsUserGesture()) { return CJS_Result::Failure(JSMessage::kUserGestureRequiredError); @@ -654,6 +656,10 @@ pRuntime->GetObjectPropertyReentrant(pObj, "aFields")); } + if (!form_fill_env_) { + return CJS_Result::Failure(JSMessage::kBadObjectError); + } + CPDF_InteractiveForm* pPDFForm = GetCoreInteractiveForm(); if (pRuntime->GetArrayLength(aFields) == 0 && bEmpty) { if (pPDFForm->CheckRequiredFields(nullptr, true)) { @@ -674,7 +680,6 @@ if (!bEmpty && pField->GetValue().IsEmpty()) { continue; } - fieldObjects.push_back(pField); } } @@ -822,6 +827,8 @@ CJS_Result CJS_Document::set_delay(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) { + const bool delay = pRuntime->ToBooleanReentrant(vp); + if (!form_fill_env_) { return CJS_Result::Failure(JSMessage::kBadObjectError); } @@ -831,7 +838,7 @@ return CJS_Result::Failure(JSMessage::kPermissionError); } - delay_ = pRuntime->ToBooleanReentrant(vp); + delay_ = delay; if (delay_) { delay_data_.clear(); return CJS_Result::Success(); @@ -1069,12 +1076,14 @@ if (params.size() != 2) { return CJS_Result::Failure(JSMessage::kParamError); } + + int nPageNo = pRuntime->ToInt32Reentrant(params[0]); + WideString swAnnotName = pRuntime->ToWideStringReentrant(params[1]); + if (!form_fill_env_) { return CJS_Result::Failure(JSMessage::kBadObjectError); } - int nPageNo = pRuntime->ToInt32Reentrant(params[0]); - WideString swAnnotName = pRuntime->ToWideStringReentrant(params[1]); CPDFSDK_PageView* pPageView = form_fill_env_->GetPageViewAtIndex(nPageNo); if (!pPageView) { return CJS_Result::Failure(JSMessage::kBadObjectError); @@ -1308,6 +1317,13 @@ CJS_Result CJS_Document::getPageNthWord( CJS_Runtime* pRuntime, pdfium::span<v8::Local<v8::Value>> params) { + int nPageNo = params.size() > 0 ? pRuntime->ToInt32Reentrant(params[0]) : 0; + int nWordNo = params.size() > 1 ? pRuntime->ToInt32Reentrant(params[1]) : 0; + bool bStrip = + params.size() > 2 ? pRuntime->ToBooleanReentrant(params[2]) : true; + + // TODO(tsepez): check maximum allowable params. + if (!form_fill_env_) { return CJS_Result::Failure(JSMessage::kBadObjectError); } @@ -1317,13 +1333,6 @@ return CJS_Result::Failure(JSMessage::kPermissionError); } - // TODO(tsepez): check maximum allowable params. - - int nPageNo = params.size() > 0 ? pRuntime->ToInt32Reentrant(params[0]) : 0; - int nWordNo = params.size() > 1 ? pRuntime->ToInt32Reentrant(params[1]) : 0; - bool bStrip = - params.size() > 2 ? pRuntime->ToBooleanReentrant(params[2]) : true; - CPDF_Document* document = form_fill_env_->GetPDFDocument(); if (nPageNo < 0 || nPageNo >= document->GetPageCount()) { return CJS_Result::Failure(JSMessage::kValueError); @@ -1377,6 +1386,8 @@ CJS_Result CJS_Document::getPageNumWords( CJS_Runtime* pRuntime, pdfium::span<v8::Local<v8::Value>> params) { + int nPageNo = params.size() > 0 ? pRuntime->ToInt32Reentrant(params[0]) : 0; + if (!form_fill_env_) { return CJS_Result::Failure(JSMessage::kBadObjectError); } @@ -1386,7 +1397,6 @@ return CJS_Result::Failure(JSMessage::kPermissionError); } - int nPageNo = params.size() > 0 ? pRuntime->ToInt32Reentrant(params[0]) : 0; CPDF_Document* document = form_fill_env_->GetPDFDocument(); if (nPageNo < 0 || nPageNo >= document->GetPageCount()) { return CJS_Result::Failure(JSMessage::kValueError); @@ -1475,14 +1485,15 @@ if (params.size() != 1) { return CJS_Result::Failure(JSMessage::kParamError); } + const ByteString dest_name = pRuntime->ToByteStringReentrant(params[0]); if (!form_fill_env_) { return CJS_Result::Failure(JSMessage::kBadObjectError); } CPDF_Document* document = form_fill_env_->GetPDFDocument(); - RetainPtr<const CPDF_Array> dest_array = CPDF_NameTree::LookupNamedDest( - document, pRuntime->ToByteStringReentrant(params[0])); + RetainPtr<const CPDF_Array> dest_array = + CPDF_NameTree::LookupNamedDest(document, dest_name); if (!dest_array) { return CJS_Result::Failure(JSMessage::kBadObjectError); }
diff --git a/fxjs/cjs_field.cpp b/fxjs/cjs_field.cpp index c020254..e8c1658 100644 --- a/fxjs/cjs_field.cpp +++ b/fxjs/cjs_field.cpp
@@ -2179,8 +2179,6 @@ CJS_Result CJS_Field::set_text_font(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) { - DCHECK(form_fill_env_); - if (!can_set_) { return CJS_Result::Failure(JSMessage::kReadOnlyError); }
diff --git a/fxjs/cjs_publicmethods.cpp b/fxjs/cjs_publicmethods.cpp index 29349a8..38d7839 100644 --- a/fxjs/cjs_publicmethods.cpp +++ b/fxjs/cjs_publicmethods.cpp
@@ -1378,8 +1378,12 @@ v8::Local<v8::Array> FieldNameArray = AF_MakeArrayFromList(pRuntime, params[1]); - CPDFSDK_InteractiveForm* pReaderForm = - pRuntime->GetFormFillEnv()->GetInteractiveForm(); + CPDFSDK_FormFillEnvironment* form_fill_env = pRuntime->GetFormFillEnv(); + if (!form_fill_env) { + return CJS_Result::Failure(JSMessage::kBadObjectError); + } + + CPDFSDK_InteractiveForm* pReaderForm = form_fill_env->GetInteractiveForm(); CPDF_InteractiveForm* pForm = pReaderForm->GetInteractiveForm(); double dValue = sFunction.EqualsASCII("PRD") ? 1.0 : 0.0;