diff options
author | Eli Schwartz <eschwartz93@gmail.com> | 2024-04-28 12:14:06 -0400 |
---|---|---|
committer | Jussi Pakkanen <jpakkane@gmail.com> | 2024-04-28 22:51:08 +0300 |
commit | e5f32b74144b9f4a43304fa167899e202c5912b5 (patch) | |
tree | cd3991e1fa1e5daae50cbe7915b58b62dc7c172e /mesonbuild | |
parent | 4f3a3e2efeb415fe83f9e858b010a36baf72b455 (diff) | |
download | meson-e5f32b74144b9f4a43304fa167899e202c5912b5.zip meson-e5f32b74144b9f4a43304fa167899e202c5912b5.tar.gz meson-e5f32b74144b9f4a43304fa167899e202c5912b5.tar.bz2 |
catch build files that cannot be opened in utf8 mode and emit useful error
Previously, if a junked meson.build or native.ini was used we got a
lengthy traceback ending in UnicodeDecodeError.
Fixes: #13154
Fixes: #13156
Diffstat (limited to 'mesonbuild')
-rw-r--r-- | mesonbuild/ast/interpreter.py | 4 | ||||
-rw-r--r-- | mesonbuild/coredata.py | 20 | ||||
-rw-r--r-- | mesonbuild/interpreter/interpreter.py | 4 | ||||
-rw-r--r-- | mesonbuild/interpreterbase/interpreterbase.py | 11 | ||||
-rw-r--r-- | mesonbuild/optinterpreter.py | 6 |
5 files changed, 28 insertions, 17 deletions
diff --git a/mesonbuild/ast/interpreter.py b/mesonbuild/ast/interpreter.py index 53ddc10..15d2793 100644 --- a/mesonbuild/ast/interpreter.py +++ b/mesonbuild/ast/interpreter.py @@ -189,9 +189,7 @@ class AstInterpreter(InterpreterBase): if not os.path.isfile(absname): sys.stderr.write(f'Unable to find build file {buildfilename} --> Skipping\n') return - with open(absname, encoding='utf-8') as f: - code = f.read() - assert isinstance(code, str) + code = self.read_buildfile(absname, buildfilename) try: codeblock = mparser.Parser(code, absname).parse() except mesonlib.MesonException as me: diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 3cf873f..7213115 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -1102,14 +1102,18 @@ class MachineFileParser(): self.sections: T.Dict[str, T.Dict[str, T.Union[str, bool, int, T.List[str]]]] = {} for fname in filenames: - with open(fname, encoding='utf-8') as f: - content = f.read() - content = content.replace('@GLOBAL_SOURCE_ROOT@', sourcedir) - content = content.replace('@DIRNAME@', os.path.dirname(fname)) - try: - self.parser.read_string(content, fname) - except configparser.Error as e: - raise EnvironmentException(f'Malformed machine file: {e}') + try: + with open(fname, encoding='utf-8') as f: + content = f.read() + except UnicodeDecodeError as e: + raise EnvironmentException(f'Malformed machine file {fname!r} failed to parse as unicode: {e}') + + content = content.replace('@GLOBAL_SOURCE_ROOT@', sourcedir) + content = content.replace('@DIRNAME@', os.path.dirname(fname)) + try: + self.parser.read_string(content, fname) + except configparser.Error as e: + raise EnvironmentException(f'Malformed machine file: {e}') # Parse [constants] first so they can be used in other sections if self.parser.has_section('constants'): diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index de8f24d..f6b4cf4 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -2425,9 +2425,7 @@ class Interpreter(InterpreterBase, HoldableObject): if not os.path.isfile(absname): self.subdir = prev_subdir raise InterpreterException(f"Nonexistent build file '{buildfilename!s}'") - with open(absname, encoding='utf-8') as f: - code = f.read() - assert isinstance(code, str) + code = self.read_buildfile(absname, buildfilename) try: codeblock = mparser.Parser(code, absname).parse() except mesonlib.MesonException as me: diff --git a/mesonbuild/interpreterbase/interpreterbase.py b/mesonbuild/interpreterbase/interpreterbase.py index ccc3349..525d5d6 100644 --- a/mesonbuild/interpreterbase/interpreterbase.py +++ b/mesonbuild/interpreterbase/interpreterbase.py @@ -93,12 +93,19 @@ class InterpreterBase: # do nothing in an AST interpreter return + def read_buildfile(self, fname: str, errname: str) -> str: + try: + with open(fname, encoding='utf-8') as f: + return f.read() + except UnicodeDecodeError as e: + node = mparser.BaseNode(1, 1, errname) + raise InvalidCode.from_node(f'Build file failed to parse as unicode: {e}', node=node) + def load_root_meson_file(self) -> None: mesonfile = os.path.join(self.source_root, self.subdir, environment.build_filename) if not os.path.isfile(mesonfile): raise InvalidArguments(f'Missing Meson file in {mesonfile}') - with open(mesonfile, encoding='utf-8') as mf: - code = mf.read() + code = self.read_buildfile(mesonfile, mesonfile) if code.isspace(): raise InvalidCode('Builder file is empty.') assert isinstance(code, str) diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py index 980dadd..599da65 100644 --- a/mesonbuild/optinterpreter.py +++ b/mesonbuild/optinterpreter.py @@ -78,7 +78,11 @@ class OptionInterpreter: def process(self, option_file: str) -> None: try: with open(option_file, encoding='utf-8') as f: - ast = mparser.Parser(f.read(), option_file).parse() + code = f.read() + except UnicodeDecodeError as e: + raise mesonlib.MesonException(f'Malformed option file {option_file!r} failed to parse as unicode: {e}') + try: + ast = mparser.Parser(code, option_file).parse() except mesonlib.MesonException as me: me.file = option_file raise me |