Revision: 17088
http://sourceforge.net/p/edk2/code/17088
Author: vanjeff
Date: 2015-04-01 07:19:31 +0000 (Wed, 01 Apr 2015)
Log Message:
-----------
ShellPkg: Refactor quote and escape search to use new function.
ShellPkg: Add quotes around NSH index argument replacement.
(Sync part of patches r16682 and r16699 from main trunk.)
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jaben Carsey <[email protected]>
Signed-off-by: Joe Peterson <[email protected]>
Reviewed-by: Shumin Qiu <[email protected]>
Reviewed-by: Joe Peterson <[email protected]>
Reviewed-by: Tapan Shah <[email protected]>
Revision Links:
--------------
http://sourceforge.net/p/edk2/code/16682
http://sourceforge.net/p/edk2/code/16699
Modified Paths:
--------------
branches/UDK2014.SP1/ShellPkg/Application/Shell/Shell.c
branches/UDK2014.SP1/ShellPkg/Application/Shell/Shell.h
branches/UDK2014.SP1/ShellPkg/Application/Shell/ShellParametersProtocol.c
branches/UDK2014.SP1/ShellPkg/Application/Shell/ShellParametersProtocol.h
Modified: branches/UDK2014.SP1/ShellPkg/Application/Shell/Shell.c
===================================================================
--- branches/UDK2014.SP1/ShellPkg/Application/Shell/Shell.c 2015-04-01
04:56:00 UTC (rev 17087)
+++ branches/UDK2014.SP1/ShellPkg/Application/Shell/Shell.c 2015-04-01
07:19:31 UTC (rev 17088)
@@ -1,7 +1,7 @@
/** @file
This is THE shell (application)
- Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
(C) Copyright 2013-2014, Hewlett-Packard Development Company, L.P.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD
License
@@ -101,30 +101,92 @@
}
/**
- Find a command line contains a split operation
+ Parse for the next instance of one string within another string. Can
optionally make sure that
+ the string was not escaped (^ character) per the shell specification.
- @param[in] CmdLine The command line to parse.
-
- @retval A pointer to the | character in CmdLine or NULL if
not present.
+ @param[in] SourceString The string to search within
+ @param[in] FindString The string to look for
+ @param[in] CheckForEscapeCharacter TRUE to skip escaped instances of
FinfString, otherwise will return even escaped instances
**/
-CONST CHAR16*
+CHAR16*
EFIAPI
-FindSplit(
- IN CONST CHAR16 *CmdLine
+FindNextInstance(
+ IN CONST CHAR16 *SourceString,
+ IN CONST CHAR16 *FindString,
+ IN CONST BOOLEAN CheckForEscapeCharacter
)
{
- CONST CHAR16 *TempSpot;
- TempSpot = NULL;
- if (StrStr(CmdLine, L"|") != NULL) {
- for (TempSpot = CmdLine ; TempSpot != NULL && *TempSpot != CHAR_NULL ;
TempSpot++) {
- if (*TempSpot == L'^' && *(TempSpot+1) == L'|') {
- TempSpot++;
- } else if (*TempSpot == L'|') {
- break;
+ CHAR16 *Temp;
+ if (SourceString == NULL) {
+ return (NULL);
+ }
+ Temp = StrStr(SourceString, FindString);
+
+ //
+ // If nothing found, or we dont care about escape characters
+ //
+ if (Temp == NULL || !CheckForEscapeCharacter) {
+ return (Temp);
+ }
+
+ //
+ // If we found an escaped character, try again on the remainder of the string
+ //
+ if ((Temp > (SourceString)) && *(Temp-1) == L'^') {
+ return FindNextInstance(Temp+1, FindString, CheckForEscapeCharacter);
+ }
+
+ //
+ // we found the right character
+ //
+ return (Temp);
+}
+
+/**
+ Check whether the string between a pair of % is a valid envifronment
variable name.
+
+ @param[in] BeginPercent pointer to the first percent.
+ @param[in] EndPercent pointer to the last percent.
+
+ @retval TRUE is a valid environment variable name.
+ @retval FALSE is NOT a valid environment variable
name.
+**/
+BOOLEAN
+IsValidEnvironmentVariableName(
+ IN CONST CHAR16 *BeginPercent,
+ IN CONST CHAR16 *EndPercent
+ )
+{
+ CONST CHAR16 *Walker;
+
+ Walker = NULL;
+
+ ASSERT (BeginPercent != NULL);
+ ASSERT (EndPercent != NULL);
+ ASSERT (BeginPercent < EndPercent);
+
+ if ((BeginPercent + 1) == EndPercent) {
+ return FALSE;
+ }
+
+ for (Walker = BeginPercent + 1; Walker < EndPercent; Walker++) {
+ if (
+ (*Walker >= L'0' && *Walker <= L'9') ||
+ (*Walker >= L'A' && *Walker <= L'Z') ||
+ (*Walker >= L'a' && *Walker <= L'z') ||
+ (*Walker == L'_')
+ ) {
+ if (Walker == BeginPercent + 1 && (*Walker >= L'0' && *Walker <= L'9')) {
+ return FALSE;
+ } else {
+ continue;
}
+ } else {
+ return FALSE;
}
}
- return (TempSpot);
+
+ return TRUE;
}
/**
@@ -142,7 +204,39 @@
)
{
CONST CHAR16 *TempSpot;
- TempSpot = FindSplit(CmdLine);
+ CONST CHAR16 *FirstQuote;
+ CONST CHAR16 *SecondQuote;
+
+ FirstQuote = FindNextInstance (CmdLine, L"\"", TRUE);
+ SecondQuote = NULL;
+ TempSpot = FindFirstCharacter(CmdLine, L"|", L'^');
+
+ if (FirstQuote == NULL ||
+ TempSpot == NULL ||
+ TempSpot == CHAR_NULL ||
+ FirstQuote > TempSpot
+ ) {
+ return (BOOLEAN) ((TempSpot != NULL) && (*TempSpot != CHAR_NULL));
+ }
+
+ while ((TempSpot != NULL) && (*TempSpot != CHAR_NULL)) {
+ if (FirstQuote == NULL || FirstQuote > TempSpot) {
+ break;
+ }
+ SecondQuote = FindNextInstance (FirstQuote + 1, L"\"", TRUE);
+ if (SecondQuote == NULL) {
+ break;
+ }
+ if (SecondQuote < TempSpot) {
+ FirstQuote = FindNextInstance (SecondQuote + 1, L"\"", TRUE);
+ continue;
+ } else {
+ FirstQuote = FindNextInstance (SecondQuote + 1, L"\"", TRUE);
+ TempSpot = FindFirstCharacter(TempSpot + 1, L"|", L'^');
+ continue;
+ }
+ }
+
return (BOOLEAN) ((TempSpot != NULL) && (*TempSpot != CHAR_NULL));
}
@@ -1233,48 +1327,6 @@
}
/**
- Parse for the next instance of one string within another string. Can
optionally make sure that
- the string was not escaped (^ character) per the shell specification.
-
- @param[in] SourceString The string to search within
- @param[in] FindString The string to look for
- @param[in] CheckForEscapeCharacter TRUE to skip escaped instances of
FinfString, otherwise will return even escaped instances
-**/
-CHAR16*
-EFIAPI
-FindNextInstance(
- IN CONST CHAR16 *SourceString,
- IN CONST CHAR16 *FindString,
- IN CONST BOOLEAN CheckForEscapeCharacter
- )
-{
- CHAR16 *Temp;
- if (SourceString == NULL) {
- return (NULL);
- }
- Temp = StrStr(SourceString, FindString);
-
- //
- // If nothing found, or we dont care about escape characters
- //
- if (Temp == NULL || !CheckForEscapeCharacter) {
- return (Temp);
- }
-
- //
- // If we found an escaped character, try again on the remainder of the string
- //
- if ((Temp > (SourceString)) && *(Temp-1) == L'^') {
- return FindNextInstance(Temp+1, FindString, CheckForEscapeCharacter);
- }
-
- //
- // we found the right character
- //
- return (Temp);
-}
-
-/**
This function will eliminate unreplaced (and therefore non-found)
environment variables.
@param[in,out] CmdLine The command line to update.
@@ -1302,8 +1354,8 @@
break;
}
- if (FirstQuote < FirstPercent) {
- SecondQuote = FirstQuote!= NULL?FindNextInstance(FirstQuote+1, L"\"",
TRUE):NULL;
+ if (FirstQuote!= NULL && FirstQuote < FirstPercent) {
+ SecondQuote = FindNextInstance(FirstQuote+1, L"\"", TRUE);
//
// Quote is first found
//
@@ -1321,19 +1373,21 @@
}
continue;
}
- ASSERT(FirstPercent < FirstQuote);
- if (SecondPercent < FirstQuote) {
- FirstPercent[0] = L'\"';
- SecondPercent[0] = L'\"';
-
- //
- // We need to remove from FirstPercent to SecondPercent
- //
- CopyMem(FirstPercent + 1, SecondPercent, StrSize(SecondPercent));
- CurrentLocator = FirstPercent + 2;
+
+ if (FirstQuote == NULL || SecondPercent < FirstQuote) {
+ if (IsValidEnvironmentVariableName(FirstPercent, SecondPercent)) {
+ //
+ // We need to remove from FirstPercent to SecondPercent
+ //
+ CopyMem(FirstPercent, SecondPercent + 1, StrSize(SecondPercent + 1));
+ //
+ // dont need to update the locator. both % characters are gone.
+ //
+ } else {
+ CurrentLocator = SecondPercent + 1;
+ }
continue;
}
- ASSERT(FirstQuote < SecondPercent);
CurrentLocator = FirstQuote;
}
return (EFI_SUCCESS);
@@ -1448,14 +1502,14 @@
ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize,
AliasListNode->Alias, AliasListNode->CommandString, TRUE, FALSE);
StrnCpy(NewCommandLine1, NewCommandLine2, NewSize/sizeof(CHAR16)-1);
}
-
- //
- // Remove non-existant environment variables in scripts only
- //
- StripUnreplacedEnvironmentVariables(NewCommandLine1);
}
//
+ // Remove non-existant environment variables
+ //
+ StripUnreplacedEnvironmentVariables(NewCommandLine1);
+
+ //
// Now cleanup any straggler intentionally ignored "%" characters
//
ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, L"^%",
L"%", TRUE, FALSE);
@@ -1789,12 +1843,12 @@
return (EFI_OUT_OF_RESOURCES);
}
TempWalker = (CHAR16*)Temp;
- GetNextParameter(&TempWalker, &FirstParameter, StrSize(CmdLine));
-
- if (GetOperationType(FirstParameter) == Unknown_Invalid) {
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND),
ShellInfoObject.HiiHandle, FirstParameter);
- SetLastError(SHELL_NOT_FOUND);
- Status = EFI_NOT_FOUND;
+ if (!EFI_ERROR(GetNextParameter(&TempWalker, &FirstParameter,
StrSize(CmdLine)))) {
+ if (GetOperationType(FirstParameter) == Unknown_Invalid) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND),
ShellInfoObject.HiiHandle, FirstParameter);
+ SetLastError(SHELL_NOT_FOUND);
+ Status = EFI_NOT_FOUND;
+ }
}
}
@@ -1838,7 +1892,7 @@
//
// recurse to verify the next item
//
- TempSpot = FindSplit(CmdLine)+1;
+ TempSpot = FindFirstCharacter(CmdLine, L"|", L'^') + 1;
return (VerifySplit(TempSpot));
}
@@ -1949,24 +2003,25 @@
Walker = *CmdLine;
while(Walker != NULL && *Walker != CHAR_NULL) {
LastWalker = Walker;
- GetNextParameter(&Walker, &CurrentParameter, StrSize(*CmdLine));
- if (StrStr(CurrentParameter, L"-?") == CurrentParameter) {
- LastWalker[0] = L' ';
- LastWalker[1] = L' ';
- NewCommandLine = AllocateZeroPool(StrSize(L"help ") + StrSize(*CmdLine));
- if (NewCommandLine == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
+ if (!EFI_ERROR(GetNextParameter(&Walker, &CurrentParameter,
StrSize(*CmdLine)))) {
+ if (StrStr(CurrentParameter, L"-?") == CurrentParameter) {
+ LastWalker[0] = L' ';
+ LastWalker[1] = L' ';
+ NewCommandLine = AllocateZeroPool(StrSize(L"help ") +
StrSize(*CmdLine));
+ if (NewCommandLine == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ break;
+ }
+
+ //
+ // We know the space is sufficient since we just calculated it.
+ //
+ StrnCpy(NewCommandLine, L"help ", 5);
+ StrnCat(NewCommandLine, *CmdLine, StrLen(*CmdLine));
+ SHELL_FREE_NON_NULL(*CmdLine);
+ *CmdLine = NewCommandLine;
break;
}
-
- //
- // We know the space is sufficient since we just calculated it.
- //
- StrnCpy(NewCommandLine, L"help ", 5);
- StrnCat(NewCommandLine, *CmdLine, StrLen(*CmdLine));
- SHELL_FREE_NON_NULL(*CmdLine);
- *CmdLine = NewCommandLine;
- break;
}
}
@@ -2418,27 +2473,30 @@
return (EFI_OUT_OF_RESOURCES);
}
TempWalker = CleanOriginal;
- GetNextParameter(&TempWalker, &FirstParameter, StrSize(CleanOriginal));
-
- //
- // Depending on the first parameter we change the behavior
- //
- switch (Type = GetOperationType(FirstParameter)) {
- case File_Sys_Change:
- Status = ChangeMappedDrive (FirstParameter);
- break;
- case Internal_Command:
- case Script_File_Name:
- case Efi_Application:
- Status = SetupAndRunCommandOrFile(Type, CleanOriginal, FirstParameter,
ShellInfoObject.NewShellParametersProtocol);
- break;
- default:
- //
- // Whatever was typed, it was invalid.
- //
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND),
ShellInfoObject.HiiHandle, FirstParameter);
- SetLastError(SHELL_NOT_FOUND);
- break;
+ if (!EFI_ERROR(GetNextParameter(&TempWalker, &FirstParameter,
StrSize(CleanOriginal)))) {
+ //
+ // Depending on the first parameter we change the behavior
+ //
+ switch (Type = GetOperationType(FirstParameter)) {
+ case File_Sys_Change:
+ Status = ChangeMappedDrive (FirstParameter);
+ break;
+ case Internal_Command:
+ case Script_File_Name:
+ case Efi_Application:
+ Status = SetupAndRunCommandOrFile(Type, CleanOriginal, FirstParameter,
ShellInfoObject.NewShellParametersProtocol);
+ break;
+ default:
+ //
+ // Whatever was typed, it was invalid.
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND),
ShellInfoObject.HiiHandle, FirstParameter);
+ SetLastError(SHELL_NOT_FOUND);
+ break;
+ }
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND),
ShellInfoObject.HiiHandle, FirstParameter);
+ SetLastError(SHELL_NOT_FOUND);
}
SHELL_FREE_NON_NULL(CleanOriginal);
@@ -2631,34 +2689,34 @@
if (NewScriptFile->Argv != NULL) {
switch (NewScriptFile->Argc) {
default:
- Status = ShellCopySearchAndReplace(CommandLine2, CommandLine,
PcdGet16 (PcdShellPrintBufferSize), L"%9", NewScriptFile->Argv[9], FALSE,
FALSE);
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine,
PcdGet16 (PcdShellPrintBufferSize), L"%9", NewScriptFile->Argv[9], FALSE, TRUE);
ASSERT_EFI_ERROR(Status);
case 9:
- Status = ShellCopySearchAndReplace(CommandLine, CommandLine2,
PcdGet16 (PcdShellPrintBufferSize), L"%8", NewScriptFile->Argv[8], FALSE,
FALSE);
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2,
PcdGet16 (PcdShellPrintBufferSize), L"%8", NewScriptFile->Argv[8], FALSE, TRUE);
ASSERT_EFI_ERROR(Status);
case 8:
- Status = ShellCopySearchAndReplace(CommandLine2, CommandLine,
PcdGet16 (PcdShellPrintBufferSize), L"%7", NewScriptFile->Argv[7], FALSE,
FALSE);
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine,
PcdGet16 (PcdShellPrintBufferSize), L"%7", NewScriptFile->Argv[7], FALSE, TRUE);
ASSERT_EFI_ERROR(Status);
case 7:
- Status = ShellCopySearchAndReplace(CommandLine, CommandLine2,
PcdGet16 (PcdShellPrintBufferSize), L"%6", NewScriptFile->Argv[6], FALSE,
FALSE);
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2,
PcdGet16 (PcdShellPrintBufferSize), L"%6", NewScriptFile->Argv[6], FALSE, TRUE);
ASSERT_EFI_ERROR(Status);
case 6:
- Status = ShellCopySearchAndReplace(CommandLine2, CommandLine,
PcdGet16 (PcdShellPrintBufferSize), L"%5", NewScriptFile->Argv[5], FALSE,
FALSE);
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine,
PcdGet16 (PcdShellPrintBufferSize), L"%5", NewScriptFile->Argv[5], FALSE, TRUE);
ASSERT_EFI_ERROR(Status);
case 5:
- Status = ShellCopySearchAndReplace(CommandLine, CommandLine2,
PcdGet16 (PcdShellPrintBufferSize), L"%4", NewScriptFile->Argv[4], FALSE,
FALSE);
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2,
PcdGet16 (PcdShellPrintBufferSize), L"%4", NewScriptFile->Argv[4], FALSE, TRUE);
ASSERT_EFI_ERROR(Status);
case 4:
- Status = ShellCopySearchAndReplace(CommandLine2, CommandLine,
PcdGet16 (PcdShellPrintBufferSize), L"%3", NewScriptFile->Argv[3], FALSE,
FALSE);
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine,
PcdGet16 (PcdShellPrintBufferSize), L"%3", NewScriptFile->Argv[3], FALSE, TRUE);
ASSERT_EFI_ERROR(Status);
case 3:
- Status = ShellCopySearchAndReplace(CommandLine, CommandLine2,
PcdGet16 (PcdShellPrintBufferSize), L"%2", NewScriptFile->Argv[2], FALSE,
FALSE);
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2,
PcdGet16 (PcdShellPrintBufferSize), L"%2", NewScriptFile->Argv[2], FALSE, TRUE);
ASSERT_EFI_ERROR(Status);
case 2:
- Status = ShellCopySearchAndReplace(CommandLine2, CommandLine,
PcdGet16 (PcdShellPrintBufferSize), L"%1", NewScriptFile->Argv[1], FALSE,
FALSE);
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine,
PcdGet16 (PcdShellPrintBufferSize), L"%1", NewScriptFile->Argv[1], FALSE, TRUE);
ASSERT_EFI_ERROR(Status);
case 1:
- Status = ShellCopySearchAndReplace(CommandLine, CommandLine2,
PcdGet16 (PcdShellPrintBufferSize), L"%0", NewScriptFile->Argv[0], FALSE,
FALSE);
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2,
PcdGet16 (PcdShellPrintBufferSize), L"%0", NewScriptFile->Argv[0], FALSE, TRUE);
ASSERT_EFI_ERROR(Status);
break;
case 0:
@@ -2836,3 +2894,38 @@
return (Status);
}
+
+/**
+ Return the pointer to the first occurance of any character from a list of
characters
+
+ @param[in] String the string to parse
+ @param[in] CharacterList the list of character to look for
+ @param[in] EscapeCharacter An escape character to skip
+
+ @return the location of the first character in the string
+ @retval CHAR_NULL no instance of any character in CharacterList was found in
String
+**/
+CONST CHAR16*
+EFIAPI
+FindFirstCharacter(
+ IN CONST CHAR16 *String,
+ IN CONST CHAR16 *CharacterList,
+ IN CONST CHAR16 EscapeCharacter
+ )
+{
+ UINT32 WalkChar;
+ UINT32 WalkStr;
+
+ for (WalkStr = 0; WalkStr < StrLen(String); WalkStr++) {
+ if (String[WalkStr] == EscapeCharacter) {
+ WalkStr++;
+ continue;
+ }
+ for (WalkChar = 0; WalkChar < StrLen(CharacterList); WalkChar++) {
+ if (String[WalkStr] == CharacterList[WalkChar]) {
+ return (&String[WalkStr]);
+ }
+ }
+ }
+ return (String + StrLen(String));
+}
\ No newline at end of file
Modified: branches/UDK2014.SP1/ShellPkg/Application/Shell/Shell.h
===================================================================
--- branches/UDK2014.SP1/ShellPkg/Application/Shell/Shell.h 2015-04-01
04:56:00 UTC (rev 17087)
+++ branches/UDK2014.SP1/ShellPkg/Application/Shell/Shell.h 2015-04-01
07:19:31 UTC (rev 17088)
@@ -2,7 +2,7 @@
function definitions for internal to shell functions.
(C) Copyright 2014, Hewlett-Packard Development Company, L.P.
- Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD
License
which accompanies this distribution. The full text of the license may be
found at
@@ -343,6 +343,23 @@
IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol
);
+/**
+ Return the pointer to the first occurance of any character from a list of
characters
+ @param[in] String the string to parse
+ @param[in] CharacterList the list of character to look for
+ @param[in] EscapeCharacter An escape character to skip
+
+ @return the location of the first character in the string
+ @retval CHAR_NULL no instance of any character in CharacterList was found in
String
+**/
+CONST CHAR16*
+EFIAPI
+FindFirstCharacter(
+ IN CONST CHAR16 *String,
+ IN CONST CHAR16 *CharacterList,
+ IN CONST CHAR16 EscapeCharacter
+ );
+
#endif //_SHELL_INTERNAL_HEADER_
Modified:
branches/UDK2014.SP1/ShellPkg/Application/Shell/ShellParametersProtocol.c
===================================================================
--- branches/UDK2014.SP1/ShellPkg/Application/Shell/ShellParametersProtocol.c
2015-04-01 04:56:00 UTC (rev 17087)
+++ branches/UDK2014.SP1/ShellPkg/Application/Shell/ShellParametersProtocol.c
2015-04-01 07:19:31 UTC (rev 17088)
@@ -4,7 +4,7 @@
Copyright (C) 2014, Red Hat, Inc.
Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
- Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD
License
which accompanies this distribution. The full text of the license may be
found at
@@ -18,8 +18,51 @@
#include "Shell.h"
/**
- return the next parameter from a command line string;
+ Return the next parameter's end from a command line string.
+ @param[in] String the string to parse
+**/
+CONST CHAR16*
+EFIAPI
+FindEndOfParameter(
+ IN CONST CHAR16 *String
+ )
+{
+ CONST CHAR16 *First;
+ CONST CHAR16 *CloseQuote;
+
+ First = FindFirstCharacter(String, L" \"", L'^');
+
+ //
+ // nothing, all one parameter remaining
+ //
+ if (*First == CHAR_NULL) {
+ return (First);
+ }
+
+ //
+ // If space before a quote (or neither found, i.e. both CHAR_NULL),
+ // then that's the end.
+ //
+ if (*First == L' ') {
+ return (First);
+ }
+
+ CloseQuote = FindFirstCharacter (First+1, L"\"", L'^');
+
+ //
+ // We did not find a terminator...
+ //
+ if (*CloseQuote == CHAR_NULL) {
+ return (NULL);
+ }
+
+ return (FindEndOfParameter (CloseQuote+1));
+}
+
+/**
+ Return the next parameter from a command line string.
+
This function moves the next parameter from Walker into TempParameter and
moves
Walker up past that parameter for recursive calling. When the final
parameter
is moved *Walker will be set to NULL;
@@ -27,12 +70,17 @@
Temp Parameter must be large enough to hold the parameter before calling this
function.
+ This will also remove all remaining ^ characters after processing.
+
@param[in, out] Walker pointer to string of command line. Adjusted to
reminaing command line on return
@param[in, out] TempParameter pointer to string of command line item
extracted.
@param[in] Length buffer size of TempParameter.
+
+ @return EFI_INALID_PARAMETER A required parameter was NULL or pointed to
a NULL or empty string.
+ @return EFI_NOT_FOUND A closing " could not be found on the
specified string
**/
-VOID
+EFI_STATUS
EFIAPI
GetNextParameter(
IN OUT CHAR16 **Walker,
@@ -40,14 +88,17 @@
IN CONST UINTN Length
)
{
- CHAR16 *NextDelim;
- CHAR16 *TempLoc;
+ CONST CHAR16 *NextDelim;
- ASSERT(Walker != NULL);
- ASSERT(*Walker != NULL);
- ASSERT(TempParameter != NULL);
- ASSERT(*TempParameter != NULL);
+ if (Walker == NULL
+ ||*Walker == NULL
+ ||TempParameter == NULL
+ ||*TempParameter == NULL
+ ){
+ return (EFI_INVALID_PARAMETER);
+ }
+
//
// make sure we dont have any leading spaces
//
@@ -59,81 +110,60 @@
// make sure we still have some params now...
//
if (StrLen(*Walker) == 0) {
- ASSERT((*Walker)[0] == CHAR_NULL);
- *Walker = NULL;
- return;
+DEBUG_CODE_BEGIN();
+ *Walker = NULL;
+DEBUG_CODE_END();
+ return (EFI_INVALID_PARAMETER);
}
+ NextDelim = FindEndOfParameter(*Walker);
+
+ if (NextDelim == NULL){
+DEBUG_CODE_BEGIN();
+ *Walker = NULL;
+DEBUG_CODE_END();
+ return (EFI_NOT_FOUND);
+ }
+
+ StrnCpy(*TempParameter, (*Walker), NextDelim - *Walker);
+
//
- // we have a quoted parameter
- // could be the last parameter, but SHOULD have a trailing quote
+ // Add a CHAR_NULL if we didnt get one via the copy
//
- if ((*Walker)[0] == L'\"') {
- NextDelim = NULL;
- for (TempLoc = *Walker + 1 ; TempLoc != NULL && *TempLoc != CHAR_NULL ;
TempLoc++) {
- if (*TempLoc == L'^' && *(TempLoc+1) == L'\"') {
- TempLoc++;
- } else if (*TempLoc == L'\"') {
- NextDelim = TempLoc;
- break;
- }
- }
+ if (*NextDelim != CHAR_NULL) {
+ (*TempParameter)[NextDelim - *Walker] = CHAR_NULL;
+ }
- if (NextDelim - ((*Walker)+1) == 0) {
+ //
+ // Update Walker for the next iteration through the function
+ //
+ *Walker = (CHAR16*)NextDelim;
+
+ //
+ // Remove any non-escaped quotes in the string
+ // Remove any remaining escape characters in the string
+ //
+ for (NextDelim = FindFirstCharacter(*TempParameter, L"\"^", CHAR_NULL)
+ ; *NextDelim != CHAR_NULL
+ ; NextDelim = FindFirstCharacter(NextDelim, L"\"^", CHAR_NULL)
+ ) {
+ if (*NextDelim == L'^') {
+
//
- // found ""
+ // eliminate the escape ^
//
- *(*TempParameter) = CHAR_NULL;
- *Walker = NextDelim + 1;
- } else if (NextDelim != NULL) {
+ CopyMem ((CHAR16*)NextDelim, NextDelim + 1, StrSize (NextDelim + 1));
+ NextDelim++;
+ } else if (*NextDelim == L'\"') {
//
- // Copy ensuring that both quotes are left in place.
+ // eliminate the unescaped quote
//
- StrnCpy(*TempParameter, (*Walker), NextDelim - *Walker + 1);
- *Walker = NextDelim + 1;
- } else {
- //
- // last one... someone forgot the training quote!
- //
- StrnCpy(*TempParameter, *Walker, Length/sizeof(CHAR16) - 1);
- *Walker = NULL;
+ CopyMem ((CHAR16*)NextDelim, NextDelim + 1, StrSize (NextDelim + 1));
}
- for (TempLoc = *TempParameter ; TempLoc != NULL && *TempLoc != CHAR_NULL ;
TempLoc++) {
- if (*TempLoc == L'^' && *(TempLoc+1) == L'\"') {
- CopyMem(TempLoc, TempLoc+1, StrSize(TempLoc) - sizeof(TempLoc[0]));
- }
- }
- } else {
- //
- // we have a regular parameter (no quote) OR
- // we have the final parameter (no trailing space)
- //
- NextDelim = StrStr((*Walker), L" ");
- if (NextDelim != NULL) {
- StrnCpy(*TempParameter, *Walker, NextDelim - (*Walker));
- (*TempParameter)[NextDelim - (*Walker)] = CHAR_NULL;
- *Walker = NextDelim+1;
- } else {
- //
- // last one.
- //
- StrnCpy(*TempParameter, *Walker, Length/sizeof(CHAR16) - 1);
- *Walker = NULL;
- }
- for (NextDelim = *TempParameter ; NextDelim != NULL && *NextDelim !=
CHAR_NULL ; NextDelim++) {
- if (*NextDelim == L'^' && *(NextDelim+1) == L'^') {
- CopyMem(NextDelim, NextDelim+1, StrSize(NextDelim) -
sizeof(NextDelim[0]));
- }
- }
- while ((*TempParameter)[StrLen(*TempParameter)-1] == L' ') {
- (*TempParameter)[StrLen(*TempParameter)-1] = CHAR_NULL;
- }
- while ((*TempParameter)[0] == L' ') {
- CopyMem(*TempParameter, (*TempParameter)+1, StrSize(*TempParameter) -
sizeof((*TempParameter)[0]));
- }
}
- return;
+
+ return EFI_SUCCESS;
}
/**
@@ -143,6 +173,9 @@
parameters for inclusion in EFI_SHELL_PARAMETERS_PROTOCOL. this supports
space
delimited and quote surrounded parameter definition.
+ All special character processing (alias, environment variable, redirection,
+ etc... must be complete before calling this API.
+
@param[in] CommandLine String of command line to parse
@param[in, out] Argv pointer to array of strings; one for each
parameter
@param[in, out] Argc pointer to number of strings in Argv array
@@ -182,9 +215,12 @@
for ( Count = 0
, Walker = (CHAR16*)CommandLine
; Walker != NULL && *Walker != CHAR_NULL
- ; GetNextParameter(&Walker, &TempParameter, Size)
- , Count++
- );
+ ; Count++
+ ) {
+ if (EFI_ERROR(GetNextParameter(&Walker, &TempParameter, Size))) {
+ break;
+ }
+ }
//
// lets allocate the pointer array
@@ -199,7 +235,11 @@
Walker = (CHAR16*)CommandLine;
while(Walker != NULL && *Walker != CHAR_NULL) {
SetMem16(TempParameter, Size, CHAR_NULL);
- GetNextParameter(&Walker, &TempParameter, Size);
+ if (EFI_ERROR(GetNextParameter(&Walker, &TempParameter, Size))) {
+ SHELL_FREE_NON_NULL(TempParameter);
+ return (EFI_INVALID_PARAMETER);
+ }
+
NewParam = AllocateCopyPool(StrSize(TempParameter), TempParameter);
if (NewParam == NULL){
SHELL_FREE_NON_NULL(TempParameter);
Modified:
branches/UDK2014.SP1/ShellPkg/Application/Shell/ShellParametersProtocol.h
===================================================================
--- branches/UDK2014.SP1/ShellPkg/Application/Shell/ShellParametersProtocol.h
2015-04-01 04:56:00 UTC (rev 17087)
+++ branches/UDK2014.SP1/ShellPkg/Application/Shell/ShellParametersProtocol.h
2015-04-01 07:19:31 UTC (rev 17088)
@@ -192,8 +192,10 @@
@param[in, out] TempParameter pointer to string of command line item
extracted.
@param[in] Length Length of (*TempParameter) in bytes
+ @return EFI_INALID_PARAMETER A required parameter was NULL or pointed to
a NULL or empty string.
+ @return EFI_NOT_FOUND A closing " could not be found on the
specified string
**/
-VOID
+EFI_STATUS
EFIAPI
GetNextParameter(
IN OUT CHAR16 **Walker,
------------------------------------------------------------------------------
Dive into the World of Parallel Programming The Go Parallel Website, sponsored
by Intel and developed in partnership with Slashdot Media, is your hub for all
things parallel software development, from weekly thought leadership blogs to
news, videos, case studies, tutorials and more. Take a look and join the
conversation now. http://goparallel.sourceforge.net/
_______________________________________________
edk2-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-commits