diff --git a/Contrib/Modern UI 2/Interface.nsh b/Contrib/Modern UI 2/Interface.nsh index 74e1a382..ee858bd0 100644 --- a/Contrib/Modern UI 2/Interface.nsh +++ b/Contrib/Modern UI 2/Interface.nsh @@ -214,12 +214,14 @@ Var mui.Button.Back ${if} $(^RTL) == 1 File "/oname=$PLUGINSDIR\modern-header.bmp" "${MUI_HEADERIMAGE_${UN}BITMAP_RTL}" + !pragma verifyloadimage "${MUI_HEADERIMAGE_${UN}BITMAP_RTL}" !insertmacro MUI_HEADERIMAGE_INITHELPER_LOADIMAGE "${UN}" "_RTL" ${IMGRESID} "$PLUGINSDIR\modern-header.bmp" ${else} !endif File "/oname=$PLUGINSDIR\modern-header.bmp" "${MUI_HEADERIMAGE_${UN}BITMAP}" + !pragma verifyloadimage "${MUI_HEADERIMAGE_${UN}BITMAP}" !insertmacro MUI_HEADERIMAGE_INITHELPER_LOADIMAGE "${UN}" "" ${IMGRESID} "$PLUGINSDIR\modern-header.bmp" !ifdef MUI_HEADERIMAGE_${UN}BITMAP_RTL diff --git a/Contrib/Modern UI 2/Pages/Finish.nsh b/Contrib/Modern UI 2/Pages/Finish.nsh index be986a48..493c1e06 100644 --- a/Contrib/Modern UI 2/Pages/Finish.nsh +++ b/Contrib/Modern UI 2/Pages/Finish.nsh @@ -91,6 +91,7 @@ Finish page (implemented using nsDialogs) InitPluginsDir File "/oname=$PLUGINSDIR\modern-wizard.bmp" "${MUI_${MUI_PAGE_UNINSTALLER_PREFIX}WELCOMEFINISHPAGE_BITMAP}" + !pragma verifyloadimage "${MUI_${MUI_PAGE_UNINSTALLER_PREFIX}WELCOMEFINISHPAGE_BITMAP}" !ifdef MUI_${MUI_PAGE_UNINSTALLER_PREFIX}PAGE_FUNCTION_GUIINIT Call "${MUI_${MUI_PAGE_UNINSTALLER_PREFIX}PAGE_FUNCTION_GUIINIT}" diff --git a/Contrib/Modern UI 2/Pages/Welcome.nsh b/Contrib/Modern UI 2/Pages/Welcome.nsh index 9d0c43f3..0839b949 100644 --- a/Contrib/Modern UI 2/Pages/Welcome.nsh +++ b/Contrib/Modern UI 2/Pages/Welcome.nsh @@ -43,6 +43,7 @@ Welcome page (implemented using nsDialogs) InitPluginsDir File "/oname=$PLUGINSDIR\modern-wizard.bmp" "${MUI_${MUI_PAGE_UNINSTALLER_PREFIX}WELCOMEFINISHPAGE_BITMAP}" + !pragma verifyloadimage "${MUI_${MUI_PAGE_UNINSTALLER_PREFIX}WELCOMEFINISHPAGE_BITMAP}" !ifdef MUI_${MUI_PAGE_UNINSTALLER_PREFIX}PAGE_FUNCTION_GUIINIT Call "${MUI_${MUI_PAGE_UNINSTALLER_PREFIX}PAGE_FUNCTION_GUIINIT}" diff --git a/Contrib/Modern UI/System.nsh b/Contrib/Modern UI/System.nsh index 3ec40add..819e7b00 100644 --- a/Contrib/Modern UI/System.nsh +++ b/Contrib/Modern UI/System.nsh @@ -452,6 +452,7 @@ Var MUI_TEMP2 !insertmacro INSTALLOPTIONS_EXTRACT_AS "${MUI_${UNINSTALLER}WELCOMEFINISHPAGE_INI}" "ioSpecial.ini" File "/oname=$PLUGINSDIR\modern-wizard.bmp" "${MUI_${UNINSTALLER}WELCOMEFINISHPAGE_BITMAP}" + !pragma verifyloadimage "${MUI_${UNINSTALLER}WELCOMEFINISHPAGE_BITMAP}" !insertmacro INSTALLOPTIONS_WRITE "ioSpecial.ini" "Field 1" "Text" "$PLUGINSDIR\modern-wizard.bmp" @@ -474,6 +475,7 @@ Var MUI_TEMP2 StrCmp $(^RTL) 0 mui.headerimageinit_nortl File "/oname=$PLUGINSDIR\modern-header.bmp" "${MUI_HEADERIMAGE_${UNINSTALLER}BITMAP_RTL}" + !pragma verifyloadimage "${MUI_HEADERIMAGE_${UNINSTALLER}BITMAP_RTL}" !ifndef MUI_HEADERIMAGE_${UNINSTALLER}BITMAP_RTL_NOSTRETCH SetBrandingImage /IMGID=1046 /RESIZETOFIT "$PLUGINSDIR\modern-header.bmp" @@ -488,6 +490,7 @@ Var MUI_TEMP2 !endif File "/oname=$PLUGINSDIR\modern-header.bmp" "${MUI_HEADERIMAGE_${UNINSTALLER}BITMAP}" + !pragma verifyloadimage "${MUI_HEADERIMAGE_${UNINSTALLER}BITMAP}" !ifndef MUI_HEADERIMAGE_${UNINSTALLER}BITMAP_NOSTRETCH SetBrandingImage /IMGID=1046 /RESIZETOFIT "$PLUGINSDIR\modern-header.bmp" diff --git a/Source/BinInterop.cpp b/Source/BinInterop.cpp index b38edcec..75fccac1 100644 --- a/Source/BinInterop.cpp +++ b/Source/BinInterop.cpp @@ -485,3 +485,29 @@ DWORD IsBMPFile(const void*pData, size_t DataSize, GENERICIMAGEINFO*pInfo) } return 0; } + +bool LoadImageCanLoadFile(const void*pData, size_t DataSize) +{ + bool valid = IsICOCURFile(pData, DataSize) != 0; + if (!valid) + { + GENERICIMAGEINFO info; + UINT headersize = GetBMPFileHeaderSize(pData, DataSize, &info); + valid = headersize == 12 || headersize == 40; // Only supports BITMAPCOREHEADER and BITMAPINFOHEADER (Bug #681 & FR #559) + valid = valid && !info.IsTopDownBitmap(); // TopDown bitmaps are only valid if they are loaded with LR_CREATEDIBSECTION, and if loaded from a resource, and if running on Vista+? and therefore we deny! + } + return valid; +} + +bool LoadImageCanLoadFile(const TCHAR *filepath) +{ + bool valid = false; + unsigned char header[14+124]; + FILE *f = my_fopen(filepath, "rb"); + if (f) + { + valid = LoadImageCanLoadFile(header, fread(header, 1, sizeof(header), f)); + fclose(f); + } + return valid; +} diff --git a/Source/BinInterop.h b/Source/BinInterop.h index b0f9f3a9..29a7d6b0 100644 --- a/Source/BinInterop.h +++ b/Source/BinInterop.h @@ -37,6 +37,7 @@ typedef struct GENERICIMAGEINFO { DWORD GetDIBHeaderInfo(const void*pData, size_t DataSize, GENERICIMAGEINFO&Info); DWORD IsBMPFile(const void*pData, size_t DataSize, GENERICIMAGEINFO*pInfo = 0); +#define GetBMPFileHeaderSize IsBMPFile inline WORD IsICOCURFile(const void*pData) { @@ -51,4 +52,8 @@ inline WORD IsICOCURFile(const void*pData, size_t DataSize) return DataSize > 6 ? IsICOCURFile(pData) : 0; } +bool LoadImageCanLoadFile(const void*pData, size_t DataSize); +bool LoadImageCanLoadFile(const TCHAR *filepath); +#define LoadImageCanLoadFileFromResource LoadImageCanLoadFile + #endif //~ NSIS_BININTEROP_H diff --git a/Source/build.cpp b/Source/build.cpp index 800eac6c..c2e5f7cd 100644 --- a/Source/build.cpp +++ b/Source/build.cpp @@ -31,6 +31,7 @@ #include "manifest.h" #include "icon.h" #include "utf.h" // For NStream +#include "BinInterop.h" #include "exehead/api.h" #include "exehead/resource.h" @@ -3403,12 +3404,18 @@ int CEXEBuild::parse_pragma(LineParser &line) return rvErr; } + if (line.gettoken_enum(1, _T("verifyloadimage\0")) == 0) + { + bool valid = LoadImageCanLoadFile(line.gettoken_str(2)); + return valid ? rvSucc : (warning_fl(DW_BADFORMAT_EXTERNAL_FILE, _T("Unsupported format %") NPRIs, line.gettoken_str(2)), rvWarn); + } + // 2.47 shipped with a corrupted CHM file (bug #1129). This minimal verification command exists because the !searchparse hack we added does not work with codepage 936! if (line.gettoken_enum(1, _T("verifychm\0")) == 0) { struct { UINT32 Sig, Ver, cbH; } chm; NIStream f; - bool valid = f.OpenFileForReading(line.gettoken_str(2)); + bool valid = f.OpenFileForReading(line.gettoken_str(2), NStreamEncoding::BINARY); valid = valid && 12 == f.ReadOctets(&chm, 12); valid = valid && FIX_ENDIAN_INT32(chm.Sig) == 0x46535449 && (FIX_ENDIAN_INT32(chm.Ver)|1) == 3; // 'ITSF' v2..3 return valid ? rvSucc : (ERROR_MSG(_T("Error: Invalid format\n")), PS_ERROR); diff --git a/Source/build.h b/Source/build.h index f2e94342..f73cddb4 100644 --- a/Source/build.h +++ b/Source/build.h @@ -71,6 +71,7 @@ typedef enum { //DE_PP_VERBOSE_BAD_LEVEL = 4000?, //DW_STALE_TEMP = 5020?, TODO: There is currently no way to disable this DW_PACKHDR_RETNONZERO = 5021, + DW_BADFORMAT_EXTERNAL_FILE = 5040, DW_UNSUPP_STORE_FILE_ATT = 5050, //DW_CMDLINE_UNSUPP = 5200?, //DW_CMDLINE_UNSUPP_WIN = 5201?, diff --git a/Source/utf.cpp b/Source/utf.cpp index ad388bbb..4f5d3fe0 100644 --- a/Source/utf.cpp +++ b/Source/utf.cpp @@ -363,6 +363,7 @@ void NStreamEncoding::GetCPDisplayName(WORD CP, TCHAR*Buf) case UTF32LE: p = _T("UTF32LE"); break; case UTF32BE: p = _T("UTF32BE"); break; case UTF8: p = _T("UTF8"); break; + case BINARY: p = _T("BIN"); break; default: _stprintf(mybuf,_T("CP%u"),CP); if (CP >= NStreamEncoding::CPCOUNT) p = _T("?"); @@ -376,13 +377,17 @@ bool NBaseStream::Attach(FILE*hFile, WORD enc, bool Seek /*= true*/) m_hFile = hFile; if (!m_hFile) return false; if (!NStream::SetBinaryMode(m_hFile) && m_hFile != stdin) return false; - fpos_t pos; - if (Seek && !fgetpos(m_hFile, &pos)) rewind(m_hFile); else Seek = false; - WORD cp = DetectUTFBOM(m_hFile); - if (Seek) + WORD cp = 0; + if (enc != NStreamEncoding::BINARY) { - fsetpos(m_hFile, &pos); - if (cp) DetectUTFBOM(m_hFile); // parseScript() etc does not like the BOM, make sure we skip past it + fpos_t pos; + if (Seek && !fgetpos(m_hFile, &pos)) rewind(m_hFile); else Seek = false; + cp = DetectUTFBOM(m_hFile); + if (Seek) + { + fsetpos(m_hFile, &pos); + if (cp) DetectUTFBOM(m_hFile); // parseScript() etc does not like the BOM, make sure we skip past it + } } if (!cp) cp = enc; m_Enc.SafeSetCodepage(cp); diff --git a/Source/utf.h b/Source/utf.h index 047e4ac6..34503ef4 100644 --- a/Source/utf.h +++ b/Source/utf.h @@ -185,7 +185,8 @@ public: UTF8 = CP_UTF8, UNKNOWN = (0xffff-0), AUTO = (0xffff-1), - CPCOUNT = (0xffff-2) // Must be less than our other magic numbers + BINARY = (0xffff-2), + CPCOUNT = (0xffff-3) // Must be less than our other magic numbers }; NStreamEncoding() { Reset(); } diff --git a/Source/util.cpp b/Source/util.cpp index 36af0b6e..96a873c8 100644 --- a/Source/util.cpp +++ b/Source/util.cpp @@ -146,7 +146,7 @@ int update_bitmap(CResourceEditor* re, WORD id, const TCHAR* filename, int width signed char hdr[14+124], retval = -2; size_t size = fread(hdr, 1, sizeof(hdr), f); GENERICIMAGEINFO info; - if (IsBMPFile(hdr, size, &info) && 0 == fseek(f, 0, SEEK_SET) && !info.IsTopDownBitmap()) + if (IsBMPFile(hdr, size, &info) && 0 == fseek(f, 0, SEEK_SET) && LoadImageCanLoadFileFromResource(hdr, size)) { if ((width && width != (int) info.Width) || (height && height != (int) info.Height)) retval = -3;