8300491: SymbolLookup::libraryLookup accepts strings with terminators

Reviewed-by: psandoz
This commit is contained in:
Maurizio Cimadamore 2023-05-25 15:22:27 +00:00
parent 48d21bd089
commit 534de6d8ae
6 changed files with 38 additions and 0 deletions

View File

@ -28,6 +28,7 @@ package java.lang.foreign;
import jdk.internal.access.JavaLangAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.foreign.MemorySessionImpl;
import jdk.internal.foreign.Utils;
import jdk.internal.javac.PreviewFeature;
import jdk.internal.loader.BuiltinClassLoader;
import jdk.internal.loader.NativeLibrary;
@ -192,6 +193,7 @@ public interface SymbolLookup {
}
return name -> {
Objects.requireNonNull(name);
if (Utils.containsNullChars(name)) return Optional.empty();
JavaLangAccess javaLangAccess = SharedSecrets.getJavaLangAccess();
// note: ClassLoader::findNative supports a null loader
long addr = javaLangAccess.findNative(loader, name);
@ -229,6 +231,9 @@ public interface SymbolLookup {
@CallerSensitive
static SymbolLookup libraryLookup(String name, Arena arena) {
Reflection.ensureNativeAccess(Reflection.getCallerClass(), SymbolLookup.class, "libraryLookup");
if (Utils.containsNullChars(name)) {
throw new IllegalArgumentException("Cannot open library: " + name);
}
return libraryLookup(name, RawNativeLibraries::load, arena);
}
@ -279,6 +284,7 @@ public interface SymbolLookup {
});
return name -> {
Objects.requireNonNull(name);
if (Utils.containsNullChars(name)) return Optional.empty();
long addr = library.find(name);
return addr == 0L ?
Optional.empty() :

View File

@ -95,6 +95,7 @@ public final class SystemLookup implements SymbolLookup {
final SymbolLookup finalLookup = lookup;
lookup = name -> {
Objects.requireNonNull(name);
if (Utils.containsNullChars(name)) return Optional.empty();
return finalLookup.find(name).or(() -> fallbackLookup.apply(name));
};
}
@ -106,6 +107,7 @@ public final class SystemLookup implements SymbolLookup {
NativeLibrary lib = loader.apply(RawNativeLibraries.newInstance(MethodHandles.lookup()));
return name -> {
Objects.requireNonNull(name);
if (Utils.containsNullChars(name)) return Optional.empty();
try {
long addr = lib.lookup(name);
return addr == 0 ?

View File

@ -251,4 +251,8 @@ public final class Utils {
public static boolean isPowerOfTwo(long value) {
return (value & (value - 1)) == 0L;
}
public static boolean containsNullChars(String s) {
return s.indexOf('\u0000') >= 0;
}
}

View File

@ -67,6 +67,21 @@ public class LibraryLookupTest {
callFunc(addr);
}
@Test(expectedExceptions = IllegalArgumentException.class)
void testLoadLibraryBadName() {
try (Arena arena = Arena.ofConfined()) {
SymbolLookup.libraryLookup(LIB_PATH.toString() + "\u0000", arena);
}
}
@Test
void testLoadLibraryBadLookupName() {
try (Arena arena = Arena.ofConfined()) {
SymbolLookup lookup = SymbolLookup.libraryLookup(LIB_PATH, arena);
assertTrue(lookup.find("inc\u0000foobar").isEmpty());
}
}
private static MemorySegment loadLibrary(Arena session) {
SymbolLookup lib = SymbolLookup.libraryLookup(LIB_PATH, session);
MemorySegment addr = lib.find("inc").get();

View File

@ -134,6 +134,11 @@ public class StdLibTest extends NativeTestHelper {
assertEquals(found, expected.length());
}
@Test
void testSystemLibraryBadLookupName() {
assertTrue(LINKER.defaultLookup().find("strlen\u0000foobar").isEmpty());
}
static class StdLibHelper {
final static MethodHandle strcat = abi.downcallHandle(abi.defaultLookup().find("strcat").get(),

View File

@ -28,6 +28,7 @@
* @run testng/othervm --enable-native-access=ALL-UNNAMED TestClassLoaderFindNative
*/
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.SymbolLookup;
import org.testng.annotations.Test;
@ -60,4 +61,9 @@ public class TestClassLoaderFindNative {
MemorySegment segment = SymbolLookup.loaderLookup().find("c").get().reinterpret(1);
assertEquals(segment.get(JAVA_BYTE, 0), 42);
}
@Test
void testLoadLibraryBadLookupName() {
assertTrue(SymbolLookup.loaderLookup().find("f\u0000foobar").isEmpty());
}
}