[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.
This commit is contained in:
Whindmar Saksit 2023-11-13 16:31:37 +01:00 committed by GitHub
parent b4b1c5b9aa
commit f283a3f9ae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 42 additions and 17 deletions

View file

@ -36,9 +36,10 @@ public:
// *** IEnumIDList methods *** // *** IEnumIDList methods ***
STDMETHODIMP Next(ULONG celt, LPITEMIDLIST *rgelt, ULONG *pceltFetched) STDMETHODIMP Next(ULONG celt, LPITEMIDLIST *rgelt, ULONG *pceltFetched)
{ {
if (!pceltFetched || !rgelt) if (!rgelt || (!pceltFetched && celt != 1))
return E_POINTER; return E_POINTER;
HRESULT hr = S_OK;
ULONG Fetched = 0; ULONG Fetched = 0;
while (celt) while (celt)
@ -48,15 +49,25 @@ public:
if (m_Index < g_FontCache->Size()) if (m_Index < g_FontCache->Size())
{ {
CStringW Name = g_FontCache->Name(m_Index); 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++; m_Index++;
Fetched++; Fetched++;
} }
else
{
hr = S_FALSE;
}
} }
if (pceltFetched)
*pceltFetched = Fetched; *pceltFetched = Fetched;
return Fetched ? S_OK : S_FALSE; return hr;
} }
STDMETHODIMP Skip(ULONG celt) STDMETHODIMP Skip(ULONG celt)
{ {

View file

@ -277,9 +277,17 @@ CEnumIDList::Next(
for (i = 0; i < celt; i++) for (i = 0; i < celt; i++)
{ {
if (!m_pCurrent) if (!m_pCurrent)
{
hr = S_FALSE;
break; break;
}
temp = ILClone(m_pCurrent->pidl); temp = ILClone(m_pCurrent->pidl);
if (!temp)
{
hr = i ? S_FALSE : E_OUTOFMEMORY;
break;
}
rgelt[i] = temp; rgelt[i] = temp;
m_pCurrent = m_pCurrent->pNext; m_pCurrent = m_pCurrent->pNext;
} }

View file

@ -34,25 +34,25 @@ public:
// *** IEnumIDList methods *** // *** IEnumIDList methods ***
STDMETHODIMP Next(ULONG celt, LPITEMIDLIST *rgelt, ULONG *pceltFetched) STDMETHODIMP Next(ULONG celt, LPITEMIDLIST *rgelt, ULONG *pceltFetched)
{ {
if (!pceltFetched || !rgelt) if (!rgelt || (!pceltFetched && celt != 1))
return E_POINTER; return E_POINTER;
*pceltFetched = 0; LPITEMIDLIST item;
if (celt != 1)
return E_FAIL;
CStringW name; CStringW name;
bool dir; bool dir;
unz_file_info64 info; unz_file_info64 info;
if (mEnumerator.next_unique(m_Prefix, name, dir, info)) for (ULONG i = 0; i < celt; ++i)
{ {
*pceltFetched = 1; if (pceltFetched)
*rgelt = _ILCreate(dir ? ZIP_PIDL_DIRECTORY : ZIP_PIDL_FILE, name, info); *pceltFetched = i;
return S_OK; if (!mEnumerator.next_unique(m_Prefix, name, dir, info))
}
return S_FALSE; 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_OK;
} }
STDMETHODIMP Skip(ULONG celt) STDMETHODIMP Skip(ULONG celt)
{ {

View file

@ -172,9 +172,15 @@ HRESULT WINAPI CEnumIDListBase::Next(
for(i = 0; i < celt; i++) for(i = 0; i < celt; i++)
{ if(!mpCurrent) { if(!mpCurrent)
{ hr = S_FALSE;
break; break;
}
temp = ILClone(mpCurrent->pidl); temp = ILClone(mpCurrent->pidl);
if (!temp)
{ hr = i ? S_FALSE : E_OUTOFMEMORY;
break;
}
rgelt[i] = temp; rgelt[i] = temp;
mpCurrent = mpCurrent->pNext; mpCurrent = mpCurrent->pNext;
} }