Fix an out-of-boundary issue for wide string

BUG=381521
R=palmer@chromium.org

Review URL: https://codereview.chromium.org/383563002
diff --git a/core/include/fxcrt/fx_string.h b/core/include/fxcrt/fx_string.h
index fe56e18..26b04b7 100644
--- a/core/include/fxcrt/fx_string.h
+++ b/core/include/fxcrt/fx_string.h
@@ -634,9 +634,11 @@
 
     static CFX_WideString	FromLocal(const char* str, FX_STRSIZE len = -1);
 
-    static CFX_WideString	FromUTF8(const char* str, FX_STRSIZE len = -1);
+    static CFX_WideString	FromUTF8(const char* str, FX_STRSIZE len);
 
-    static CFX_WideString	FromUTF16LE(const unsigned short* str, FX_STRSIZE len = -1);
+    static CFX_WideString	FromUTF16LE(const unsigned short* str, FX_STRSIZE len);
+
+    static FX_STRSIZE       WStringLength(const unsigned short* str);
 
     operator FX_LPCWSTR() const
     {
diff --git a/core/src/fxcrt/fx_basic_util.cpp b/core/src/fxcrt/fx_basic_util.cpp
index 1d947d3..dc5eea7 100644
--- a/core/src/fxcrt/fx_basic_util.cpp
+++ b/core/src/fxcrt/fx_basic_util.cpp
@@ -273,7 +273,7 @@
             rURI += bsURI[i];
         }
     }
-    return CFX_WideString::FromUTF8(rURI);
+    return CFX_WideString::FromUTF8(rURI, rURI.GetLength());
 }
 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
 class CFindFileData : public CFX_Object
diff --git a/core/src/fxcrt/fx_basic_wstring.cpp b/core/src/fxcrt/fx_basic_wstring.cpp
index 192579f..794630b 100644
--- a/core/src/fxcrt/fx_basic_wstring.cpp
+++ b/core/src/fxcrt/fx_basic_wstring.cpp
@@ -398,15 +398,10 @@
 }
 CFX_WideString CFX_WideString::FromUTF8(const char* str, FX_STRSIZE len)
 {
-    if (!str) {
+    if (!str || 0 == len) {
         return CFX_WideString();
     }
-    if (len < 0) {
-        len = 0;
-        while (str[len]) {
-            len ++;
-        }
-    }
+
     CFX_UTF8Decoder decoder;
     for (FX_STRSIZE i = 0; i < len; i ++) {
         decoder.Input(str[i]);
@@ -415,15 +410,10 @@
 }
 CFX_WideString CFX_WideString::FromUTF16LE(const unsigned short* wstr, FX_STRSIZE wlen)
 {
-    if (!wstr || !wlen) {
+    if (!wstr || 0 == wlen) {
         return CFX_WideString();
     }
-    if (wlen < 0) {
-        wlen = 0;
-        while (wstr[wlen]) {
-            wlen ++;
-        }
-    }
+
     CFX_WideString result;
     FX_WCHAR* buf = result.GetBuffer(wlen);
     for (int i = 0; i < wlen; i ++) {
@@ -432,6 +422,16 @@
     result.ReleaseBuffer(wlen);
     return result;
 }
+FX_STRSIZE CFX_WideString::WStringLength(const unsigned short* str)
+{
+    FX_STRSIZE len = 0;
+    if (str)
+        while (str[len]) len++;
+    return len;
+}
+
+
+
 void CFX_WideString::AllocCopy(CFX_WideString& dest, FX_STRSIZE nCopyLen, FX_STRSIZE nCopyIndex) const
 {
     // |FX_STRSIZE| is currently typedef'd as in |int|. TODO(palmer): It
diff --git a/core/src/fxge/win32/fx_win32_device.cpp b/core/src/fxge/win32/fx_win32_device.cpp
index 2e2ea9a..9c03a30 100644
--- a/core/src/fxge/win32/fx_win32_device.cpp
+++ b/core/src/fxge/win32/fx_win32_device.cpp
@@ -328,7 +328,9 @@
     for (int i = 0; i < iCount; ++i) {
         if (face == VariantNames[i].m_pFaceName) {
             CFX_WideString wsFace = CFX_WideString::FromLocal(facebuf);
-            CFX_WideString wsName = CFX_WideString::FromUTF16LE((const unsigned short*)VariantNames[i].m_pVariantName);
+            const unsigned short* pName = (const unsigned short*)VariantNames[i].m_pVariantName;
+            FX_STRSIZE len = CFX_WideString::WStringLength(pName);
+            CFX_WideString wsName = CFX_WideString::FromUTF16LE(pName, len);
             if (wsFace == wsName) {
                 return hFont;
             }
diff --git a/fpdfsdk/src/fpdfdoc.cpp b/fpdfsdk/src/fpdfdoc.cpp
index edd61f9..e974ffb 100644
--- a/fpdfsdk/src/fpdfdoc.cpp
+++ b/fpdfsdk/src/fpdfdoc.cpp
@@ -36,7 +36,8 @@
 	CPDF_Document* pDoc = (CPDF_Document*)document;
 	CPDF_BookmarkTree tree(pDoc);
 
-	CFX_WideString wstr = CFX_WideString::FromUTF16LE(title);
+	FX_STRSIZE len = CFX_WideString::WStringLength(title);
+	CFX_WideString wstr = CFX_WideString::FromUTF16LE(title, len);
 	return FindBookmark(tree, NULL, wstr);
 }
 
diff --git a/fpdfsdk/src/fpdftext.cpp b/fpdfsdk/src/fpdftext.cpp
index 1aa0542..869ec48 100644
--- a/fpdfsdk/src/fpdftext.cpp
+++ b/fpdfsdk/src/fpdftext.cpp
@@ -11,7 +11,7 @@
 #include <tchar.h>
 #endif
 
-        // jabdelmalek: commented out to build on Linux.  Not used.
+	// jabdelmalek: commented out to build on Linux.  Not used.
 	// extern HANDLE g_hModule;
 
 DLLEXPORT FPDF_TEXTPAGE STDCALL FPDFText_LoadPage(FPDF_PAGE page)
@@ -162,7 +162,8 @@
 	try
 	{
 		textpageFind=IPDF_TextPageFind::CreatePageFind((IPDF_TextPage*)text_page);
-		textpageFind->FindFirst(CFX_WideString::FromUTF16LE(findwhat),flags,start_index);
+		FX_STRSIZE len = CFX_WideString::WStringLength(findwhat);
+		textpageFind->FindFirst(CFX_WideString::FromUTF16LE(findwhat, len),flags,start_index);
 	}
 	catch (...)
 	{
diff --git a/fpdfsdk/src/javascript/Document.cpp b/fpdfsdk/src/javascript/Document.cpp
index 2318d9b..0c4d4f4 100644
--- a/fpdfsdk/src/javascript/Document.cpp
+++ b/fpdfsdk/src/javascript/Document.cpp
@@ -196,7 +196,7 @@
 
 	ASSERT(m_pDocument != NULL);
 
-   	CPDFSDK_InterForm *pInterForm = m_pDocument->GetInterForm();
+	CPDFSDK_InterForm *pInterForm = m_pDocument->GetInterForm();
 	ASSERT(pInterForm != NULL);
 
 	CPDF_InterForm *pPDFForm = pInterForm->GetInterForm();
@@ -284,7 +284,7 @@
 		}
 	}
 
- 	return TRUE;
+	return TRUE;
 }
 
 FX_BOOL Document::ParserParams(JSObject* pObj,CJS_AnnotObj& annotobj)
@@ -294,7 +294,7 @@
 
 FX_BOOL Document::addAnnot(OBJ_METHOD_PARAMS)
 {
- 	return TRUE;
+	return TRUE;
 }
 
 FX_BOOL Document::addField(OBJ_METHOD_PARAMS)
@@ -336,7 +336,7 @@
 	if (!bWhole)
 		arrayFileds.Attach(params[2]);
 	//FX_BOOL bFlags = params.size() > 3 ? (FX_BOOL)params[3] : FALSE;
-    CFX_WideString swFilePath = params.size() > 4 ? (FX_LPCWSTR)params[4].operator CFX_WideString() : (FX_LPCWSTR)L"";
+	CFX_WideString swFilePath = params.size() > 4 ? (FX_LPCWSTR)params[4].operator CFX_WideString() : (FX_LPCWSTR)L"";
 
 	if (swFilePath.IsEmpty())
 	{
@@ -349,10 +349,10 @@
 	{
 		swFilePath = app::PDFPathToSysPath(swFilePath);
 	}
-    
+	
 	m_pDocument->SetFocusAnnot(NULL);
    
-    CPDFSDK_InterForm* pInterForm= (CPDFSDK_InterForm*)m_pDocument->GetInterForm();
+	CPDFSDK_InterForm* pInterForm= (CPDFSDK_InterForm*)m_pDocument->GetInterForm();
 	ASSERT(pInterForm != NULL);
 
 	CPDF_InterForm* pPDFForm = pInterForm->GetInterForm();
@@ -386,7 +386,7 @@
 
 	for (int i=0,sz=aFields.GetSize(); i<sz; i++)
 	{
-	    CPDF_FormField* pField = (CPDF_FormField*)aFields[i];
+		CPDF_FormField* pField = (CPDF_FormField*)aFields[i];
 		
 		if (!bAllFields)
 			if (pField->GetValue() == L"")
@@ -396,10 +396,10 @@
 			if (pField->GetFieldFlags() & 0x2000)
 				continue;
 
-        fields.Add((void*)pField);
+		fields.Add((void*)pField);
 	}    
 
-    return pInterForm->ExportFieldsToFDFFile(swFilePath, fields, TRUE);
+	return pInterForm->ExportFieldsToFDFFile(swFilePath, fields, TRUE);
 }
 
 //exports form fields an XFDF file to the local hard drive
@@ -430,7 +430,7 @@
 
 	CFX_WideString wideName = params[0].operator CFX_WideString();
 
-    CPDFSDK_InterForm* pInterForm = m_pDocument->GetInterForm();
+	CPDFSDK_InterForm* pInterForm = m_pDocument->GetInterForm();
 	ASSERT(pInterForm != NULL);
 
 	CPDF_InterForm* pPDFForm = pInterForm->GetInterForm();
@@ -505,7 +505,7 @@
 	
 	if (params.size() > 0)
 		swPath = params[0];
-    
+	
 	if (swPath.IsEmpty())
 	{
 		CPDFDoc_Environment* pEnv = m_pDocument->GetEnv();
@@ -526,7 +526,7 @@
 	if (!pInterForm->ImportFormFromFDFFile(swPath, TRUE))
 		return FALSE;
 
- 	m_pDocument->SetChangeMark();
+	m_pDocument->SetChangeMark();
 // 	CPDFDoc_Environment* pEnv = m_pDocument->GetEnv();
 // 	ASSERT(pEnv != NULL);
 // 	IUndo* pUndo = IUndo::GetUndo(pEnv);
@@ -605,9 +605,9 @@
 	ASSERT(pRuntime != NULL);
 
 	pRuntime->BeginBlock();
-    pEnv->JS_docmailForm(textBuf.GetBuffer(), textBuf.GetLength(), bUI, (FX_LPCWSTR)cTo, (FX_LPCWSTR)cSubject, (FX_LPCWSTR)cCc, (FX_LPCWSTR)cBcc, (FX_LPCWSTR)cMsg);
+	pEnv->JS_docmailForm(textBuf.GetBuffer(), textBuf.GetLength(), bUI, (FX_LPCWSTR)cTo, (FX_LPCWSTR)cSubject, (FX_LPCWSTR)cCc, (FX_LPCWSTR)cBcc, (FX_LPCWSTR)cMsg);
 	pRuntime->EndBlock();
- 	return TRUE;
+	return TRUE;
 }
 
 FX_BOOL Document::print(OBJ_METHOD_PARAMS)
@@ -660,11 +660,11 @@
 		if(nlength >= 2)
 			 nStart = (int)params[1];
 		if(nlength >= 3)
-		    nEnd = (int)params[2];
+			nEnd = (int)params[2];
 		if(nlength >= 4)
 			bSilent = params[3];
 		if(nlength >= 5)
-		    bShrinkToFit = params[4];
+			bShrinkToFit = params[4];
 		if(nlength >= 6)
 			bPrintAsImage = params[5];
 		if(nlength >= 7)
@@ -673,13 +673,13 @@
 			bAnnotations = params[7];
 	}
 
- 	ASSERT(m_pDocument != NULL);
+	ASSERT(m_pDocument != NULL);
  
- 	if (CPDFDoc_Environment* pEnv = m_pDocument->GetEnv())
- 	{
+	if (CPDFDoc_Environment* pEnv = m_pDocument->GetEnv())
+	{
 		pEnv->JS_docprint(bUI, nStart, nEnd, bSilent, bShrinkToFit, bPrintAsImage, bReverse, bAnnotations);
- 		return TRUE;
- 	}
+		return TRUE;
+	}
 	return FALSE;
 }
 
@@ -786,15 +786,15 @@
 
 		if (aFields.GetSize() > 0)
 		{
- 			pPDFForm->ResetForm(aFields, TRUE, TRUE);
- 			m_pDocument->SetChangeMark();
+			pPDFForm->ResetForm(aFields, TRUE, TRUE);
+			m_pDocument->SetChangeMark();
 
 		}
 	}
 	else
 	{
- 		pPDFForm->ResetForm(TRUE);
- 		m_pDocument->SetChangeMark();
+		pPDFForm->ResetForm(TRUE);
+		m_pDocument->SetChangeMark();
 
 	}
 
@@ -1070,7 +1070,7 @@
 		{
 			CFX_ByteString bsKey;
 			CPDF_Object* pValueObj = pDictionary->GetNextElement(pos, bsKey);
-			CFX_WideString wsKey  = CFX_WideString::FromUTF8(bsKey);
+			CFX_WideString wsKey  = CFX_WideString::FromUTF8(bsKey, bsKey.GetLength());
 			if((pValueObj->GetType()==PDFOBJ_STRING) || (pValueObj->GetType()==PDFOBJ_NAME) )
 					JS_PutObjectString(isolate,pObj, wsKey, pValueObj->GetUnicodeText());
 			if(pValueObj->GetType()==PDFOBJ_NUMBER)
@@ -1356,12 +1356,12 @@
 
 FX_BOOL Document::mouseX(OBJ_PROP_PARAMS)
 {
- 	return TRUE;	
+	return TRUE;	
 }
 
 FX_BOOL Document::mouseY(OBJ_PROP_PARAMS)
 {
- 	return TRUE;
+	return TRUE;
 }
 
 FX_BOOL Document::baseURL(OBJ_PROP_PARAMS)
@@ -1493,7 +1493,7 @@
 
 FX_BOOL Document::addLink(OBJ_METHOD_PARAMS)
 {
- 	return TRUE;
+	return TRUE;
 }
 
 FX_BOOL Document::closeDoc(OBJ_METHOD_PARAMS)
@@ -1509,13 +1509,13 @@
 
 FX_BOOL Document::getPageBox(OBJ_METHOD_PARAMS)
 {
- 	return TRUE;
+	return TRUE;
 }
 
 
 FX_BOOL Document::getAnnot(OBJ_METHOD_PARAMS)
 {
- 	return TRUE;
+	return TRUE;
 }
 
 FX_BOOL Document::getAnnots(OBJ_METHOD_PARAMS)
diff --git a/fpdfsdk/src/javascript/app.cpp b/fpdfsdk/src/javascript/app.cpp
index a3e61c0..3b92a99 100644
--- a/fpdfsdk/src/javascript/app.cpp
+++ b/fpdfsdk/src/javascript/app.cpp
@@ -886,15 +886,15 @@
 	{
 		JSObject pObj = (JSObject )params[0];
 
- 		v8::Handle<v8::Value> pValue = JS_GetObjectElement(isolate,pObj,L"bSave");
- 			bSave = (bool)CJS_Value(isolate,pValue,GET_VALUE_TYPE(pValue));
- 		
+		v8::Handle<v8::Value> pValue = JS_GetObjectElement(isolate,pObj,L"bSave");
+			bSave = (bool)CJS_Value(isolate,pValue,GET_VALUE_TYPE(pValue));
+		
 		pValue = JS_GetObjectElement(isolate, pObj,L"cFilenameInit");
 		{
 			CJS_Value t = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue));
- 			cFilenameInit = t.operator CFX_ByteString();
+			cFilenameInit = t.operator CFX_ByteString();
 		}
- 		
+		
 		pValue = JS_GetObjectElement(isolate,pObj,L"cFSInit");
 		{
 			CJS_Value t = CJS_Value(isolate, pValue, GET_VALUE_TYPE(pValue));
@@ -1097,25 +1097,23 @@
 	}
 
 	CJS_Context* pContext = (CJS_Context *)cc;
- 	ASSERT(pContext != NULL);
+	ASSERT(pContext != NULL);
 
 	CPDFDoc_Environment* pApp = pContext->GetReaderApp();
- 	ASSERT(pApp != NULL);
+	ASSERT(pApp != NULL);
 	int nLength = 2048;
 	char* pBuff = new char[nLength];
 	nLength = pApp->JS_appResponse(swQuestion, swTitle, swDefault, swLabel, bPassWord, pBuff, nLength);
 	if(nLength<=0)
 	{
+		delete[] pBuff;
 		vRet.SetNull();
 		return FALSE;
 	}
 	else
 	{
-		nLength = nLength>2046?2046:nLength;
-    pBuff[nLength] = 0;
-    pBuff[nLength+1] = 0;
-		swResponse = CFX_WideString::FromUTF16LE((unsigned short*)pBuff, nLength);
-		vRet = swResponse;
+		nLength = nLength > sizeof(pBuff) ? sizeof(pBuff) : nLength;
+        vRet = swResponse = CFX_WideString::FromUTF16LE((unsigned short*)pBuff, nLength / 2);
 	}
 	delete[] pBuff;
 
diff --git a/fpdfsdk/src/jsapi/fxjs_v8.cpp b/fpdfsdk/src/jsapi/fxjs_v8.cpp
index f2336ab..5eb9873 100644
--- a/fpdfsdk/src/jsapi/fxjs_v8.cpp
+++ b/fpdfsdk/src/jsapi/fxjs_v8.cpp
@@ -734,7 +734,7 @@
 {
 	if(pValue.IsEmpty()) return L"";
 	v8::String::Utf8Value s(pValue->ToString());
-	return CFX_WideString::FromUTF8(*s);
+	return CFX_WideString::FromUTF8(*s, s.length());
 }
 
 v8::Handle<v8::Array> JS_ToArray(v8::Handle<v8::Value> pValue)