From f283a3f9ae16eb047d60272186fcb911c79dc266 Mon Sep 17 00:00:00 2001 From: Whindmar Saksit Date: Mon, 13 Nov 2023 16:31:37 +0100 Subject: [PATCH] [SHELL32][SHELLEXT] IEnumIDList::Next must handle pceltFetched and memory errors correctly (#5820) - pceltFetched can be NULL if the caller is not requesting multiple items. - All entries returned in rgelt must be valid, they cannot be NULL. --- dll/shellext/fontext/CEnumFonts.cpp | 21 +++++++++++++++----- dll/shellext/netshell/enumlist.cpp | 8 ++++++++ dll/shellext/zipfldr/CEnumZipContents.cpp | 24 +++++++++++------------ dll/win32/shell32/CEnumIDListBase.cpp | 6 ++++++ 4 files changed, 42 insertions(+), 17 deletions(-) diff --git a/dll/shellext/fontext/CEnumFonts.cpp b/dll/shellext/fontext/CEnumFonts.cpp index 3897a73debd..957e816d322 100644 --- a/dll/shellext/fontext/CEnumFonts.cpp +++ b/dll/shellext/fontext/CEnumFonts.cpp @@ -36,9 +36,10 @@ public: // *** IEnumIDList methods *** STDMETHODIMP Next(ULONG celt, LPITEMIDLIST *rgelt, ULONG *pceltFetched) { - if (!pceltFetched || !rgelt) + if (!rgelt || (!pceltFetched && celt != 1)) return E_POINTER; + HRESULT hr = S_OK; ULONG Fetched = 0; while (celt) @@ -48,15 +49,25 @@ public: if (m_Index < g_FontCache->Size()) { CStringW Name = g_FontCache->Name(m_Index); - rgelt[Fetched] = _ILCreate(Name, m_Index); - + LPITEMIDLIST item = _ILCreate(Name, m_Index); + if (!item) + { + hr = Fetched ? S_FALSE : E_OUTOFMEMORY; + break; + } + rgelt[Fetched] = item; m_Index++; Fetched++; } + else + { + hr = S_FALSE; + } } - *pceltFetched = Fetched; - return Fetched ? S_OK : S_FALSE; + if (pceltFetched) + *pceltFetched = Fetched; + return hr; } STDMETHODIMP Skip(ULONG celt) { diff --git a/dll/shellext/netshell/enumlist.cpp b/dll/shellext/netshell/enumlist.cpp index a95eab776d8..9369663f708 100644 --- a/dll/shellext/netshell/enumlist.cpp +++ b/dll/shellext/netshell/enumlist.cpp @@ -277,9 +277,17 @@ CEnumIDList::Next( for (i = 0; i < celt; i++) { if (!m_pCurrent) + { + hr = S_FALSE; break; + } temp = ILClone(m_pCurrent->pidl); + if (!temp) + { + hr = i ? S_FALSE : E_OUTOFMEMORY; + break; + } rgelt[i] = temp; m_pCurrent = m_pCurrent->pNext; } diff --git a/dll/shellext/zipfldr/CEnumZipContents.cpp b/dll/shellext/zipfldr/CEnumZipContents.cpp index 372e21ba772..a3f5bcbf79c 100644 --- a/dll/shellext/zipfldr/CEnumZipContents.cpp +++ b/dll/shellext/zipfldr/CEnumZipContents.cpp @@ -34,25 +34,25 @@ public: // *** IEnumIDList methods *** STDMETHODIMP Next(ULONG celt, LPITEMIDLIST *rgelt, ULONG *pceltFetched) { - if (!pceltFetched || !rgelt) + if (!rgelt || (!pceltFetched && celt != 1)) return E_POINTER; - *pceltFetched = 0; - - if (celt != 1) - return E_FAIL; - + LPITEMIDLIST item; CStringW name; bool dir; unz_file_info64 info; - if (mEnumerator.next_unique(m_Prefix, name, dir, info)) + for (ULONG i = 0; i < celt; ++i) { - *pceltFetched = 1; - *rgelt = _ILCreate(dir ? ZIP_PIDL_DIRECTORY : ZIP_PIDL_FILE, name, info); - return S_OK; + if (pceltFetched) + *pceltFetched = i; + if (!mEnumerator.next_unique(m_Prefix, name, dir, info)) + return S_FALSE; + item = _ILCreate(dir ? ZIP_PIDL_DIRECTORY : ZIP_PIDL_FILE, name, info); + if (!item) + return i ? S_FALSE : E_OUTOFMEMORY; + rgelt[i] = item; } - - return S_FALSE; + return S_OK; } STDMETHODIMP Skip(ULONG celt) { diff --git a/dll/win32/shell32/CEnumIDListBase.cpp b/dll/win32/shell32/CEnumIDListBase.cpp index 59633418c3d..47adf6e2ea8 100644 --- a/dll/win32/shell32/CEnumIDListBase.cpp +++ b/dll/win32/shell32/CEnumIDListBase.cpp @@ -172,9 +172,15 @@ HRESULT WINAPI CEnumIDListBase::Next( for(i = 0; i < celt; i++) { if(!mpCurrent) + { hr = S_FALSE; break; + } temp = ILClone(mpCurrent->pidl); + if (!temp) + { hr = i ? S_FALSE : E_OUTOFMEMORY; + break; + } rgelt[i] = temp; mpCurrent = mpCurrent->pNext; }