mirror of https://github.com/acidanthera/audk.git
ShellPkg/Shell: clean up bogus member types in SPLIT_LIST
The "SPLIT_LIST.SplitStdOut" and "SPLIT_LIST.SplitStdIn" members currently have type (SHELL_FILE_HANDLE *). This is wrong; SHELL_FILE_HANDLE is already a pointer, there's no need to store a pointer to a pointer. The error is obvious if we check where and how these members are used: - In the RunSplitCommand() function, these members are used (populated) extensively; this function has to be updated in sync. ConvertEfiFileProtocolToShellHandle() already returns the temporary memory file created with CreateFileInterfaceMem() as SHELL_FILE_HANDLE, not as (SHELL_FILE_HANDLE *). - In particular, the ConvertShellHandleToEfiFileProtocol() calls need to be dropped as well in RunSplitCommand(), since EFI_SHELL_PROTOCOL.SetFilePosition() and EFI_SHELL_PROTOCOL.CloseFile() take SHELL_FILE_HANDLE parameters, not (EFI_FILE_PROTOCOL *). Given that ConvertShellHandleToEfiFileProtocol() only performs a type-cast (it does not adjust any pointer values), *and* SHELL_FILE_HANDLE -- taken by EFI_SHELL_PROTOCOL member functions -- is actually a typedef to (VOID *) -- see more on this later --, this conversion error hasn't been caught by compilers. - In the ProcessNewSplitCommandLine() function, RunSplitCommand() is called either initially (passing in NULL / NULL; no update needed), or recursively (passing in Split->SplitStdIn / Split->SplitStdOut; again no update is necessary beyond the RunSplitCommand() modification above). - In the UpdateStdInStdOutStdErr() and RestoreStdInStdOutStdErr() functions, said structure members are compared and assigned to "EFI_SHELL_PARAMETERS_PROTOCOL.StdIn" and "EFI_SHELL_PARAMETERS_PROTOCOL.StdOut", both of which have type SHELL_FILE_HANDLE, *not* (SHELL_FILE_HANDLE *). The compiler hasn't caught this error because of the fatally flawed type definition of SHELL_FILE_HANDLE, namely typedef VOID *SHELL_FILE_HANDLE; Pointer-to-void silently converts to and from most other pointer types; among them, pointer-to-pointer-to-void. That is also why no update is necessary for UpdateStdInStdOutStdErr() and RestoreStdInStdOutStdErr() in this fix. ( Generally speaking, using (VOID *) typedefs for opaque handles is a tragic mistake in all of the UEFI-related specifications; this practice defeats any type checking that compilers might help programmers with. The right way to define an opaque handle is as follows: // // Introduce the incomplete structure type, and the derived pointer // type, in both the specification and the public edk2 headers. Note // that the derived pointer type itself is a complete type, and it can // be used freely by client code. // typedef struct SHELL_FILE *SHELL_FILE_HANDLE; // // Complete the structure type in the edk2 internal C source files. // struct SHELL_FILE { // // list fields // }; This way the structure size and members remain hidden from client code, but the C compiler can nonetheless catch any invalid conversions between incompatible XXX_HANDLE types. ) Cc: Jaben Carsey <jaben.carsey@intel.com> Cc: Marvin Häuser <Marvin.Haeuser@outlook.com> Cc: Qiu Shumin <shumin.qiu@intel.com> Cc: Ruiyu Ni <ruiyu.ni@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Jaben Carsey <jaben.carsey@intel.com>
This commit is contained in:
parent
6bbd4a8f5f
commit
1bd0bf153e
|
@ -1714,8 +1714,8 @@ ShellConvertVariables (
|
|||
EFI_STATUS
|
||||
RunSplitCommand(
|
||||
IN CONST CHAR16 *CmdLine,
|
||||
IN SHELL_FILE_HANDLE *StdIn,
|
||||
IN SHELL_FILE_HANDLE *StdOut
|
||||
IN SHELL_FILE_HANDLE StdIn,
|
||||
IN SHELL_FILE_HANDLE StdOut
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
@ -1724,7 +1724,7 @@ RunSplitCommand(
|
|||
UINTN Size1;
|
||||
UINTN Size2;
|
||||
SPLIT_LIST *Split;
|
||||
SHELL_FILE_HANDLE *TempFileHandle;
|
||||
SHELL_FILE_HANDLE TempFileHandle;
|
||||
BOOLEAN Unicode;
|
||||
|
||||
ASSERT(StdOut == NULL);
|
||||
|
@ -1790,7 +1790,7 @@ RunSplitCommand(
|
|||
Split->SplitStdOut = Split->SplitStdIn;
|
||||
}
|
||||
Split->SplitStdIn = TempFileHandle;
|
||||
ShellInfoObject.NewEfiShellProtocol->SetFilePosition(ConvertShellHandleToEfiFileProtocol(Split->SplitStdIn), 0);
|
||||
ShellInfoObject.NewEfiShellProtocol->SetFilePosition (Split->SplitStdIn, 0);
|
||||
|
||||
if (!EFI_ERROR(Status)) {
|
||||
Status = RunCommand(NextCommandLine);
|
||||
|
@ -1806,10 +1806,10 @@ RunSplitCommand(
|
|||
// Note that the original StdIn is now the StdOut...
|
||||
//
|
||||
if (Split->SplitStdOut != NULL) {
|
||||
ShellInfoObject.NewEfiShellProtocol->CloseFile(ConvertShellHandleToEfiFileProtocol(Split->SplitStdOut));
|
||||
ShellInfoObject.NewEfiShellProtocol->CloseFile (Split->SplitStdOut);
|
||||
}
|
||||
if (Split->SplitStdIn != NULL) {
|
||||
ShellInfoObject.NewEfiShellProtocol->CloseFile(ConvertShellHandleToEfiFileProtocol(Split->SplitStdIn));
|
||||
ShellInfoObject.NewEfiShellProtocol->CloseFile (Split->SplitStdIn);
|
||||
FreePool (Split->SplitStdIn);
|
||||
}
|
||||
|
||||
|
|
|
@ -63,8 +63,8 @@ extern CONST CHAR16 mNoNestingFalse[];
|
|||
|
||||
typedef struct {
|
||||
LIST_ENTRY Link; ///< Standard linked list handler.
|
||||
SHELL_FILE_HANDLE *SplitStdOut; ///< ConsoleOut for use in the split.
|
||||
SHELL_FILE_HANDLE *SplitStdIn; ///< ConsoleIn for use in the split.
|
||||
SHELL_FILE_HANDLE SplitStdOut; ///< ConsoleOut for use in the split.
|
||||
SHELL_FILE_HANDLE SplitStdIn; ///< ConsoleIn for use in the split.
|
||||
} SPLIT_LIST;
|
||||
|
||||
typedef struct {
|
||||
|
|
Loading…
Reference in New Issue