From bb9b88b70f8c9caf8f5ee3490ce478315ed9e4f9 Mon Sep 17 00:00:00 2001 From: anders_k Date: Tue, 8 Oct 2013 18:59:28 +0000 Subject: [PATCH] Fix DupWCFromBytes/CharEncConv optimized return bug when converting UTF16LE license file to wchar_t(UTF16LE) git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@6414 212acab6-be3b-0410-9dea-997c60f758d6 --- Source/script.cpp | 12 ++++++------ Source/utf.cpp | 7 ++++--- Source/utf.h | 5 +++-- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/Source/script.cpp b/Source/script.cpp index 68a565ba..8ff1efef 100644 --- a/Source/script.cpp +++ b/Source/script.cpp @@ -991,12 +991,12 @@ int CEXEBuild::LoadLicenseFile(const TCHAR *file, TCHAR** pdata, const TCHAR *cm fseek(f,cbBOMOffset,SEEK_SET); UINT cbTotalData=sizeof(TCHAR)+cbFileData+sizeof(TCHAR); // SF_*+file+\0 TCHAR*data=(TCHAR*)malloc(cbTotalData); + *pdata=data; // memory will be released by caller if (!data) { ERROR_MSG(_T("Internal compiler error #12345: %s malloc(%d) failed.\n"),cmdname,cbTotalData); return PS_ERROR; } - *pdata=data; // memory will be released by caller *((TCHAR*)((char*)data+cbTotalData-sizeof(TCHAR)))=_T('\0'); TCHAR*ldata=data+1; @@ -1014,16 +1014,16 @@ l_errwcconv: ERROR_MSG(_T("%s: wchar_t conversion failed!\n"),cmdname); return PS_ERROR; } - // Create a fake character in the "header" part of the buffer + // Create a fake character in the "header" part of the buffer (For DupWCFromBytes) char*lichdr=((char*)ldata) - cbcu; *((char*)lichdr)='X'; if (cbcu > 1) *((WORD*)lichdr)='X'; //BUGBUG: No room: if (cbcu > 2) *((UINT32*)lichdr)='X'; - wchar_t*wcdata=DupWCFromBytes(lichdr,cbcu+cbFileData,srccp); + const bool canOptRet = (char*)data == lichdr; + wchar_t*wcdata=DupWCFromBytes(lichdr,cbcu+cbFileData,srccp|(canOptRet?DWCFBF_ALLOWOPTIMIZEDRETURN:0)); if (!wcdata) goto l_errwcconv; - free(data); - *pdata=data=wcdata; - ldata=data+1; + if (wcdata != data) free(data); + *pdata=data=wcdata, ldata=data+1; const bool isRTF=!memcmp(ldata,_T("{\\rtf"),5*sizeof(TCHAR)); if (isRTF) diff --git a/Source/utf.cpp b/Source/utf.cpp index 6c80f679..1a300927 100644 --- a/Source/utf.cpp +++ b/Source/utf.cpp @@ -92,14 +92,15 @@ UINT WCFromCodePoint(wchar_t*Dest,UINT cchDest,UINT32 CodPt) #endif } -wchar_t* DupWCFromBytes(void*Buffer,UINT cbBuffer,WORD SrcCP) +wchar_t* DupWCFromBytes(void*Buffer,UINT cbBuffer,UINT32 SrcCP) { /*\ Converts a buffer encoded with SrcCP to a \0 terminated wchar_t malloc'ed buffer. Returns 0 on failure. \*/ CharEncConv cec; - if (!cec.Initialize(-1, SrcCP)) return 0; + cec.SetAllowOptimizedReturn(!!(SrcCP&DWCFBF_ALLOWOPTIMIZEDRETURN)); + if (!cec.Initialize(-1, SrcCP&=~DWCFBF_ALLOWOPTIMIZEDRETURN)) return 0; wchar_t *pWC = (wchar_t*) cec.Convert(Buffer, cbBuffer); return pWC ? (wchar_t*) cec.Detach() : 0; } @@ -183,7 +184,7 @@ void* CharEncConv::Convert(const void*Src, size_t cbSrc, size_t*cbOut) if (cbSrc && ((WORD*)Src)[--cbSrc]) ++cbSrc; *cbOut = cbSrc * sizeof(wchar_t); } - return (void*) Src; + return (void*) (m_Result = (char*) Src); } #endif char *p = (char*) realloc(m_Result, cbSrc + sizeof(UINT32)); diff --git a/Source/utf.h b/Source/utf.h index 57ce0174..cfb4e6bd 100644 --- a/Source/utf.h +++ b/Source/utf.h @@ -91,7 +91,8 @@ UINT StrLenUTF16(const void*str); bool StrSetUTF16LE(tstring&dest, const void*src); UINT WCFromCodePoint(wchar_t*Dest,UINT cchDest,UINT32 CodPt); -wchar_t* DupWCFromBytes(void*Buffer,UINT cbBuffer,WORD SrcCP); +#define DWCFBF_ALLOWOPTIMIZEDRETURN 0x80000000 // DupWCFromBytes can return input Buffer +wchar_t* DupWCFromBytes(void*Buffer,UINT cbBuffer,UINT32 SrcCP); UINT DetectUTFBOM(void*Buffer,UINT cb); UINT DetectUTFBOM(FILE*strm); WORD GetEncodingFromString(const TCHAR*s, bool&BOM); @@ -110,7 +111,7 @@ protected: static bool IsWE(WORD Encoding) { return (WORD)-1 == Encoding; } static bool IsWE(UINT32 Encoding) { return (UINT32)-1 == Encoding; } public: - CharEncConv() : m_Result(0) {} + CharEncConv() : m_Result(0) { SetAllowOptimizedReturn(false); } ~CharEncConv() { Close(); } void Close() {