Speculative fix for uninitialized value in CFX_ByteString(). If somehow different length values could be obtained by two successive calls to Doc_getFilePath() (and FieldBrowse() for that matter), and the method is true to the API documentation that says "The return value always indicated number of bytes required for the buffer, even when there is no buffer specified, or the buffer size is less then required", then it is possible to get a returned length describing memory beyond the current buffer. We can make the corresponding JS_docGetFilePath() method more robust against this case by applying better checks to the returned value. This probably is unrelated since ASAN seems to be flagging the corresponding bug as UAF, but doesn't hurt to make things more robust. BUG=392956 R=jun_fang@foxitsoftware.com Review URL: https://codereview.chromium.org/423233002
diff --git a/fpdfsdk/include/fsdk_mgr.h b/fpdfsdk/include/fsdk_mgr.h index d7e4e3d..95d1a79 100644 --- a/fpdfsdk/include/fsdk_mgr.h +++ b/fpdfsdk/include/fsdk_mgr.h
@@ -173,18 +173,24 @@ CFX_WideString JS_fieldBrowse() { - if(m_pInfo && m_pInfo->m_pJsPlatform && m_pInfo->m_pJsPlatform->Field_browse) + if (m_pInfo && m_pInfo->m_pJsPlatform && m_pInfo->m_pJsPlatform->Field_browse) { - int nLen = m_pInfo->m_pJsPlatform->Field_browse(m_pInfo->m_pJsPlatform, NULL, 0); - if(nLen <= 0) + int nRequiredLen = m_pInfo->m_pJsPlatform->Field_browse(m_pInfo->m_pJsPlatform, NULL, 0); + if (nRequiredLen <= 0) return L""; - char* pbuff = new char[nLen]; - if(pbuff) - memset(pbuff, 0, nLen); - else + + char* pbuff = new char[nRequiredLen]; + if (!pbuff) return L""; - nLen = m_pInfo->m_pJsPlatform->Field_browse(m_pInfo->m_pJsPlatform, pbuff, nLen); - CFX_ByteString bsRet = CFX_ByteString(pbuff, nLen); + + memset(pbuff, 0, nRequiredLen); + int nActualLen = m_pInfo->m_pJsPlatform->Field_browse(m_pInfo->m_pJsPlatform, pbuff, nRequiredLen); + if (nActualLen <= 0 || nActualLen > nRequiredLen) + { + delete[] pbuff; + return L""; + } + CFX_ByteString bsRet = CFX_ByteString(pbuff, nActualLen); CFX_WideString wsRet = CFX_WideString::FromLocal(bsRet); delete[] pbuff; return wsRet; @@ -193,19 +199,25 @@ } CFX_WideString JS_docGetFilePath() - { - if(m_pInfo && m_pInfo->m_pJsPlatform && m_pInfo->m_pJsPlatform->Doc_getFilePath) + { + if (m_pInfo && m_pInfo->m_pJsPlatform && m_pInfo->m_pJsPlatform->Doc_getFilePath) { - int nLen = m_pInfo->m_pJsPlatform->Doc_getFilePath(m_pInfo->m_pJsPlatform, NULL, 0); - if(nLen <= 0) + int nRequiredLen = m_pInfo->m_pJsPlatform->Doc_getFilePath(m_pInfo->m_pJsPlatform, NULL, 0); + if (nRequiredLen <= 0) return L""; - char* pbuff = new char[nLen]; - if(pbuff) - memset(pbuff, 0, nLen); - else + + char* pbuff = new char[nRequiredLen]; + if (!pbuff) return L""; - nLen = m_pInfo->m_pJsPlatform->Doc_getFilePath(m_pInfo->m_pJsPlatform, pbuff, nLen); - CFX_ByteString bsRet = CFX_ByteString(pbuff, nLen); + + memset(pbuff, 0, nRequiredLen); + int nActualLen = m_pInfo->m_pJsPlatform->Doc_getFilePath(m_pInfo->m_pJsPlatform, pbuff, nRequiredLen); + if (nActualLen <= 0 || nActualLen > nRequiredLen) + { + delete[] pbuff; + return L""; + } + CFX_ByteString bsRet = CFX_ByteString(pbuff, nActualLen); CFX_WideString wsRet = CFX_WideString::FromLocal(bsRet); delete[] pbuff; return wsRet;