Speculative fix for uninitialized value in CFX_ByteString().
authorTom Sepez <tsepez@chromium.org>
Wed, 30 Jul 2014 20:03:52 +0000 (13:03 -0700)
committerTom Sepez <tsepez@chromium.org>
Wed, 30 Jul 2014 20:03:52 +0000 (13:03 -0700)
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

fpdfsdk/include/fsdk_mgr.h

index d7e4e3d..95d1a79 100644 (file)
@@ -173,18 +173,24 @@ public:
 
        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"";
+
+                       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"";
-                       nLen = m_pInfo->m_pJsPlatform->Field_browse(m_pInfo->m_pJsPlatform, pbuff, nLen);
-                       CFX_ByteString bsRet = CFX_ByteString(pbuff, nLen);
+                       }
+                       CFX_ByteString bsRet = CFX_ByteString(pbuff, nActualLen);
                        CFX_WideString wsRet = CFX_WideString::FromLocal(bsRet);
                        delete[] pbuff;
                        return wsRet;
@@ -193,19 +199,25 @@ public:
        }
 
        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"";
+
+                       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"";
-                       nLen = m_pInfo->m_pJsPlatform->Doc_getFilePath(m_pInfo->m_pJsPlatform, pbuff, nLen);
-                       CFX_ByteString bsRet = CFX_ByteString(pbuff, nLen);
+                       }
+                       CFX_ByteString bsRet = CFX_ByteString(pbuff, nActualLen);
                        CFX_WideString wsRet = CFX_WideString::FromLocal(bsRet);
                        delete[] pbuff;
                        return wsRet;