Skip to content

Commit 9aeadbb

Browse files
committed
8256865: Foreign Memory Access and Linker API are missing NPE checks
Reviewed-by: jvernee, sundar, chegar
1 parent 8cd2e0f commit 9aeadbb

36 files changed

+858
-196
lines changed

src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/AbstractLayout.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ public AbstractLayout(OptionalLong size, long alignment, Map<String, Constable>
6262

6363
@Override
6464
public AbstractLayout withName(String name) {
65+
Objects.requireNonNull(name);
6566
return withAttribute(LAYOUT_NAME, name);
6667
}
6768

@@ -72,6 +73,7 @@ public final Optional<String> name() {
7273

7374
@Override
7475
public Optional<Constable> attribute(String name) {
76+
Objects.requireNonNull(name);
7577
return Optional.ofNullable(attributes.get(name));
7678
}
7779

@@ -82,6 +84,7 @@ public Stream<String> attributes() {
8284

8385
@Override
8486
public AbstractLayout withAttribute(String name, Constable value) {
87+
Objects.requireNonNull(name);
8588
Map<String, Constable> newAttributes = new HashMap<>(attributes);
8689
newAttributes.put(name, value);
8790
return dup(alignment, newAttributes);

src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/CLinker.java

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import java.nio.charset.Charset;
3737
import java.util.Objects;
3838
import java.util.function.Consumer;
39+
import java.util.stream.Stream;
3940

4041
import static jdk.internal.foreign.PlatformLayouts.*;
4142

@@ -94,6 +95,9 @@
9495
* {@link #asVarArg(MemoryLayout)} is used to create the memory layouts for each parameter corresponding to a variadic
9596
* argument in a specialized function descriptor.
9697
*
98+
* <p> Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null}
99+
* elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown. </p>
100+
*
97101
* @apiNote In the future, if the Java language permits, {@link CLinker}
98102
* may become a {@code sealed} interface, which would prohibit subclassing except by
99103
* explicitly permitted types.
@@ -186,14 +190,16 @@ static CLinker getInstance() {
186190
MemoryLayout C_VA_LIST = pick(SysV.C_VA_LIST, Win64.C_VA_LIST, AArch64.C_VA_LIST);
187191

188192
/**
189-
* Returns a memory layout that is suitable to use the layout for variadic arguments.
193+
* Returns a memory layout that is suitable to use as the layout for variadic arguments in a specialized
194+
* function descriptor.
190195
* @param <T> the memory layout type
191-
* @param ml the layout the adapt
196+
* @param layout the layout the adapt
192197
* @return a potentially newly created layout with the right attributes
193198
*/
194199
@SuppressWarnings("unchecked")
195-
static <T extends MemoryLayout> T asVarArg(T ml) {
196-
return (T) PlatformLayouts.asVarArg(ml);
200+
static <T extends MemoryLayout> T asVarArg(T layout) {
201+
Objects.requireNonNull(layout);
202+
return (T) PlatformLayouts.asVarArg(layout);
197203
}
198204

199205
/**
@@ -207,7 +213,6 @@ static <T extends MemoryLayout> T asVarArg(T ml) {
207213
*
208214
* @param str the Java string to be converted into a C string.
209215
* @return a new native memory segment containing the converted C string.
210-
* @throws NullPointerException if {@code str == null}.
211216
*/
212217
static MemorySegment toCString(String str) {
213218
Objects.requireNonNull(str);
@@ -226,7 +231,6 @@ static MemorySegment toCString(String str) {
226231
* @param str the Java string to be converted into a C string.
227232
* @param charset The {@link java.nio.charset.Charset} to be used to compute the contents of the C string.
228233
* @return a new native memory segment containing the converted C string.
229-
* @throws NullPointerException if either {@code str == null} or {@code charset == null}.
230234
*/
231235
static MemorySegment toCString(String str, Charset charset) {
232236
Objects.requireNonNull(str);
@@ -246,7 +250,6 @@ static MemorySegment toCString(String str, Charset charset) {
246250
* @param str the Java string to be converted into a C string.
247251
* @param scope the scope to be used for the native segment allocation.
248252
* @return a new native memory segment containing the converted C string.
249-
* @throws NullPointerException if either {@code str == null} or {@code scope == null}.
250253
*/
251254
static MemorySegment toCString(String str, NativeScope scope) {
252255
Objects.requireNonNull(str);
@@ -267,7 +270,6 @@ static MemorySegment toCString(String str, NativeScope scope) {
267270
* @param charset The {@link java.nio.charset.Charset} to be used to compute the contents of the C string.
268271
* @param scope the scope to be used for the native segment allocation.
269272
* @return a new native memory segment containing the converted C string.
270-
* @throws NullPointerException if either {@code str == null}, {@code charset == null} or {@code scope == null}.
271273
*/
272274
static MemorySegment toCString(String str, Charset charset, NativeScope scope) {
273275
Objects.requireNonNull(str);
@@ -289,11 +291,11 @@ static MemorySegment toCString(String str, Charset charset, NativeScope scope) {
289291
* restricted methods, and use safe and supported functionalities, where possible.
290292
* @param addr the address at which the string is stored.
291293
* @return a Java string with the contents of the null-terminated C string at given address.
292-
* @throws NullPointerException if {@code addr == null}
293294
* @throws IllegalArgumentException if the size of the native string is greater than the largest string supported by the platform.
294295
*/
295296
static String toJavaStringRestricted(MemoryAddress addr) {
296297
Utils.checkRestrictedAccess("CLinker.toJavaStringRestricted");
298+
Objects.requireNonNull(addr);
297299
return SharedUtils.toJavaStringInternal(NativeMemorySegmentImpl.EVERYTHING, addr.toRawLongValue(), Charset.defaultCharset());
298300
}
299301

@@ -311,7 +313,6 @@ static String toJavaStringRestricted(MemoryAddress addr) {
311313
* @param addr the address at which the string is stored.
312314
* @param charset The {@link java.nio.charset.Charset} to be used to compute the contents of the Java string.
313315
* @return a Java string with the contents of the null-terminated C string at given address.
314-
* @throws NullPointerException if {@code addr == null} or {@code charset == null}.
315316
* @throws IllegalArgumentException if the size of the native string is greater than the largest string supported by the platform.
316317
*/
317318
static String toJavaStringRestricted(MemoryAddress addr, Charset charset) {
@@ -330,7 +331,6 @@ static String toJavaStringRestricted(MemoryAddress addr, Charset charset) {
330331
* over the decoding process is required.
331332
* @param addr the address at which the string is stored.
332333
* @return a Java string with the contents of the null-terminated C string at given address.
333-
* @throws NullPointerException if {@code addr == null}
334334
* @throws IllegalArgumentException if the size of the native string is greater than the largest string supported by the platform.
335335
* @throws IllegalStateException if the size of the native string is greater than the size of the segment
336336
* associated with {@code addr}, or if {@code addr} is associated with a segment that is <em>not alive</em>.
@@ -350,7 +350,6 @@ static String toJavaString(MemorySegment addr) {
350350
* @param addr the address at which the string is stored.
351351
* @param charset The {@link java.nio.charset.Charset} to be used to compute the contents of the Java string.
352352
* @return a Java string with the contents of the null-terminated C string at given address.
353-
* @throws NullPointerException if {@code addr == null} or {@code charset == null}.
354353
* @throws IllegalArgumentException if the size of the native string is greater than the largest string supported by the platform.
355354
* @throws IllegalStateException if the size of the native string is greater than the size of the segment
356355
* associated with {@code addr}, or if {@code addr} is associated with a segment that is <em>not alive</em>.
@@ -408,7 +407,6 @@ static MemoryAddress allocateMemoryRestricted(long size) {
408407
* restricted methods, and use safe and supported functionalities, where possible.
409408
*
410409
* @param addr memory address of the native memory to be freed
411-
* @throws NullPointerException if {@code addr == null}.
412410
*/
413411
static void freeMemoryRestricted(MemoryAddress addr) {
414412
Utils.checkRestrictedAccess("CLinker.freeMemoryRestricted");
@@ -429,6 +427,9 @@ static void freeMemoryRestricted(MemoryAddress addr) {
429427
* As such, this interface only supports reading {@code int}, {@code double},
430428
* and any other type that fits into a {@code long}.
431429
*
430+
* <p> Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null}
431+
* elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown. </p>
432+
*
432433
* @apiNote In the future, if the Java language permits, {@link VaList}
433434
* may become a {@code sealed} interface, which would prohibit subclassing except by
434435
* explicitly permitted types.
@@ -597,6 +598,7 @@ interface VaList extends Addressable, AutoCloseable {
597598
*/
598599
static VaList ofAddressRestricted(MemoryAddress address) {
599600
Utils.checkRestrictedAccess("VaList.ofAddressRestricted");
601+
Objects.requireNonNull(address);
600602
return SharedUtils.newVaListOfAddress(address);
601603
}
602604

@@ -618,6 +620,7 @@ static VaList ofAddressRestricted(MemoryAddress address) {
618620
* @return a new {@code VaList} instance backed by a fresh C {@code va_list}.
619621
*/
620622
static VaList make(Consumer<Builder> actions) {
623+
Objects.requireNonNull(actions);
621624
return SharedUtils.newVaList(actions, MemorySegment::allocateNative);
622625
}
623626

@@ -639,6 +642,8 @@ static VaList make(Consumer<Builder> actions) {
639642
* @return a new {@code VaList} instance backed by a fresh C {@code va_list}.
640643
*/
641644
static VaList make(Consumer<Builder> actions, NativeScope scope) {
645+
Objects.requireNonNull(actions);
646+
Objects.requireNonNull(scope);
642647
return SharedUtils.newVaList(actions, SharedUtils.Allocator.ofScope(scope));
643648
}
644649

@@ -656,6 +661,9 @@ static VaList empty() {
656661
/**
657662
* A builder interface used to construct a C {@code va_list}.
658663
*
664+
* <p> Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null}
665+
* elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown. </p>
666+
*
659667
* @apiNote In the future, if the Java language permits, {@link Builder}
660668
* may become a {@code sealed} interface, which would prohibit subclassing except by
661669
* explicitly permitted types.

src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/FunctionDescriptor.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242
/**
4343
* A function descriptor is made up of zero or more argument layouts and zero or one return layout. A function descriptor
4444
* is used to model the signature of foreign functions.
45+
*
46+
* <p> Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null}
47+
* elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown. </p>
4548
*/
4649
public final class FunctionDescriptor implements Constable {
4750

@@ -68,6 +71,7 @@ private FunctionDescriptor(MemoryLayout resLayout, Map<String, Constable> attrib
6871
* @return the attribute with the given name (if it exists).
6972
*/
7073
public Optional<Constable> attribute(String name) {
74+
Objects.requireNonNull(name);
7175
return Optional.ofNullable(attributes.get(name));
7276
}
7377

@@ -90,6 +94,7 @@ public Stream<String> attributes() {
9094
* @return a new function descriptor which features the same attributes as this descriptor, plus the newly specified attribute.
9195
*/
9296
public FunctionDescriptor withAttribute(String name, Constable value) {
97+
Objects.requireNonNull(name);
9398
Map<String, Constable> newAttributes = new HashMap<>(attributes);
9499
newAttributes.put(name, value);
95100
return new FunctionDescriptor(resLayout, newAttributes, argLayouts);
@@ -116,10 +121,10 @@ public List<MemoryLayout> argumentLayouts() {
116121
* @param resLayout the return layout.
117122
* @param argLayouts the argument layouts.
118123
* @return the new function descriptor.
119-
* @throws NullPointerException if any of the argument layouts, or the return layout is null.
120124
*/
121125
public static FunctionDescriptor of(MemoryLayout resLayout, MemoryLayout... argLayouts) {
122126
Objects.requireNonNull(resLayout);
127+
Objects.requireNonNull(argLayouts);
123128
Arrays.stream(argLayouts).forEach(Objects::requireNonNull);
124129
return new FunctionDescriptor(resLayout, Map.of(), argLayouts);
125130
}
@@ -128,9 +133,9 @@ public static FunctionDescriptor of(MemoryLayout resLayout, MemoryLayout... argL
128133
* Create a function descriptor with given argument layouts and no return layout.
129134
* @param argLayouts the argument layouts.
130135
* @return the new function descriptor.
131-
* @throws NullPointerException if any of the argument layouts is null.
132136
*/
133137
public static FunctionDescriptor ofVoid(MemoryLayout... argLayouts) {
138+
Objects.requireNonNull(argLayouts);
134139
Arrays.stream(argLayouts).forEach(Objects::requireNonNull);
135140
return new FunctionDescriptor(null, Map.of(), argLayouts);
136141
}
@@ -140,9 +145,9 @@ public static FunctionDescriptor ofVoid(MemoryLayout... argLayouts) {
140145
* of this function descriptor.
141146
* @param addedLayouts the argument layouts to append.
142147
* @return the new function descriptor.
143-
* @throws NullPointerException if any of the new argument layouts is null.
144148
*/
145149
public FunctionDescriptor withAppendedArgumentLayouts(MemoryLayout... addedLayouts) {
150+
Objects.requireNonNull(addedLayouts);
146151
Arrays.stream(addedLayouts).forEach(Objects::requireNonNull);
147152
MemoryLayout[] newLayouts = Arrays.copyOf(argLayouts, argLayouts.length + addedLayouts.length);
148153
System.arraycopy(addedLayouts, 0, newLayouts, argLayouts.length, addedLayouts.length);
@@ -153,7 +158,6 @@ public FunctionDescriptor withAppendedArgumentLayouts(MemoryLayout... addedLayou
153158
* Create a new function descriptor with the given memory layout as the new return layout.
154159
* @param newReturn the new return layout.
155160
* @return the new function descriptor.
156-
* @throws NullPointerException if the new return layout is null.
157161
*/
158162
public FunctionDescriptor withReturnLayout(MemoryLayout newReturn) {
159163
Objects.requireNonNull(newReturn);

src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/GroupLayout.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@
5252
* {@code GroupLayout} may have unpredictable results and should be avoided.
5353
* The {@code equals} method should be used for comparisons.
5454
*
55+
* <p> Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null}
56+
* elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown. </p>
57+
*
5558
* @implSpec
5659
* This class is immutable and thread-safe.
5760
*/

src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/LibraryLookup.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@
5656
* <p>
5757
* To allow for a library to be unloaded, a client will have to discard any strong references it
5858
* maintains, directly, or indirectly to a lookup object associated with given library.
59+
*
60+
* <p> Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null}
61+
* elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown. </p>
5962
*/
6063
public interface LibraryLookup {
6164

src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MappedMemorySegments.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import jdk.internal.foreign.MappedMemorySegmentImpl;
2929

3030
import java.nio.MappedByteBuffer;
31+
import java.util.Objects;
3132

3233
/**
3334
* This class provides capabilities to manipulate mapped memory segments, such as {@link #force(MemorySegment)},
@@ -42,6 +43,9 @@
4243
* with the desired parameters; the returned address can be easily wrapped into a memory segment, using
4344
* {@link MemoryAddress#ofLong(long)} and {@link MemoryAddress#asSegmentRestricted(long, Runnable, Object)}.
4445
*
46+
* <p> Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null}
47+
* elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown. </p>
48+
*
4549
* @implNote
4650
* The behavior of some the methods in this class (see {@link #load(MemorySegment)}, {@link #unload(MemorySegment)} and
4751
* {@link #isLoaded(MemorySegment)}) is highly platform-dependent; as a result, calling these methods might
@@ -151,6 +155,7 @@ public static void force(MemorySegment segment) {
151155
}
152156

153157
static MappedMemorySegmentImpl toMappedSegment(MemorySegment segment) {
158+
Objects.requireNonNull(segment);
154159
if (segment instanceof MappedMemorySegmentImpl) {
155160
return (MappedMemorySegmentImpl)segment;
156161
} else {

0 commit comments

Comments
 (0)