aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Claessens <xavier.claessens@collabora.com>2021-10-31 16:16:10 -0400
committerEli Schwartz <eschwartz93@gmail.com>2022-06-16 17:06:25 -0400
commit2e3ac3eec00f32dabcfc470cd4c1090303d08e58 (patch)
tree1c7c1b51798a99a5566c99233b5a6d2b713292c8
parent7229443738482db2183d048cf8b8b8e6bd11fa6d (diff)
downloadmeson-2e3ac3eec00f32dabcfc470cd4c1090303d08e58.zip
meson-2e3ac3eec00f32dabcfc470cd4c1090303d08e58.tar.gz
meson-2e3ac3eec00f32dabcfc470cd4c1090303d08e58.tar.bz2
minstall: Add more safety checks when unpickling installdata
When need to catch exceptions just like we do in coredata.load() to print proper error message instead of backtrace when user mix meson versions. This happens frequently when user has a newer version of meson installed in their HOME and then "sudo meson install" uses the system version of meson.
-rw-r--r--mesonbuild/coredata.py19
-rw-r--r--mesonbuild/mesonlib/universal.py22
-rw-r--r--mesonbuild/minstall.py15
3 files changed, 30 insertions, 26 deletions
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index 569fe39..a55d674 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -23,6 +23,7 @@ from .mesonlib import (
MesonException, EnvironmentException, MachineChoice, PerMachine,
PerMachineDefaultable, default_libdir, default_libexecdir,
default_prefix, split_args, OptionKey, OptionType, stringlistify,
+ pickle_load
)
from .wrap import WrapMode
import ast
@@ -1047,23 +1048,11 @@ def major_versions_differ(v1: str, v2: str) -> bool:
def load(build_dir: str) -> CoreData:
filename = os.path.join(build_dir, 'meson-private', 'coredata.dat')
- load_fail_msg = f'Coredata file {filename!r} is corrupted. Try with a fresh build tree.'
- try:
- with open(filename, 'rb') as f:
- obj = pickle.load(f)
- except (pickle.UnpicklingError, EOFError):
- raise MesonException(load_fail_msg)
- except (TypeError, ModuleNotFoundError, AttributeError):
- raise MesonException(
- f"Coredata file {filename!r} references functions or classes that don't "
- "exist. This probably means that it was generated with an old "
- "version of meson.")
- if not isinstance(obj, CoreData):
- raise MesonException(load_fail_msg)
- if major_versions_differ(obj.version, version):
- raise MesonVersionMismatchException(obj.version, version)
+ obj = pickle_load(filename, 'Coredata', CoreData)
+ assert isinstance(obj, CoreData), 'for mypy'
return obj
+
def save(obj: CoreData, build_dir: str) -> str:
filename = os.path.join(build_dir, 'meson-private', 'coredata.dat')
prev_filename = filename + '.prev'
diff --git a/mesonbuild/mesonlib/universal.py b/mesonbuild/mesonlib/universal.py
index d708671..71f206a 100644
--- a/mesonbuild/mesonlib/universal.py
+++ b/mesonbuild/mesonlib/universal.py
@@ -31,6 +31,7 @@ import typing as T
import uuid
import textwrap
import copy
+import pickle
from mesonbuild import mlog
@@ -123,6 +124,7 @@ __all__ = [
'listify',
'partition',
'path_is_in_root',
+ 'pickle_load',
'Popen_safe',
'quiet_git',
'quote_arg',
@@ -2232,3 +2234,23 @@ class OptionKey:
def is_base(self) -> bool:
"""Convenience method to check if this is a base option."""
return self.type is OptionType.BASE
+
+def pickle_load(filename: str, object_name: str, object_type: T.Type) -> T.Any:
+ load_fail_msg = f'{object_name} file {filename!r} is corrupted. Try with a fresh build tree.'
+ try:
+ with open(filename, 'rb') as f:
+ obj = pickle.load(f)
+ except (pickle.UnpicklingError, EOFError):
+ raise MesonException(load_fail_msg)
+ except (TypeError, ModuleNotFoundError, AttributeError):
+ raise MesonException(
+ f"{object_name} file {filename!r} references functions or classes that don't "
+ "exist. This probably means that it was generated with an old "
+ "version of meson.")
+ if not isinstance(obj, object_type):
+ raise MesonException(load_fail_msg)
+ from ..coredata import version as coredata_version
+ from ..coredata import major_versions_differ, MesonVersionMismatchException
+ if major_versions_differ(obj.version, coredata_version):
+ raise MesonVersionMismatchException(obj.version, coredata_version)
+ return obj
diff --git a/mesonbuild/minstall.py b/mesonbuild/minstall.py
index 0c69126..551f909 100644
--- a/mesonbuild/minstall.py
+++ b/mesonbuild/minstall.py
@@ -18,7 +18,6 @@ from pathlib import Path
import argparse
import errno
import os
-import pickle
import shlex
import shutil
import subprocess
@@ -28,9 +27,7 @@ import typing as T
from . import build
from . import environment
from .backend.backends import InstallData
-from .coredata import major_versions_differ, MesonVersionMismatchException
-from .coredata import version as coredata_version
-from .mesonlib import MesonException, Popen_safe, RealPathAction, is_windows, setup_vsenv
+from .mesonlib import MesonException, Popen_safe, RealPathAction, is_windows, setup_vsenv, pickle_load
from .scripts import depfixer, destdir_join
from .scripts.meson_exe import run_exe
try:
@@ -133,13 +130,9 @@ class DirMaker:
def load_install_data(fname: str) -> InstallData:
- with open(fname, 'rb') as ifile:
- obj = pickle.load(ifile)
- if not isinstance(obj, InstallData) or not hasattr(obj, 'version'):
- raise MesonVersionMismatchException('<unknown>', coredata_version)
- if major_versions_differ(obj.version, coredata_version):
- raise MesonVersionMismatchException(obj.version, coredata_version)
- return obj
+ obj = pickle_load(fname, 'InstallData', InstallData)
+ assert isinstance(obj, InstallData), 'fo mypy'
+ return obj
def is_executable(path: str, follow_symlinks: bool = False) -> bool:
'''Checks whether any of the "x" bits are set in the source file mode.'''