Skip to content

Commit

Permalink
Do not allow third parties to provide Netty's native libraries
Browse files Browse the repository at this point in the history
Fixes netty/netty-tcnative#681
Throw an exception when there are multiple netty-tcnative-** libraries with the same path in the classpath
  • Loading branch information
martin-g committed Nov 24, 2021
1 parent 2b4ac36 commit 4659769
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,16 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UncheckedIOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Enumeration;
import java.util.List;
import java.util.Set;

Expand Down Expand Up @@ -94,6 +97,7 @@ public static void loadFirstAvailable(ClassLoader loader, String... names) {
for (String name : names) {
try {
load(name, loader);
logger.debug("Loaded library with name '{}'", name);
return;
} catch (Throwable t) {
suppressed.add(t);
Expand Down Expand Up @@ -145,22 +149,13 @@ public static void load(String originalName, ClassLoader loader) {
InputStream in = null;
OutputStream out = null;
File tmpFile = null;
URL url;
if (loader == null) {
url = ClassLoader.getSystemResource(path);
} else {
url = loader.getResource(path);
}
URL url = getResource(path, loader);
try {
if (url == null) {
if (PlatformDependent.isOsx()) {
String fileName = path.endsWith(".jnilib") ? NATIVE_RESOURCE_HOME + "lib" + name + ".dynlib" :
NATIVE_RESOURCE_HOME + "lib" + name + ".jnilib";
if (loader == null) {
url = ClassLoader.getSystemResource(fileName);
} else {
url = loader.getResource(fileName);
}
url = getResource(fileName, loader);
if (url == null) {
FileNotFoundException fnf = new FileNotFoundException(fileName);
ThrowableUtil.addSuppressedAndClear(fnf, suppressed);
Expand Down Expand Up @@ -236,6 +231,28 @@ public static void load(String originalName, ClassLoader loader) {
}
}

private static URL getResource(String path, ClassLoader loader) {
Enumeration<URL> urls;
try {
if (loader == null) {
urls = ClassLoader.getSystemResources(path);
} else {
urls = loader.getResources(path);
}
} catch (IOException iox) {
throw new RuntimeException("An error occurred while getting the resources for " + path, iox);
}

URL url = null;
List<URL> urlsList = Collections.list(urls);
if (urlsList.size() == 1) {
url = urlsList.get(0);
} else if (urlsList.size() > 1) {
throw new IllegalStateException("Multiple resources found for '" + path + "': " + urlsList);
}
return url;
}

static void tryPatchShadedLibraryIdAndSign(File libraryFile, String originalName) {
String newId = new String(generateUniqueId(originalName.length()), CharsetUtil.UTF_8);
if (!tryExec("install_name_tool -id " + newId + " " + libraryFile.getAbsolutePath())) {
Expand Down Expand Up @@ -288,7 +305,7 @@ private static void loadLibrary(final ClassLoader loader, final String name, fin
Throwable suppressed = null;
try {
try {
// Make sure the helper is belong to the target ClassLoader.
// Make sure the helper belongs to the target ClassLoader.
final Class<?> newHelper = tryToLoadClass(loader, NativeLibraryUtil.class);
loadLibraryByHelper(newHelper, name, absolute);
logger.debug("Successfully loaded the library {}", name);
Expand Down
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@

import org.junit.jupiter.api.Test;

import java.io.File;
import java.io.FileNotFoundException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.UUID;

import static org.junit.jupiter.api.Assertions.assertTrue;
Expand Down Expand Up @@ -51,6 +55,21 @@ public void testFileNotFoundWithNullClassLoader() {
}
}

@Test
void testMultipleResourcesInTheClassLoader() throws MalformedURLException {
URL url1 = new File("src/test/data/NativeLibraryLoader/1").toURI().toURL();
URL url2 = new File("src/test/data/NativeLibraryLoader/2").toURI().toURL();
URLClassLoader loader = new URLClassLoader(new URL[] {url1, url2});
String resourceName = "test";
try {
NativeLibraryLoader.load(resourceName, loader);
fail("Expected IllegalStateException because there are more than one resources with the same name");
} catch (IllegalStateException ise) {
assertTrue(ise.getMessage()
.contains("Multiple resources found for 'META-INF/native/lib" + resourceName + ".so'"));
}
}

@SuppressJava6Requirement(reason = "uses Java 7+ Throwable#getSuppressed but is guarded by version checks")
private static void verifySuppressedException(UnsatisfiedLinkError error,
Class<?> expectedSuppressedExceptionClass) {
Expand Down

0 comments on commit 4659769

Please sign in to comment.