ShellPkg: Fixes for the ‘type’ command:

- Better handling to skip byte order mark in Unicode files.
- Only display valid ASCII characters.
- Change to use ShellPrintEx() instead of Print().
- Print each character instead of %s to avoid possible overrun when not NULL terminated.
- Check for ExecutionBreak.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Chris Phillips <chrisp@hp.com>
reviewed-by: Jaben Carsey <jaben.carsey@intel.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14788 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Chris Phillips 2013-10-18 20:53:06 +00:00 committed by jcarsey
parent c32ad35161
commit a4883d4cb6
1 changed files with 98 additions and 22 deletions

View File

@ -1,6 +1,7 @@
/** @file /** @file
Main file for Type shell level 3 function. Main file for Type shell level 3 function.
Copyright (c) 2013, Hewlett-Packard Development Company, L.P.
Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved. <BR> Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved. <BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License are licensed and made available under the terms and conditions of the BSD License
@ -31,59 +32,129 @@
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
TypeFileByHandle ( TypeFileByHandle (
IN EFI_HANDLE Handle, IN SHELL_FILE_HANDLE Handle,
BOOLEAN Ascii, IN BOOLEAN Ascii,
BOOLEAN UCS2 IN BOOLEAN UCS2
) )
{ {
UINTN ReadSize; UINTN ReadSize;
VOID *Buffer; VOID *Buffer;
VOID *AllocatedBuffer;
EFI_STATUS Status; EFI_STATUS Status;
UINTN LoopVar; UINTN LoopVar;
UINTN LoopSize;
CHAR16 AsciiChar; CHAR16 AsciiChar;
CHAR16 Ucs2Char;
ReadSize = PcdGet32(PcdShellFileOperationSize); ReadSize = PcdGet32(PcdShellFileOperationSize);
Buffer = AllocateZeroPool(ReadSize); AllocatedBuffer = AllocateZeroPool(ReadSize);
if (Buffer == NULL) { if (AllocatedBuffer == NULL) {
return (EFI_OUT_OF_RESOURCES); return (EFI_OUT_OF_RESOURCES);
} }
Status = ShellSetFilePosition(Handle, 0); Status = ShellSetFilePosition(Handle, 0);
ASSERT_EFI_ERROR(Status); ASSERT_EFI_ERROR(Status);
while (ReadSize == ((UINTN)PcdGet32(PcdShellFileOperationSize))){ while (ReadSize == ((UINTN)PcdGet32(PcdShellFileOperationSize))) {
Buffer = AllocatedBuffer;
ZeroMem(Buffer, ReadSize); ZeroMem(Buffer, ReadSize);
Status = ShellReadFile(Handle, &ReadSize, Buffer); Status = ShellReadFile(Handle, &ReadSize, Buffer);
if (EFI_ERROR(Status)){ if (EFI_ERROR(Status)){
break; break;
} }
if (!(Ascii|UCS2)){ if (!(Ascii|UCS2)) {
if (*(UINT16*)Buffer == gUnicodeFileTag) { if (*(UINT16*)Buffer == gUnicodeFileTag) {
UCS2 = TRUE; UCS2 = TRUE;
Buffer = ((UINT16*)Buffer) + 1;
} else { } else {
Ascii = TRUE; Ascii = TRUE;
} }
} }
if (Ascii) {
LoopSize = ReadSize;
for (LoopVar = 0 ; LoopVar < LoopSize ; LoopVar++) {
// //
// We want to use plain Print function here! (no color support for files) // The valid range of ASCII characters is 0x20-0x7E.
// Display "." when there is an invalid character.
// //
if (Ascii){
for (LoopVar = 0 ; LoopVar < ReadSize ; LoopVar++) {
AsciiChar = CHAR_NULL; AsciiChar = CHAR_NULL;
AsciiChar = ((CHAR8*)Buffer)[LoopVar]; AsciiChar = ((CHAR8*)Buffer)[LoopVar];
if (AsciiChar == CHAR_NULL) { if (AsciiChar == '\r' || AsciiChar == '\n') {
AsciiChar = '.'; //
} // Allow Line Feed (LF) (0xA) & Carriage Return (CR) (0xD)
Print(L"%c", AsciiChar); // characters to be displayed as is.
//
if (AsciiChar == '\n' && ((CHAR8*)Buffer)[LoopVar-1] != '\r') {
//
// In case Line Feed (0xA) is encountered & Carriage Return (0xD)
// was not the previous character, print CR and LF. This is because
// Shell 2.0 requires carriage return with line feed for displaying
// each new line from left.
//
ShellPrintEx (-1, -1, L"\r\n");
continue;
} }
} else { } else {
Print(L"%s", Buffer); //
// For all other characters which are not printable, display '.'
//
if (AsciiChar < 0x20 || AsciiChar >= 0x7F) {
AsciiChar = '.';
} }
} }
Print(L"\r\n", Buffer); ShellPrintEx (-1, -1, L"%c", AsciiChar);
}
} else {
if (*(UINT16*)Buffer == gUnicodeFileTag) {
//
// For unicode files, skip displaying the byte order marker.
//
Buffer = ((UINT16*)Buffer) + 1;
LoopSize = (ReadSize / (sizeof (CHAR16))) - 1;
} else {
LoopSize = ReadSize / (sizeof (CHAR16));
}
for (LoopVar = 0 ; LoopVar < LoopSize ; LoopVar++) {
//
// An invalid range of characters is 0x0-0x1F.
// Display "." when there is an invalid character.
//
Ucs2Char = CHAR_NULL;
Ucs2Char = ((CHAR16*)Buffer)[LoopVar];
if (Ucs2Char == '\r' || Ucs2Char == '\n') {
//
// Allow Line Feed (LF) (0xA) & Carriage Return (CR) (0xD)
// characters to be displayed as is.
//
if (Ucs2Char == '\n' && ((CHAR16*)Buffer)[LoopVar-1] != '\r') {
//
// In case Line Feed (0xA) is encountered & Carriage Return (0xD)
// was not the previous character, print CR and LF. This is because
// Shell 2.0 requires carriage return with line feed for displaying
// each new line from left.
//
ShellPrintEx (-1, -1, L"\r\n");
continue;
}
}
else if (Ucs2Char < 0x20) {
//
// For all other characters which are not printable, display '.'
//
Ucs2Char = L'.';
}
ShellPrintEx (-1, -1, L"%c", Ucs2Char);
}
}
if (ShellGetExecutionBreakFlag()) {
break;
}
}
FreePool (AllocatedBuffer);
ShellPrintEx (-1, -1, L"\r\n");
return (Status); return (Status);
} }
@ -196,6 +267,11 @@ ShellCommandRunType (
; !IsNull(&FileList->Link, &Node->Link) && !ShellGetExecutionBreakFlag() ; !IsNull(&FileList->Link, &Node->Link) && !ShellGetExecutionBreakFlag()
; Node = (EFI_SHELL_FILE_INFO*)GetNextNode(&FileList->Link, &Node->Link) ; Node = (EFI_SHELL_FILE_INFO*)GetNextNode(&FileList->Link, &Node->Link)
){ ){
if (ShellGetExecutionBreakFlag()) {
break;
}
// //
// make sure the file opened ok // make sure the file opened ok
// //
@ -217,7 +293,7 @@ ShellCommandRunType (
// //
// do it // do it
// //
Status = TypeFileByHandle(Node->Handle, AsciiMode, UnicodeMode); Status = TypeFileByHandle (Node->Handle, AsciiMode, UnicodeMode);
if (EFI_ERROR(Status)) { if (EFI_ERROR(Status)) {
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TYP_ERROR), gShellLevel3HiiHandle, Node->FileName, Status); ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TYP_ERROR), gShellLevel3HiiHandle, Node->FileName, Status);
ShellStatus = SHELL_INVALID_PARAMETER; ShellStatus = SHELL_INVALID_PARAMETER;