From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pl1-f182.google.com (mail-pl1-f182.google.com [209.85.214.182]) by mx.groups.io with SMTP id smtpd.web12.1693.1578607605749764714 for ; Thu, 09 Jan 2020 14:06:45 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@broadcom.com header.s=google header.b=fikFFRBQ; spf=pass (domain: broadcom.com, ip: 209.85.214.182, mailfrom: vladimir.olovyannikov@broadcom.com) Received: by mail-pl1-f182.google.com with SMTP id b22so2473pls.12 for ; Thu, 09 Jan 2020 14:06:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; h=from:to:cc:subject:date:message-id; bh=zCRc8QdZ2RYo30fVBxRTtOqrrarjERI4qiNgh1E9yUg=; b=fikFFRBQX51dxFBCrwfj1C8wzcVIXwsL6+nuh6hwaRH3iD7d4WNPsrRjrzIV4dqvCo 4vUklQq4i9w6BQvdtfWysSkiw1BO6UQUHUziwAiSRA/gubVma9+CKL/MyOHQstSf/JoQ Mlrjmd8vmiUOC1rWQVQm/pT0vE4rtEnl2qH/s= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=zCRc8QdZ2RYo30fVBxRTtOqrrarjERI4qiNgh1E9yUg=; b=QdVm5RLRT7JD4HrAah/SyMgvxNNPHiHRD4Gu0heeGJA6/yOMh35bKLZlcOmyiiDCSO gWk/GuWgX8fOM26O2xyOopVW9tM2iTC+UNZgUleWlE9WvOxx6346nz7XOzFCQn90Fbg3 ecVcSQW4bVt53S+kdsuXTwAonI5UmIXvrHn0U9+LYTk+9Nu3ZpKTBzGO3IdDMz1ZTh6E fvPhR9KNcRvrqEjsrukddnWi4GIJA1wbJ/iLMCTR/5yN/U9JQVG5MzAYuzXoVBqnHANm SrCdqfncUklmqPMoLS9k/B48d8qGPVlrWJWze2KF4D1Af+TEBo3Sb/CAIXwSG5fAUUvb eulA== X-Gm-Message-State: APjAAAWGwHDblG1leGThgFsfiwooTp9FxXFil25faKyVY7E00uYa3CgT YNyfva7zYRY1t2sMlKH3ppYR2cMqXHV7mZXhlrOJ/raSfSva9aH9PvWHVB2TH56UaF0/rYZBFg3 QlSJsHJNY7EerheVku1V81NmfQ+nzDOY7Z0AgIR2ZI6z2ckbvKmb0GRcvjNnATpvF8Yv6cMOZ2A 0utfPpTPtbCv4= X-Google-Smtp-Source: APXvYqy0LT1INm2u/vp6Sf9W8w4EXWhLt+f3d5K/fFW8rXgcovgGUK4jfqxyIpmWxhN5zYl8iK6Qjw== X-Received: by 2002:a17:902:7613:: with SMTP id k19mr202284pll.7.1578607604847; Thu, 09 Jan 2020 14:06:44 -0800 (PST) Return-Path: Received: from LBRMN-LNXUB114.ric.broadcom.com ([192.19.228.250]) by smtp.gmail.com with ESMTPSA id b20sm2890pfi.153.2020.01.09.14.06.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Jan 2020 14:06:44 -0800 (PST) From: "Vladimir Olovyannikov" To: devel@edk2.groups.io, Ray Ni , Zhichao Gao Cc: Vladimir Olovyannikov Subject: [PATCH 1/1] ShellPkg/Application: Support nested variables substitution from cmd line Date: Thu, 9 Jan 2020 14:06:37 -0800 Message-Id: <20200109220637.28691-1-vladimir.olovyannikov@broadcom.com> X-Mailer: git-send-email 2.17.1 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 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