diff --git a/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemePreferences.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemePreferences.java index 6c8f84d556..75edc6f2ec 100644 --- a/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemePreferences.java +++ b/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemePreferences.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -47,8 +47,15 @@ public class ThemePreferences { else if (themeId.startsWith(DiscoverableGTheme.CLASS_PREFIX)) { String className = themeId.substring(DiscoverableGTheme.CLASS_PREFIX.length()); try { - Class forName = Class.forName(className); - return (GTheme) forName.getDeclaredConstructor().newInstance(); + ClassLoader loader = getClass().getClassLoader(); + Class clazz = Class.forName(className, false, loader); + if (!GTheme.class.isAssignableFrom(clazz)) { + Msg.showError(GTheme.class, null, "Can't Load Previous Theme", + "Theme class name does not point to a GTheme instance: " + className); + return ThemeManager.getDefaultTheme(); + } + + return (GTheme) clazz.getDeclaredConstructor().newInstance(); } catch (Exception e) { Msg.showError(GTheme.class, null, "Can't Load Previous Theme", diff --git a/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeReader.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeReader.java index eae40ccdd3..e6db3bd083 100644 --- a/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeReader.java +++ b/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeReader.java @@ -135,7 +135,15 @@ class ThemeReader extends AbstractThemeReader { int indexOf = path.indexOf("images/"); if (indexOf < 0) { Msg.error(this, "Unknown file: " + path); + return; } + + if (path.contains("..")) { + // We write the theme images to an 'images' dir under the zip root. No need for '..' + Msg.error(this, "Zip paths with '..' not allowed: " + path); + return; + } + String relativePath = path.substring(indexOf, path.length()); File dir = Application.getUserSettingsDirectory(); File iconFile = new File(dir, relativePath); diff --git a/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeWriter.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeWriter.java index 45f49ed5e6..bfee835d31 100644 --- a/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeWriter.java +++ b/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeWriter.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -122,12 +122,17 @@ public class ThemeWriter { } private void copyToZipFile(String dir, File iconFile, ZipOutputStream zos) throws IOException { + // dir: MyTheme.theme/ + // zip name: MyTheme.theme/images/myicon.png ZipEntry entry = new ZipEntry(dir + "images/" + iconFile.getName()); zos.putNextEntry(entry); Files.copy(iconFile.toPath(), zos); } private void saveThemeFileToZip(String dir, ZipOutputStream zos) throws IOException { + // dir: MyTheme.theme/ + // theme name: MyTheme + // zip name: MyTheme.theme/MyTheme.theme ZipEntry entry = new ZipEntry(dir + theme.getName() + ".theme"); zos.putNextEntry(entry); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(zos));