From 9afb5da5ada039da0a8386846717b87a6dfe9eba Mon Sep 17 00:00:00 2001 From: nichinichisou Date: Thu, 15 Oct 2026 00:04:40 +0800 Subject: [PATCH] fix(SerializedFile): load dependencies as dependencies load_dependencies called environment.load_file(path, True), which passes True as the parent argument, so is_dependency stayed False. The externals of a file, also the ones loaded while get_resource_data looks for a resource file, were therefore treated as files the user loaded: their objects showed up in Environment.objects next to the objects of the loaded file. is_dependency=True is now passed by keyword, so dependencies resolve references and resources but are no longer listed as objects. tests/test_dependencies.py writes two copies of a sample serialized file to a temporary directory, the first listing the second as an external, and checks that loading the dependency leaves Environment.objects as it was. --- UnityPy/files/SerializedFile.py | 4 ++-- tests/test_dependencies.py | 39 +++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 tests/test_dependencies.py diff --git a/UnityPy/files/SerializedFile.py b/UnityPy/files/SerializedFile.py index 309dd106..9ce1342d 100644 --- a/UnityPy/files/SerializedFile.py +++ b/UnityPy/files/SerializedFile.py @@ -407,14 +407,14 @@ def load_dependencies(self, possible_dependencies: Optional[list] = None): where the target file is not listed as external. """ for file_id in self.externals: - self.environment.load_file(file_id.path, True) + self.environment.load_file(file_id.path, is_dependency=True) if possible_dependencies is None: return for dependency in possible_dependencies: try: - self.environment.load_file(dependency, True) + self.environment.load_file(dependency, is_dependency=True) except FileNotFoundError: pass diff --git a/tests/test_dependencies.py b/tests/test_dependencies.py new file mode 100644 index 00000000..864862b8 --- /dev/null +++ b/tests/test_dependencies.py @@ -0,0 +1,39 @@ +import os + +import UnityPy +from UnityPy.files import SerializedFile +from UnityPy.files.SerializedFile import FileIdentifier + +SAMPLES = os.path.join(os.path.dirname(os.path.abspath(__file__)), "samples") + + +def write_serialized_files(directory): + """main.assets, which lists dep.assets as an external, and dep.assets, both copies of a sample file""" + env = UnityPy.load(os.path.join(SAMPLES, "banner_1")) + bundle = next(iter(env.files.values())) + serialized = next(f for f in bundle.files.values() if isinstance(f, SerializedFile)) + with open(os.path.join(directory, "dep.assets"), "wb") as f: + f.write(serialized.save()) + + external = object.__new__(FileIdentifier) + external.path = "dep.assets" + external.temp_empty = "" + external.guid = bytes(16) + external.type = 0 + serialized.externals.append(external) + with open(os.path.join(directory, "main.assets"), "wb") as f: + f.write(serialized.save()) + return len(serialized.objects) + + +def test_dependencies_are_not_listed_as_objects(tmp_path): + object_count = write_serialized_files(str(tmp_path)) + env = UnityPy.load(os.path.join(str(tmp_path), "main.assets")) + assert len(env.objects) == object_count + main = next(iter(env.files.values())) + + main.load_dependencies() + dependency = env.get_cab("dep.assets") + assert isinstance(dependency, SerializedFile) + assert dependency.is_dependency + assert len(env.objects) == object_count