diff options
author | Laszlo Ersek <lersek@redhat.com> | 2017-04-25 14:03:32 +0200 |
---|---|---|
committer | Laszlo Ersek <lersek@redhat.com> | 2017-04-26 12:10:30 +0200 |
commit | 1bd0bf153ebf4993421afd5084c52a6e57e17fdc (patch) | |
tree | 2665f57d1e4b4c3ba5e7897dcff8e3da4300149c /BaseTools/Source/Python/build/build.py | |
parent | 6bbd4a8f5f2a538e5017045ab75674ec106f7b54 (diff) | |
download | edk2-1bd0bf153ebf4993421afd5084c52a6e57e17fdc.tar.gz edk2-1bd0bf153ebf4993421afd5084c52a6e57e17fdc.tar.bz2 edk2-1bd0bf153ebf4993421afd5084c52a6e57e17fdc.zip |
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>
Diffstat (limited to 'BaseTools/Source/Python/build/build.py')
0 files changed, 0 insertions, 0 deletions