This is an automated email from the ASF dual-hosted git repository.

mbien pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git


The following commit(s) were added to refs/heads/master by this push:
     new a208c991c1 Defensive guards against invalid code points in preferences.
     new 57335c4461 Merge pull request #6094 from mbien/invalid-code-point
a208c991c1 is described below

commit a208c991c13e9a77f429577d36016b5d770391ac
Author: Michael Bien <[email protected]>
AuthorDate: Mon Jun 19 09:02:16 2023 +0200

    Defensive guards against invalid code points in preferences.
    
    Made sure that OptionsExportModel is closing streams and zip files.
---
 .../tools/ant/module/api/IntrospectedInfo.java     |  15 +-
 .../maven/queries/MavenFileOwnerQueryImpl.java     |  15 +-
 .../src/org/netbeans/upgrade/CopyFiles.java        |  11 ++
 .../netbeans/core/windows/TopComponentTracker.java |   8 +-
 .../modules/options/export/OptionsExportModel.java | 175 +++++++++------------
 5 files changed, 114 insertions(+), 110 deletions(-)

diff --git 
a/extide/o.apache.tools.ant.module/src/org/apache/tools/ant/module/api/IntrospectedInfo.java
 
b/extide/o.apache.tools.ant.module/src/org/apache/tools/ant/module/api/IntrospectedInfo.java
index 728bc09cd6..eec4a7a3fc 100644
--- 
a/extide/o.apache.tools.ant.module/src/org/apache/tools/ant/module/api/IntrospectedInfo.java
+++ 
b/extide/o.apache.tools.ant.module/src/org/apache/tools/ant/module/api/IntrospectedInfo.java
@@ -674,22 +674,30 @@ public final class IntrospectedInfo {
             null | String[] enumTags: .enumTags=whenempty,always,never
              */
             Pattern p = 
Pattern.compile("(.+)\\.(supportsText|attrs\\.(.+)|subs\\.(.+)|enumTags)");
+            @Override
             public IntrospectedInfo load(Preferences node) {
                 IntrospectedInfo ii = new IntrospectedInfo();
                 try {
                     for (String k : node.keys()) {
-                        String v = node.get(k, null);
+                        String v;
+                        try {
+                            v = node.get(k, null);
+                        } catch (IllegalArgumentException ex) { // e.g invalid 
code point JDK-8075156
+                            LOG.log(Level.WARNING, "malformed key: {0}, pref 
path: {1}, msg: {2}",
+                                    new Object[] {k, node.absolutePath(), 
ex.getMessage()});
+                            continue;
+                        }
                         assert v != null : k;
                         String[] ss = k.split("\\.", 2);
                         if (ss.length != 2) {
-                            LOG.log(Level.WARNING, "malformed key: {0}", k);
+                            LOG.log(Level.WARNING, "malformed key: {0}, pref 
path: {1}", new Object[] {k, node.absolutePath()});
                             continue;
                         }
                         if (ss[0].equals("class")) {
                             Matcher m = p.matcher(ss[1]);
                             boolean match = m.matches();
                             if (!match) {
-                                LOG.log(Level.WARNING, "malformed key: {0}", 
k);
+                                LOG.log(Level.WARNING, "malformed key: {0}, 
pref path: {1}", new Object[] {k, node.absolutePath()});
                                 continue;
                             }
                             String c = m.group(1);
@@ -742,6 +750,7 @@ public final class IntrospectedInfo {
                 }
                 return ic;
             }
+            @Override
             public void store(Preferences node, IntrospectedInfo info) {
                 try {
                     node.clear();
diff --git 
a/java/maven/src/org/netbeans/modules/maven/queries/MavenFileOwnerQueryImpl.java
 
b/java/maven/src/org/netbeans/modules/maven/queries/MavenFileOwnerQueryImpl.java
index 996fd24526..98b87167f4 100644
--- 
a/java/maven/src/org/netbeans/modules/maven/queries/MavenFileOwnerQueryImpl.java
+++ 
b/java/maven/src/org/netbeans/modules/maven/queries/MavenFileOwnerQueryImpl.java
@@ -59,7 +59,6 @@ import org.netbeans.spi.project.FileOwnerQueryImplementation;
 import org.openide.filesystems.FileObject;
 import org.openide.filesystems.FileUtil;
 import org.openide.filesystems.URLMapper;
-import org.openide.util.Exceptions;
 import org.openide.util.Lookup;
 import org.openide.util.NbPreferences;
 import org.openide.util.Utilities;
@@ -75,9 +74,9 @@ public class MavenFileOwnerQueryImpl implements 
FileOwnerQueryImplementation {
     
     private final PropertyChangeListener projectListener;
     private final ProjectGroupChangeListener groupListener;
-    private final List<ChangeListener> listeners = new 
CopyOnWriteArrayList<ChangeListener>();
+    private final List<ChangeListener> listeners = new 
CopyOnWriteArrayList<>();
 
-    private static final AtomicReference<Preferences> prefs = new 
AtomicReference<Preferences>(NbPreferences.forModule(MavenFileOwnerQueryImpl.class).node(EXTERNAL_OWNERS));
+    private static final AtomicReference<Preferences> prefs = new 
AtomicReference<>(NbPreferences.forModule(MavenFileOwnerQueryImpl.class).node(EXTERNAL_OWNERS));
 
     private static final Logger LOG = 
Logger.getLogger(MavenFileOwnerQueryImpl.class.getName());
     
@@ -150,7 +149,15 @@ public class MavenFileOwnerQueryImpl implements 
FileOwnerQueryImplementation {
         String ownerString = owner.toString();
         try {
             for (String k : prefs().keys()) {
-                if (ownerString.equals(prefs().get(k, null))) {
+                String value;
+                try {
+                    value = prefs().get(k, null);
+                } catch (IllegalArgumentException ex) {
+                     // e.g invalid code point JDK-8075156
+                    LOG.log(Level.WARNING, "Invalid prefrences key at {0}, 
msg: {1}", new Object[] { prefs().absolutePath(), ex.getMessage() });
+                    continue;
+                }
+                if (ownerString.equals(value)) {
                     prefs().remove(k);
                     break;
                 }
diff --git a/nb/o.n.upgrader/src/org/netbeans/upgrade/CopyFiles.java 
b/nb/o.n.upgrader/src/org/netbeans/upgrade/CopyFiles.java
index 804fb3e980..f52ed87364 100644
--- a/nb/o.n.upgrader/src/org/netbeans/upgrade/CopyFiles.java
+++ b/nb/o.n.upgrader/src/org/netbeans/upgrade/CopyFiles.java
@@ -27,6 +27,7 @@ import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.io.Reader;
+import java.nio.file.Files;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map.Entry;
@@ -39,6 +40,8 @@ import org.netbeans.util.Util;
 import org.openide.filesystems.FileUtil;
 import org.openide.util.EditableProperties;
 
+import static java.nio.charset.StandardCharsets.UTF_8;
+
 /** Does copy of files according to include/exclude patterns.
  *
  * @author Jiri Skrivanek
@@ -136,6 +139,14 @@ final class CopyFiles extends Object {
      * @throws java.io.IOException if copying fails
      */
     private void copyFile(File sourceFile) throws IOException {
+
+        // invalid code point check JDK-8075156
+        if (sourceFile.getName().endsWith(".properties")
+                && new String(Files.readAllBytes(sourceFile.toPath()), 
UTF_8).indexOf('\u0000') != -1) {
+            LOGGER.log(Level.WARNING, "{0} contains invalid code points -> 
skipping", sourceFile);  //NOI18N
+            return;
+        }
+
         String relativePath = getRelativePath(sourceRoot, sourceFile);
         currentProperties = null;
         boolean includeFile = false;
diff --git 
a/platform/core.windows/src/org/netbeans/core/windows/TopComponentTracker.java 
b/platform/core.windows/src/org/netbeans/core/windows/TopComponentTracker.java
index 8f07395e32..61f50ddf60 100644
--- 
a/platform/core.windows/src/org/netbeans/core/windows/TopComponentTracker.java
+++ 
b/platform/core.windows/src/org/netbeans/core/windows/TopComponentTracker.java
@@ -73,7 +73,13 @@ public final class TopComponentTracker {
         Preferences prefs = getPreferences();
         try {
             for( String key : prefs.keys() ) {
-                boolean view = prefs.getBoolean( key, false );
+                boolean view;
+                try {
+                   view = prefs.getBoolean( key, false );
+                } catch (IllegalArgumentException ex) {
+                    
Logger.getLogger(TopComponentTracker.class.getName()).log(Level.INFO, "invalid 
preferences key", ex);
+                    continue; // e.g invalid code point JDK-8075156
+                }
                 if( view )
                     viewIds.add( key );
                 else
diff --git 
a/platform/options.api/src/org/netbeans/modules/options/export/OptionsExportModel.java
 
b/platform/options.api/src/org/netbeans/modules/options/export/OptionsExportModel.java
index 40c4f5daa4..7a48551aa5 100644
--- 
a/platform/options.api/src/org/netbeans/modules/options/export/OptionsExportModel.java
+++ 
b/platform/options.api/src/org/netbeans/modules/options/export/OptionsExportModel.java
@@ -18,6 +18,7 @@
  */
 package org.netbeans.modules.options.export;
 
+import java.io.BufferedInputStream;
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
 import java.io.File;
@@ -110,19 +111,19 @@ public final class OptionsExportModel {
     ArrayList<String> getEnabledItemsDuringExport(File importSource) {
         ArrayList<String> enabledItems = null;
         if (importSource.isFile()) { // importing from .zip file
-            try {
-                ZipFile zipFile = new ZipFile(importSource);
+            try (ZipFile zipFile = new ZipFile(importSource)) {
                 // Enumerate each entry
                 Enumeration<? extends ZipEntry> entries = zipFile.entries();
                 while (entries.hasMoreElements()) {
-                    ZipEntry zipEntry = (ZipEntry) entries.nextElement();
+                    ZipEntry zipEntry = entries.nextElement();
                     
if(zipEntry.getName().equals(OptionsExportModel.ENABLED_ITEMS_INFO)) {
-                        enabledItems = new ArrayList<String>();
-                        InputStream stream = zipFile.getInputStream(zipEntry);
-                        BufferedReader br = new BufferedReader(new 
InputStreamReader(stream, StandardCharsets.UTF_8));
-                        String strLine;
-                        while ((strLine = br.readLine()) != null) {
-                            enabledItems.add(strLine);
+                        enabledItems = new ArrayList<>();
+                        try (InputStream stream = 
zipFile.getInputStream(zipEntry);
+                             BufferedReader br = new BufferedReader(new 
InputStreamReader(stream, StandardCharsets.UTF_8));) {
+                            String strLine;
+                            while ((strLine = br.readLine()) != null) {
+                                enabledItems.add(strLine);
+                            }
                         }
                     }
                 }
@@ -158,20 +159,20 @@ public final class OptionsExportModel {
     double getBuildNumberDuringExport(File importSource) {
         String buildNumber = null;
         if (importSource.isFile()) { // importing from .zip file
-            try {
-                ZipFile zipFile = new ZipFile(importSource);
+            try (ZipFile zipFile = new ZipFile(importSource)) {
                 // Enumerate each entry
                 Enumeration<? extends ZipEntry> entries = zipFile.entries();
                 while (entries.hasMoreElements()) {
                     ZipEntry zipEntry = (ZipEntry) entries.nextElement();
                     if 
(zipEntry.getName().equals(OptionsExportModel.BUILD_INFO)) {
-                        InputStream stream = zipFile.getInputStream(zipEntry);
-                        BufferedReader br = new BufferedReader(new 
InputStreamReader(stream, StandardCharsets.UTF_8));
-                        String strLine;
-                        while ((strLine = br.readLine()) != null) {
-                            buildNumber = parseBuildNumber(strLine);
-                            if(buildNumber != null) {
-                                break; // successfully parsed build number, no 
need to continue
+                        try (InputStream stream = 
zipFile.getInputStream(zipEntry);
+                             BufferedReader br = new BufferedReader(new 
InputStreamReader(stream, StandardCharsets.UTF_8));)  {
+                            String strLine;
+                            while ((strLine = br.readLine()) != null) {
+                                buildNumber = parseBuildNumber(strLine);
+                                if(buildNumber != null) {
+                                    break; // successfully parsed build 
number, no need to continue
+                                }
                             }
                         }
                     }
@@ -304,24 +305,16 @@ public final class OptionsExportModel {
         try {
             ensureParent(targetZipFile);
             // Create the ZIP file
-            zipOutputStream = new 
ZipOutputStream(createOutputStream(targetZipFile));
-            copyFiles();
-            createEnabledItemsInfo(zipOutputStream, enabledItems);
-            createProductInfo(zipOutputStream);
-            // Complete the ZIP file
-            zipOutputStream.close();
+            try (ZipOutputStream out = new 
ZipOutputStream(createOutputStream(targetZipFile))) {
+                zipOutputStream = out;
+                copyFiles();
+                createEnabledItemsInfo(out, enabledItems);
+                createProductInfo(out);
+            }
         } catch (IOException ex) {
             Exceptions.attachLocalizedMessage(ex,
                     NbBundle.getMessage(OptionsExportModel.class, 
"OptionsExportModel.export.zip.error", targetZipFile));
             Exceptions.printStackTrace(ex);
-        } finally {
-            if (zipOutputStream != null) {
-                try {
-                    zipOutputStream.close();
-                } catch (IOException ex) {
-                    // ignore
-                }
-            }
         }
     }
 
@@ -748,21 +741,31 @@ public final class OptionsExportModel {
      */
     private void copyZipFile() throws IOException {
         // Open the ZIP file
-        ZipFile zipFile = new ZipFile(source);
-        try {
+        try (ZipFile zipFile = new ZipFile(source)) {
             // Enumerate each entry
             Enumeration<? extends ZipEntry> entries = zipFile.entries();
             while (entries.hasMoreElements()) {
                 ZipEntry zipEntry = entries.nextElement();
-                if (!zipEntry.isDirectory()) {
+                if (!zipEntry.isDirectory() && !checkIntegrity(zipEntry)) {
                     copyFile(zipEntry.getName());
                 }
             }
-        } finally {
-            if (zipFile != null) {
-                zipFile.close();
+        }
+    }
+
+    private boolean checkIntegrity(ZipEntry entry) throws IOException {
+        if (entry.getName().endsWith(".properties")) {
+            try (ZipFile zip = new ZipFile(source);
+                 BufferedReader reader = new BufferedReader(new 
InputStreamReader(zip.getInputStream(entry), StandardCharsets.UTF_8))) {
+                // invalid code point check JDK-8075156
+                boolean corrupted = reader.lines().anyMatch(l -> 
l.indexOf('\u0000') != -1);
+                if (corrupted) {
+                    LOGGER.log(Level.WARNING, "ignoring corrupted properties 
file at {0}", entry.getName());
+                }
+                return corrupted;
             }
         }
+        return true;
     }
 
     /** Copy given folder to target userdir or zip file obeying 
include/exclude patterns.
@@ -964,18 +967,12 @@ public final class OptionsExportModel {
             // Complete the entry
             zipOutputStream.closeEntry();
         } else {  // import to userdir
-            OutputStream out = null;
             File targetFile = new File(targetUserdir, relativePath);
             LOGGER.log(Level.FINE, "Path: {0}", relativePath);  //NOI18N
             if (includeKeys.isEmpty() && excludeKeys.isEmpty()) {
                 // copy entire file
-                try {
-                    out = createOutputStream(targetFile);
+                try (OutputStream out = createOutputStream(targetFile)) {
                     copyFile(relativePath, out);
-                } finally {
-                    if (out != null) {
-                        out.close();
-                    }
                 }
             } else {
                 mergeProperties(relativePath, includeKeys, excludeKeys);
@@ -999,29 +996,17 @@ public final class OptionsExportModel {
             return;
         }
         EditableProperties targetProperties = new EditableProperties(false);
-        InputStream in = null;
         File targetFile = new File(targetUserdir, relativePath);
-        try {
-            if (targetFile.exists()) {
-                in = new FileInputStream(targetFile);
+        if (targetFile.exists()) {
+            try (InputStream in = new FileInputStream(targetFile)) {
                 targetProperties.load(in);
             }
-        } finally {
-            if (in != null) {
-                in.close();
-            }
         }
         for (Entry<String, String> entry : currentProperties.entrySet()) {
             targetProperties.put(entry.getKey(), entry.getValue());
         }
-        OutputStream out = null;
-        try {
-            out = createOutputStream(targetFile);
+        try (OutputStream out = createOutputStream(targetFile)) {
             targetProperties.store(out);
-        } finally {
-            if (out != null) {
-                out.close();
-            }
         }
     }
 
@@ -1055,14 +1040,8 @@ public final class OptionsExportModel {
      */
     private EditableProperties getProperties(String relativePath) throws 
IOException {
         EditableProperties properties = new EditableProperties(false);
-        InputStream in = null;
-        try {
-            in = getInputStream(relativePath);
+        try (InputStream in = getInputStream(relativePath)) {
             properties.load(in);
-        } finally {
-            if (in != null) {
-                in.close();
-            }
         }
         return properties;
     }
@@ -1075,29 +1054,35 @@ public final class OptionsExportModel {
     private InputStream getInputStream(String relativePath) throws IOException 
{
         if (source.isFile()) {
             //zip file
-            ZipFile zipFile = new ZipFile(source);
-            ZipEntry zipEntry = zipFile.getEntry(relativePath);
-            return zipFile.getInputStream(zipEntry);
+            return singleEntryZipStream(relativePath);
         } else {
             // userdir
             return new FileInputStream(new File(source, relativePath));
         }
     }
 
+    private InputStream singleEntryZipStream(String relativePath) throws 
IOException {
+        final ZipFile zipFile = new ZipFile(source);
+        return new 
BufferedInputStream(zipFile.getInputStream(zipFile.getEntry(relativePath))) {
+            @Override
+            public void close() throws IOException {
+                try {
+                    super.close();
+                } finally {
+                    zipFile.close();
+                }
+            }
+        };
+    }
+
     /** Copy file from relative path in zip file or userdir to target 
OutputStream.
      * @param relativePath relative path
      * @param out output stream
      * @throws java.io.IOException if copying fails
      */
     private void copyFile(String relativePath, OutputStream out) throws 
IOException {
-        InputStream in = null;
-        try {
-            in = getInputStream(relativePath);
+        try (InputStream in = getInputStream(relativePath)) {
             FileUtil.copy(in, out);
-        } finally {
-            if (in != null) {
-                in.close();
-            }
         }
     }
 
@@ -1117,15 +1102,16 @@ public final class OptionsExportModel {
      * @throws java.io.IOException
      */
     static List<String> listZipFile(File file) throws IOException {
-        List<String> relativePaths = new ArrayList<String>();
+        List<String> relativePaths = new ArrayList<>();
         // Open the ZIP file
-        ZipFile zipFile = new ZipFile(file);
-        // Enumerate each entry
-        Enumeration<? extends ZipEntry> entries = zipFile.entries();
-        while (entries.hasMoreElements()) {
-            ZipEntry zipEntry = (ZipEntry) entries.nextElement();
-            if (!zipEntry.isDirectory()) {
-                relativePaths.add(zipEntry.getName());
+        try (ZipFile zipFile = new ZipFile(file)) {
+            // Enumerate each entry
+            Enumeration<? extends ZipEntry> entries = zipFile.entries();
+            while (entries.hasMoreElements()) {
+                ZipEntry zipEntry = entries.nextElement();
+                if (!zipEntry.isDirectory()) {
+                    relativePaths.add(zipEntry.getName());
+                }
             }
         }
         return relativePaths;
@@ -1139,35 +1125,20 @@ public final class OptionsExportModel {
      */
     static void createZipFile(File targetFile, File sourceDir, List<String> 
relativePaths) throws IOException {
         ensureParent(targetFile);
-        ZipOutputStream out = null;
-        try {
-            // Create the ZIP file
-            out = new ZipOutputStream(createOutputStream(targetFile));
+        try (ZipOutputStream out = new 
ZipOutputStream(createOutputStream(targetFile))) {
             // Compress the files
             for (String relativePath : relativePaths) {
                 LOGGER.finest("Adding to zip: " + relativePath);  //NOI18N
                 // Add ZIP entry to output stream.
                 out.putNextEntry(new ZipEntry(relativePath));
                 // Transfer bytes from the file to the ZIP file
-                FileInputStream in = null;
-                try {
-                    in = new FileInputStream(new File(sourceDir, 
relativePath));
+                try (FileInputStream in = new FileInputStream(new 
File(sourceDir, relativePath))) {
                     FileUtil.copy(in, out);
-                } finally {
-                    if (in != null) {
-                        in.close();
-                    }
                 }
                 // Complete the entry
                 out.closeEntry();
             }
             createProductInfo(out);
-            // Complete the ZIP file
-            out.close();
-        } finally {
-            if (out != null) {
-                out.close();
-            }
         }
     }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists

Reply via email to