GP-6288: PyGhidra now by default restores sys.modules each time a script

is run, or the interactive interpreter is reset.

Can be disabled by uncommenting
"#VMARGS=-Dpyghidra.sys.modules.restore.disable=true" in
launch.properties if its found to cause problems.
This commit is contained in:
Ryan Kurtz
2026-01-06 06:11:09 -05:00
parent 78a9822a99
commit d5b9582fd5
3 changed files with 11 additions and 5 deletions

View File

@@ -30,6 +30,7 @@ from ghidra.pyghidra import PyGhidraScriptProvider, PyGhidraPlugin
from ghidra.pyghidra.interpreter import PyGhidraConsole
from ghidra.util.task import TaskMonitor
from java.io import BufferedReader, InputStreamReader # type:ignore @UnresolvedImport
from java.lang import Boolean # type:ignore @UnresolvedImport
from java.lang import String # type:ignore @UnresolvedImport
from java.lang import Thread as JThread # type:ignore @UnresolvedImport
from java.util import Collections # type:ignore @UnresolvedImport
@@ -171,6 +172,7 @@ class PyConsole(InteractiveConsole):
self._script.set(state, ScriptControls(console, TaskMonitor.DUMMY))
self._state = ConsoleState.RESET
self._completer = PythonCodeCompleter(self)
self._orig_modules = sys.modules.copy()
def raw_input(self, prompt=''):
self._console.setPrompt(prompt)
@@ -238,6 +240,11 @@ class PyConsole(InteractiveConsole):
# this resets the locals, and gets a new code compiler
super().__init__(locals=PyGhidraScript(self._script))
# restore sys.modules to its original state
if not Boolean.getBoolean("pyghidra.sys.modules.restore.disable"):
for k in list(set(sys.modules) - set(self._orig_modules)):
sys.modules.pop(k, None)
@property
def name(self) -> str:

View File

@@ -270,7 +270,7 @@ class PyGhidraScript(dict):
finally:
sys.argv = orig_argv
if Boolean.getBoolean("pyghidra.sys.modules.restore"):
if not Boolean.getBoolean("pyghidra.sys.modules.restore.disable"):
for k in list(set(sys.modules) - set(orig_modules)):
sys.modules.pop(k, None)

View File

@@ -159,7 +159,6 @@ VMARGS=--enable-native-access=ALL-UNNAMED
# Disables the loaders echoing their message log to the application.log file
#VMARGS=-Ddisable.loader.logging=true
# Restores sys.modules to its prior state after a PyGhidra script is run so the next time the script
# is run, it freshly reloads all of its imported modules again. This is experimental and should only
# be enabled if necessary.
#VMARGS=-Dpyghidra.sys.modules.restore=true
# Prevents PyGhidra from restoring sys.modules to its original state after a PyGhidra script is run.
# Used to help debug potential issues that might arise from mucking with sys.modules.
#VMARGS=-Dpyghidra.sys.modules.restore.disable=true