From 28c784d87b0def07e63a1d5053fb9e7b6240c635 Mon Sep 17 00:00:00 2001 From: Lasse Reichstein Holst Nielsen Date: Wed, 19 May 2021 12:35:16 +0000 Subject: [PATCH] Fix gn helper script to create *valid* strings for settings containing backslashes. The current script stores some environment variable values as GN declarations. It replaces `"` inside the value with `\"` because it creates a `"`-delimited string, but it doesn't replace `\` with `\\` as it rightly should to preserve the meaning of the original string. That affects **Windows paths**. If your path ends in `\`, the created "string literal" will end (or rather, not end) with `\"` and not be valid. Similarly if it contains `\"` originally, it will become `\\"` and end the string early. It's easy to have a path ending in something like `C:\something\something\`, and you can't compile Dart if you have that. Change-Id: Iaa3cdf0c8113fe2f09e7eb3ac7435bf770d8b478 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/200641 Reviewed-by: Alexander Thomas Commit-Queue: Lasse R.H. Nielsen --- build/gn_helpers.py | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/build/gn_helpers.py b/build/gn_helpers.py index 3acb32990ba..b1fc036e1e4 100644 --- a/build/gn_helpers.py +++ b/build/gn_helpers.py @@ -5,12 +5,30 @@ exec_script function.""" +import sys + + class GNException(Exception): pass +# Computes ASCII code of an element of encoded Python 2 str / Python 3 bytes. +_Ord = ord if sys.version_info.major < 3 else lambda c: c + + +def _TranslateToGnChars(s): + for decoded_ch in s.encode('utf-8'): # str in Python 2, bytes in Python 3. + code = _Ord(decoded_ch) # int + if code in (34, 36, 92): # For '"', '$', or '\\'. + yield '\\' + chr(code) + elif 32 <= code < 127: + yield chr(code) + else: + yield '$0x%02X' % code + + def ToGNString(value, allow_dicts=True): - """Prints the given value to stdout. + """Returns a stringified GN equivalent of a Python value. allow_dicts indicates if this function will allow converting dictionaries to GN scopes. This is only possible at the top level, you can't nest a @@ -18,10 +36,10 @@ def ToGNString(value, allow_dicts=True): if isinstance(value, str) or isinstance(value, unicode): if value.find('\n') >= 0: raise GNException("Trying to print a string with a newline in it.") - return '"' + value.replace('"', '\\"') + '"' + return '"' + ''.join(_TranslateToGnChars(value)) + '"' if isinstance(value, list): - return '[ %s ]' % ', '.join(ToGNString(v) for v in value) + return '[ %s ]' % ', '.join(ToGNString(v, False) for v in value) if isinstance(value, dict): if not allow_dicts: