[edk2-devel] [PATCH 1/1] ShellPkg/Application: Support nested variables substitution from cmd line

Vladimir Olovyannikov via Groups.Io vladimir.olovyannikov=broadcom.com at groups.io
Thu Jan 9 22:06:37 UTC 2020


The current implementation of ShellSubstituteVariables() does not allow
substitution of variables names containing another variable name(s)
between %...%

Example: %text%var_name%% where var_name variable contains 0.
Here the variable value which should be returned on substitution
would be contents of text0 variable.
The current implementation would return nothing as %text0% would be
eliminated by StripUnreplacedEnvironmentVariables().

Modify the code so that StripUnreplacedEnvironmentVariables checks if
variable between %...% really exists. If it does not, delete %...%.
If it exists, preserve it and tell the caller that another run of
ShellConvertVariables() is needed. This way, any nested variable
between %...% can be easily retrieved.
REF:https://bugzilla.tianocore.org/show_bug.cgi?id=2452

Signed-off-by: Vladimir Olovyannikov <vladimir.olovyannikov at broadcom.com>
Contributed-under: TianoCore Contribution Agreement 1.1
---
 ShellPkg/Application/Shell/Shell.c | 71 ++++++++++++++++++++++++------
 1 file changed, 57 insertions(+), 14 deletions(-)

diff --git a/ShellPkg/Application/Shell/Shell.c b/ShellPkg/Application/Shell/Shell.c
index d16adae0ea30..3756a71794d1 100644
--- a/ShellPkg/Application/Shell/Shell.c
+++ b/ShellPkg/Application/Shell/Shell.c
@@ -1510,12 +1510,16 @@ ShellConvertAlias(
 
 /**
   This function will eliminate unreplaced (and therefore non-found) environment variables.
-
+  If a variable exists between %...%, it will be preserved, and VarExists
+  would be TRUE.
   @param[in,out] CmdLine   The command line to update.
+  @param[out] VarExists    A pointer to the BOOLEAN which is set if
+                           a Shell variable between %...% exists.
 **/
 EFI_STATUS
 StripUnreplacedEnvironmentVariables(
-  IN OUT CHAR16 *CmdLine
+  IN OUT CHAR16 *CmdLine,
+  OUT BOOLEAN   *VarExists
   )
 {
   CHAR16 *FirstPercent;
@@ -1558,12 +1562,38 @@ StripUnreplacedEnvironmentVariables(
     if (FirstQuote == NULL || SecondPercent < FirstQuote) {
       if (IsValidEnvironmentVariableName(FirstPercent, SecondPercent)) {
         //
-        // We need to remove from FirstPercent to SecondPercent
-        //
-        CopyMem(FirstPercent, SecondPercent + 1, StrSize(SecondPercent + 1));
-        //
-        // don't need to update the locator.  both % characters are gone.
+        // If this Shell variable exists, consider that another run is needed.
+        // For example, consider a variable %var%var2%% when var2 is 0.
+        // After the first run, it becomes %var0%, and after the second run
+        // it contains the value of var0 variable.
+        // Eliminate variable if it does not exist.
         //
+        CHAR16 *VarName;
+
+        // Consider NULL terminator as well
+        VarName = (CHAR16 *)AllocateZeroPool((SecondPercent - FirstPercent) *
+                                             sizeof(CHAR16));
+        if (VarName) {
+          CopyMem(VarName, FirstPercent + 1,
+                  (SecondPercent - FirstPercent - 1) * sizeof(CHAR16));
+        }
+
+        if (!VarName || !ShellGetEnvironmentVariable(VarName)) {
+          //
+          // We need to remove from FirstPercent to SecondPercent.
+          //
+          CopyMem(FirstPercent, SecondPercent + 1, StrSize(SecondPercent + 1));
+          //
+          // don't need to update the locator.  both % characters are gone.
+          //
+        } else {
+          *VarExists = TRUE;
+          //
+          // In this case, locator needs to be updated as % characters present.
+          //
+          CurrentLocator = SecondPercent + 1;
+        }
+        SHELL_FREE_NON_NULL(VarName);
       } else {
         CurrentLocator = SecondPercent + 1;
       }
@@ -1581,13 +1611,18 @@ StripUnreplacedEnvironmentVariables(
   If the return value is not NULL the memory must be caller freed.
 
   @param[in] OriginalCommandLine    The original command line
+  @param[out] NeedExtraRun          Indication that the caller needs to repeat
+                                    this call to convert variables as there are
+                                    existing variable(s) between %..%
+                                    present after the call.
 
   @retval NULL                      An error occurred.
   @return                           The new command line with no environment variables present.
 **/
 CHAR16*
 ShellConvertVariables (
-  IN CONST CHAR16 *OriginalCommandLine
+  IN CONST CHAR16 *OriginalCommandLine,
+  OUT BOOLEAN     *NeedExtraRun
   )
 {
   CONST CHAR16        *MasterEnvList;
@@ -1601,11 +1636,13 @@ ShellConvertVariables (
   ALIAS_LIST          *AliasListNode;
 
   ASSERT(OriginalCommandLine != NULL);
+  ASSERT(NeedExtraRun != NULL);
 
   ItemSize          = 0;
   NewSize           = StrSize(OriginalCommandLine);
   CurrentScriptFile = ShellCommandGetCurrentScriptFile();
   Temp              = NULL;
+  *NeedExtraRun     = FALSE;
 
   ///@todo update this to handle the %0 - %9 for scripting only (borrow from line 1256 area) ? ? ?
 
@@ -1698,7 +1735,7 @@ ShellConvertVariables (
   //
   // Remove non-existent environment variables
   //
-  StripUnreplacedEnvironmentVariables(NewCommandLine1);
+  StripUnreplacedEnvironmentVariables(NewCommandLine1, NeedExtraRun);
 
   //
   // Now cleanup any straggler intentionally ignored "%" characters
@@ -1845,12 +1882,18 @@ ShellSubstituteVariables(
   )
 {
   CHAR16      *NewCmdLine;
-  NewCmdLine = ShellConvertVariables(*CmdLine);
-  SHELL_FREE_NON_NULL(*CmdLine);
-  if (NewCmdLine == NULL) {
-    return (EFI_OUT_OF_RESOURCES);
+  BOOLEAN     NeedExtraRun;
+
+  NeedExtraRun = TRUE;
+  while (NeedExtraRun) {
+    NewCmdLine = ShellConvertVariables(*CmdLine, &NeedExtraRun);
+    SHELL_FREE_NON_NULL(*CmdLine);
+    if (NewCmdLine == NULL) {
+      return (EFI_OUT_OF_RESOURCES);
+    }
+    *CmdLine = NewCmdLine;
   }
-  *CmdLine = NewCmdLine;
+  
   return (EFI_SUCCESS);
 }
 
-- 
2.17.1


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#53095): https://edk2.groups.io/g/devel/message/53095
Mute This Topic: https://groups.io/mt/69589246/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-





More information about the edk2-devel-archive mailing list