From ea927d2f3f2e34f4b26c10829f5887830cb0720e Mon Sep 17 00:00:00 2001 From: "Feng, YunhuaX" Date: Mon, 26 Feb 2018 16:42:30 +0800 Subject: BaseTools: Fix flexible PCD single quote and double quote bugs 1.The " and ' inside the string, must use escape character format (\", \') 2.'string' and L'string' format in --pcd, it must be double quoted first. Some examples that to match --pcd format and DSC format --pcd DSC format L"ABC" L"ABC" "AB\\\"C" "AB\"C" "AB\\\'C" "AB\'C" L"\'AB\\\"C\'" L'AB\"C' "\'AB\\\'C\'" 'AB\'C' H"{0, L\"AB\\\"B\", \'ab\\\"c\'}" {0, L"AB\"B", 'ab\"c'} Cc: Liming Gao Cc: Yonghong Zhu Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Yunhua Feng Reviewed-by: Yonghong Zhu --- BaseTools/Source/Python/Common/Expression.py | 60 ++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 17 deletions(-) (limited to 'BaseTools/Source/Python/Common/Expression.py') diff --git a/BaseTools/Source/Python/Common/Expression.py b/BaseTools/Source/Python/Common/Expression.py index edb0a60de6..f1516d5c7b 100644 --- a/BaseTools/Source/Python/Common/Expression.py +++ b/BaseTools/Source/Python/Common/Expression.py @@ -45,15 +45,28 @@ ERR_IN_OPERAND = 'Macro after IN operator can only be: $(FAMILY), $(ARC # For example: abc"de\"f"ghi"jkl"mn will be: ['abc', '"de\"f"', 'ghi', '"jkl"', 'mn'] # def SplitString(String): - # There might be escaped quote: "abc\"def\\\"ghi" - Str = String.replace('\\\\', '//').replace('\\\"', '\\\'') + # There might be escaped quote: "abc\"def\\\"ghi", 'abc\'def\\\'ghi' + Str = String RetList = [] - InQuote = False + InSingleQuote = False + InDoubleQuote = False Item = '' for i, ch in enumerate(Str): - if ch == '"': - InQuote = not InQuote - if not InQuote: + if ch == '"' and not InSingleQuote: + if Str[i - 1] != '\\': + InDoubleQuote = not InDoubleQuote + if not InDoubleQuote: + Item += String[i] + RetList.append(Item) + Item = '' + continue + if Item: + RetList.append(Item) + Item = '' + elif ch == "'" and not InDoubleQuote: + if Str[i - 1] != '\\': + InSingleQuote = not InSingleQuote + if not InSingleQuote: Item += String[i] RetList.append(Item) Item = '' @@ -62,7 +75,7 @@ def SplitString(String): RetList.append(Item) Item = '' Item += String[i] - if InQuote: + if InSingleQuote or InDoubleQuote: raise BadExpression(ERR_STRING_TOKEN % Item) if Item: RetList.append(Item) @@ -483,6 +496,8 @@ class ValueExpression(object): Flag = 0 for Index in range(len(self._Token)): if self._Token[Index] in ['"']: + if self._Token[Index - 1] == '\\': + continue Flag += 1 if Flag == 2 and self._Token.endswith('"'): return True @@ -490,6 +505,8 @@ class ValueExpression(object): Flag = 0 for Index in range(len(self._Token)): if self._Token[Index] in ["'"]: + if self._Token[Index - 1] == '\\': + continue Flag += 1 if Flag == 2 and self._Token.endswith("'"): return True @@ -537,16 +554,25 @@ class ValueExpression(object): self._Idx += 1 # Replace escape \\\", \" - Expr = self._Expr[self._Idx:].replace('\\\\', '//').replace('\\\"', '\\\'') - for Ch in Expr: - self._Idx += 1 - if Ch == '"' or Ch == "'": - break - self._Token = self._LiteralToken = self._Expr[Idx:self._Idx] - if self._Token.startswith('"') and not self._Token.endswith('"'): - raise BadExpression(ERR_STRING_TOKEN % self._Token) - if self._Token.startswith("'") and not self._Token.endswith("'"): - raise BadExpression(ERR_STRING_TOKEN % self._Token) + if self._Expr[Idx] == '"': + Expr = self._Expr[self._Idx:].replace('\\\\', '//').replace('\\\"', '\\\'') + for Ch in Expr: + self._Idx += 1 + if Ch == '"': + break + self._Token = self._LiteralToken = self._Expr[Idx:self._Idx] + if not self._Token.endswith('"'): + raise BadExpression(ERR_STRING_TOKEN % self._Token) + #Replace escape \\\', \' + elif self._Expr[Idx] == "'": + Expr = self._Expr[self._Idx:].replace('\\\\', '//').replace("\\\'", "\\\"") + for Ch in Expr: + self._Idx += 1 + if Ch == "'": + break + self._Token = self._LiteralToken = self._Expr[Idx:self._Idx] + if not self._Token.endswith("'"): + raise BadExpression(ERR_STRING_TOKEN % self._Token) self._Token = self._Token[1:-1] return self._Token -- cgit v1.2.3