Skip to content

Commit c4d29cb

Browse files
bobm21mergify[bot]
authored andcommitted
ShellPkg/UefiHandleParsingLib: support handle list growth
Refactor GetHandleListByProtocol() to support additions to the handle list during its execution. Replace LocateHandle() with LocateHandleBuffer() to avoid the possibility that the buffer allocated for LocateHandle() is too small if additional handles are added during GetHandleListByProtocol() execution. Note that the previous implementation did not detect the handle list growth and would cause memory corruption when writing the terminating NULL handle to the allocated buffer. Signed-off-by: Bob Morgan <[email protected]>
1 parent b989871 commit c4d29cb

1 file changed

Lines changed: 31 additions & 33 deletions

File tree

ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.c

Lines changed: 31 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3761,7 +3761,7 @@ ParseHandleDatabaseForChildDevices (
37613761
@param[in] ProtocolGuid The guid of the protocol to get handles for. If NULL
37623762
then the function will return all handles.
37633763
3764-
@retval NULL A memory allocation failed.
3764+
@retval NULL Could not get handles or memory allocation failed.
37653765
@return A NULL terminated list of handles.
37663766
**/
37673767
EFI_HANDLE *
@@ -3771,45 +3771,43 @@ GetHandleListByProtocol (
37713771
)
37723772
{
37733773
EFI_HANDLE *HandleList;
3774-
UINTN Size;
3774+
EFI_HANDLE *OriginalHandleList;
3775+
UINTN OriginalHandleCount;
37753776
EFI_STATUS Status;
37763777

3777-
Size = 0;
3778-
HandleList = NULL;
3779-
3780-
//
3781-
// We cannot use LocateHandleBuffer since we need that NULL item on the ends of the list!
3782-
//
3783-
if (ProtocolGuid == NULL) {
3784-
Status = gBS->LocateHandle (AllHandles, NULL, NULL, &Size, HandleList);
3785-
if (Status == EFI_BUFFER_TOO_SMALL) {
3786-
HandleList = AllocateZeroPool (Size + sizeof (EFI_HANDLE));
3787-
if (HandleList == NULL) {
3788-
return (NULL);
3789-
}
3790-
3791-
Status = gBS->LocateHandle (AllHandles, NULL, NULL, &Size, HandleList);
3792-
HandleList[Size/sizeof (EFI_HANDLE)] = NULL;
3778+
OriginalHandleList = NULL;
3779+
Status = gBS->LocateHandleBuffer (
3780+
(ProtocolGuid == NULL) ? AllHandles : ByProtocol,
3781+
(EFI_GUID *)ProtocolGuid,
3782+
NULL,
3783+
&OriginalHandleCount,
3784+
&OriginalHandleList
3785+
);
3786+
if (EFI_ERROR (Status)) {
3787+
if (Status != EFI_NOT_FOUND) {
3788+
DEBUG ((
3789+
DEBUG_ERROR,
3790+
"%a: LocateHandleBuffer %a failed: %r\n",
3791+
__func__,
3792+
(ProtocolGuid == NULL) ? "AllHandles" : "ByProtocol",
3793+
Status
3794+
));
37933795
}
3794-
} else {
3795-
Status = gBS->LocateHandle (ByProtocol, (EFI_GUID *)ProtocolGuid, NULL, &Size, HandleList);
3796-
if (Status == EFI_BUFFER_TOO_SMALL) {
3797-
HandleList = AllocateZeroPool (Size + sizeof (EFI_HANDLE));
3798-
if (HandleList == NULL) {
3799-
return (NULL);
3800-
}
38013796

3802-
Status = gBS->LocateHandle (ByProtocol, (EFI_GUID *)ProtocolGuid, NULL, &Size, HandleList);
3803-
HandleList[Size/sizeof (EFI_HANDLE)] = NULL;
3804-
}
3797+
return NULL;
38053798
}
38063799

3807-
if (EFI_ERROR (Status)) {
3808-
if (HandleList != NULL) {
3809-
FreePool (HandleList);
3800+
// create new list with one more slot for the NULL terminator
3801+
HandleList = ReallocatePool (
3802+
OriginalHandleCount * sizeof (EFI_HANDLE),
3803+
(OriginalHandleCount + 1) * sizeof (EFI_HANDLE),
3804+
OriginalHandleList
3805+
);
3806+
if (HandleList == NULL) {
3807+
DEBUG ((DEBUG_ERROR, "%a: reallocate failed\n", __func__));
3808+
if (OriginalHandleList != NULL) {
3809+
FreePool (OriginalHandleList);
38103810
}
3811-
3812-
return (NULL);
38133811
}
38143812

38153813
return (HandleList);

0 commit comments

Comments
 (0)