From 683b7054f562dd84f5ed5279a81c2cd4ee5dcd61 Mon Sep 17 00:00:00 2001 From: ghintern Date: Fri, 17 Jan 2025 16:18:42 +0000 Subject: [PATCH] GP-5279: Fix null pointer exception in program tree save/restore --- .../core/programtree/ProgramTreePlugin.java | 6 +++-- .../programtree/ViewManagerPluginTest.java | 26 +++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/ProgramTreePlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/ProgramTreePlugin.java index 826f8dabf3..ccb7355e1a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/ProgramTreePlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/programtree/ProgramTreePlugin.java @@ -323,13 +323,15 @@ public class ProgramTreePlugin extends ProgramPlugin // // Update low-level component cache. We want to maintain the order of the tree views so // that the UI does not move around on the user. Use the view names as they are stored in - // the program to provide a consistent order. + // the program to provide a consistent order. Do not open trees the user has closed. // List list = new ArrayList<>(); String[] orderedTreeNames = currentProgram.getListing().getTreeNames(); for (String treeName : orderedTreeNames) { TreeViewProvider provider = providerMap.get(treeName); - list.add(provider); + if (provider != null) { // Provider will be null if this tree is not open in the view + list.add(provider); + } } componentProvider.treeViewsRestored(list); diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/programtree/ViewManagerPluginTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/programtree/ViewManagerPluginTest.java index 48a3ad9bed..8d95efce3d 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/programtree/ViewManagerPluginTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/programtree/ViewManagerPluginTest.java @@ -425,6 +425,32 @@ public class ViewManagerPluginTest extends AbstractGhidraHeadedIntegrationTest { assertTrue(provider.getCurrentView().hasSameAddresses(vps.getCurrentView())); } + @Test + public void testCloseSaveRestoreState() throws Exception { + // + // Test that we can close one of the program's trees and have the close correctly persist + // when saved and restored. This happens when a user closes a tree, then changes between + // program tabs. + // + final DockingActionIf closeAction = getAction(plugin, "Close Tree View"); + setCurrentViewProvider(DEFAULT_TREE_NAME); + performAction(closeAction); + + setCurrentViewProvider("Main Tree"); + AddressSetView set = provider.getCurrentView(); + + env.saveRestoreToolState(); + + String[] treeNames = program.getListing().getTreeNames(); + assertEquals(treeNames.length - 1, tabbedPane.getTabCount()); + + ViewProviderService vps = provider.getCurrentViewProvider(); + assertEquals("Main Tree", vps.getViewName()); + assertTrue(set.hasSameAddresses(provider.getCurrentView())); + assertTrue(set.hasSameAddresses(cb.getView())); + assertTrue(provider.getCurrentView().hasSameAddresses(vps.getCurrentView())); + } + @SuppressWarnings("unused") private JTextField findTextField(Container container) { Component[] c = container.getComponents();