You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ja...@apache.org on 2023/12/19 07:54:51 UTC
(lucene-solr) branch branch_8_11 updated: SOLR-16949: Fix inputstream leaks
This is an automated email from the ASF dual-hosted git repository.
janhoy pushed a commit to branch branch_8_11
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git
The following commit(s) were added to refs/heads/branch_8_11 by this push:
new 6c8f24eb9e3 SOLR-16949: Fix inputstream leaks
6c8f24eb9e3 is described below
commit 6c8f24eb9e3fe1cb19058173f2e221de3febfeda
Author: Jan Høydahl <ja...@apache.org>
AuthorDate: Mon Dec 18 09:32:33 2023 +0100
SOLR-16949: Fix inputstream leaks
---
.../org/apache/solr/util/FileTypeMagicUtil.java | 72 +++++++++++++++-------
.../apache/solr/util/FileTypeMagicUtilTest.java | 58 ++++++++---------
2 files changed, 81 insertions(+), 49 deletions(-)
diff --git a/solr/core/src/java/org/apache/solr/util/FileTypeMagicUtil.java b/solr/core/src/java/org/apache/solr/util/FileTypeMagicUtil.java
index cfc2e965537..cc66fced2b8 100644
--- a/solr/core/src/java/org/apache/solr/util/FileTypeMagicUtil.java
+++ b/solr/core/src/java/org/apache/solr/util/FileTypeMagicUtil.java
@@ -20,7 +20,6 @@ package org.apache.solr.util;
import com.j256.simplemagic.ContentInfo;
import com.j256.simplemagic.ContentInfoUtil;
import com.j256.simplemagic.ContentType;
-import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.FileVisitResult;
@@ -58,22 +57,18 @@ public class FileTypeMagicUtil implements ContentInfoUtil.ErrorCallBack {
public static void assertConfigSetFolderLegal(Path confPath) throws IOException {
Files.walkFileTree(confPath, new SimpleFileVisitor<Path>() {
@Override
- public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
// Read first 100 bytes of the file to determine the mime type
- try(InputStream fileStream = Files.newInputStream(file)) {
- byte[] bytes = new byte[100];
- fileStream.read(bytes);
- if (FileTypeMagicUtil.isFileForbiddenInConfigset(bytes)) {
- throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
- String.format(Locale.ROOT, "Not uploading file %s to configset, as it matched the MAGIC signature of a forbidden mime type %s",
- file, FileTypeMagicUtil.INSTANCE.guessMimeType(bytes)));
- }
- return FileVisitResult.CONTINUE;
+ if (FileTypeMagicUtil.isFileForbiddenInConfigset(file)) {
+ throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
+ String.format(Locale.ROOT, "Not uploading file %s to configset, as it matched the MAGIC signature of a forbidden mime type %s",
+ file, FileTypeMagicUtil.INSTANCE.guessMimeType(file)));
}
+ return FileVisitResult.CONTINUE;
}
@Override
- public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
+ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
if (SKIP_FOLDERS.contains(dir.getFileName().toString())) return FileVisitResult.SKIP_SUBTREE;
return FileVisitResult.CONTINUE;
@@ -81,19 +76,29 @@ public class FileTypeMagicUtil implements ContentInfoUtil.ErrorCallBack {
});
}
+ /**
+ * Guess the mime type of file based on its magic number.
+ *
+ * @param file file to check
+ * @return string with content-type or "application/octet-stream" if unknown
+ */
+ public String guessMimeType(Path file) {
+ try {
+ return guessTypeFallbackToOctetStream(util.findMatch(file.toFile()));
+ } catch (IOException e) {
+ throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e);
+ }
+ }
+
/**
* Guess the mime type of file based on its magic number.
*
* @param stream input stream of the file
* @return string with content-type or "application/octet-stream" if unknown
*/
- public String guessMimeType(InputStream stream) {
+ String guessMimeType(InputStream stream) {
try {
- ContentInfo info = util.findMatch(stream);
- if (info == null) {
- return ContentType.OTHER.getMimeType();
- }
- return info.getContentType().getMimeType();
+ return guessTypeFallbackToOctetStream(util.findMatch(stream));
} catch (IOException e) {
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e);
}
@@ -106,7 +111,7 @@ public class FileTypeMagicUtil implements ContentInfoUtil.ErrorCallBack {
* @return string with content-type or "application/octet-stream" if unknown
*/
public String guessMimeType(byte[] bytes) {
- return guessMimeType(new ByteArrayInputStream(bytes));
+ return guessTypeFallbackToOctetStream(util.findMatch(bytes));
}
@Override
@@ -117,6 +122,24 @@ public class FileTypeMagicUtil implements ContentInfoUtil.ErrorCallBack {
e);
}
+ /**
+ * Determine forbidden file type based on magic bytes matching of the file itself. Forbidden types
+ * are:
+ *
+ * <ul>
+ * <li><code>application/x-java-applet</code>: java class file
+ * <li><code>application/zip</code>: jar or zip archives
+ * <li><code>application/x-tar</code>: tar archives
+ * <li><code>text/x-shellscript</code>: shell or bash script
+ * </ul>
+ *
+ * @param file file to check
+ * @return true if file is among the forbidden mime-types
+ */
+ public static boolean isFileForbiddenInConfigset(Path file) {
+ return forbiddenTypes.contains(FileTypeMagicUtil.INSTANCE.guessMimeType(file));
+ }
+
/**
* Determine forbidden file type based on magic bytes matching of the file itself. Forbidden types
* are:
@@ -131,7 +154,7 @@ public class FileTypeMagicUtil implements ContentInfoUtil.ErrorCallBack {
* @param fileStream stream from the file content
* @return true if file is among the forbidden mime-types
*/
- public static boolean isFileForbiddenInConfigset(InputStream fileStream) {
+ static boolean isFileForbiddenInConfigset(InputStream fileStream) {
return forbiddenTypes.contains(FileTypeMagicUtil.INSTANCE.guessMimeType(fileStream));
}
@@ -144,7 +167,7 @@ public class FileTypeMagicUtil implements ContentInfoUtil.ErrorCallBack {
public static boolean isFileForbiddenInConfigset(byte[] bytes) {
if (bytes == null || bytes.length == 0)
return false; // A ZK znode may be a folder with no content
- return isFileForbiddenInConfigset(new ByteArrayInputStream(bytes));
+ return forbiddenTypes.contains(FileTypeMagicUtil.INSTANCE.guessMimeType(bytes));
}
private static final Set<String> forbiddenTypes =
@@ -155,4 +178,11 @@ public class FileTypeMagicUtil implements ContentInfoUtil.ErrorCallBack {
"application/x-java-applet,application/zip,application/x-tar,text/x-shellscript")
.split(",")));
+ private String guessTypeFallbackToOctetStream(ContentInfo contentInfo) {
+ if (contentInfo == null) {
+ return ContentType.OTHER.getMimeType();
+ } else {
+ return contentInfo.getContentType().getMimeType();
+ }
+ }
}
diff --git a/solr/core/src/test/org/apache/solr/util/FileTypeMagicUtilTest.java b/solr/core/src/test/org/apache/solr/util/FileTypeMagicUtilTest.java
index b8e9a35a3d9..5c02528a7f4 100644
--- a/solr/core/src/test/org/apache/solr/util/FileTypeMagicUtilTest.java
+++ b/solr/core/src/test/org/apache/solr/util/FileTypeMagicUtilTest.java
@@ -17,38 +17,40 @@
package org.apache.solr.util;
+import java.io.IOException;
+import java.io.InputStream;
import org.apache.solr.SolrTestCaseJ4;
public class FileTypeMagicUtilTest extends SolrTestCaseJ4 {
- public void testGuessMimeType() {
- assertEquals(
- "application/x-java-applet",
- FileTypeMagicUtil.INSTANCE.guessMimeType(
- FileTypeMagicUtil.class.getResourceAsStream("/magic/HelloWorldJavaClass.class.bin")));
- assertEquals(
- "application/zip",
- FileTypeMagicUtil.INSTANCE.guessMimeType(
- FileTypeMagicUtil.class.getResourceAsStream(
- "/runtimecode/containerplugin.v.1.jar.bin")));
- assertEquals(
- "application/x-tar",
- FileTypeMagicUtil.INSTANCE.guessMimeType(
- FileTypeMagicUtil.class.getResourceAsStream("/magic/hello.tar.bin")));
- assertEquals(
- "text/x-shellscript",
- FileTypeMagicUtil.INSTANCE.guessMimeType(
- FileTypeMagicUtil.class.getResourceAsStream("/magic/shell.sh.txt")));
+ public void testGuessMimeType() throws IOException {
+ assertResourceMimeType("application/x-java-applet", "/magic/HelloWorldJavaClass.class.bin");
+ assertResourceMimeType("application/zip", "/runtimecode/containerplugin.v.1.jar.bin");
+ assertResourceMimeType("application/x-tar", "/magic/hello.tar.bin");
+ assertResourceMimeType("text/x-shellscript", "/magic/shell.sh.txt");
}
- public void testIsFileForbiddenInConfigset() {
- assertTrue(
- FileTypeMagicUtil.isFileForbiddenInConfigset(
- FileTypeMagicUtil.class.getResourceAsStream("/magic/HelloWorldJavaClass.class.bin")));
- assertTrue(
- FileTypeMagicUtil.isFileForbiddenInConfigset(
- FileTypeMagicUtil.class.getResourceAsStream("/magic/shell.sh.txt")));
- assertFalse(
- FileTypeMagicUtil.isFileForbiddenInConfigset(
- FileTypeMagicUtil.class.getResourceAsStream("/magic/plain.txt")));
+ public void testIsFileForbiddenInConfigset() throws IOException {
+ assertResourceForbiddenInConfigset("/magic/HelloWorldJavaClass.class.bin");
+ assertResourceForbiddenInConfigset("/magic/shell.sh.txt");
+ assertResourceAllowedInConfigset("/magic/plain.txt");
+ }
+
+ private void assertResourceMimeType(String mimeType, String resourcePath) throws IOException {
+ try (InputStream stream =
+ FileTypeMagicUtil.class.getResourceAsStream("/magic/HelloWorldJavaClass.class.bin")) {
+ assertEquals("application/x-java-applet", FileTypeMagicUtil.INSTANCE.guessMimeType(stream));
+ }
+ }
+
+ private void assertResourceForbiddenInConfigset(String resourcePath) throws IOException {
+ try (InputStream stream = FileTypeMagicUtil.class.getResourceAsStream(resourcePath)) {
+ assertTrue(FileTypeMagicUtil.isFileForbiddenInConfigset(stream));
+ }
+ }
+
+ private void assertResourceAllowedInConfigset(String resourcePath) throws IOException {
+ try (InputStream stream = FileTypeMagicUtil.class.getResourceAsStream(resourcePath)) {
+ assertFalse(FileTypeMagicUtil.isFileForbiddenInConfigset(stream));
+ }
}
}