Skip to content
This repository has been archived by the owner on Sep 19, 2023. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
8289148: j.l.foreign.VaList::nextVarg call could throw IndexOutOfBoun…
…dsException or even crash the VM

8289333: Specification of method j.l.foreign.VaList::skip deserves clarification
8289156: j.l.foreign.VaList::skip call could throw java.lang.IndexOutOfBoundsException: Out of bound access on segment

Reviewed-by: mcimadamore
  • Loading branch information
JornVernee committed Jul 12, 2022
1 parent c3806b9 commit 3164c98
Show file tree
Hide file tree
Showing 7 changed files with 375 additions and 157 deletions.
22 changes: 21 additions & 1 deletion src/java.base/share/classes/java/lang/foreign/VaList.java
Expand Up @@ -25,6 +25,7 @@
*/
package java.lang.foreign;

import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.function.Consumer;

Expand All @@ -50,7 +51,16 @@
* <p>
* As such, this interface only supports reading {@code int}, {@code double},
* and any other type that fits into a {@code long}.
*
* <h2 id="safety">Safety considerations</h2>
* It is possible for clients to access elements outside the spatial bounds of a variable argument list.
* Variable argument list implementations will try to detect out-of-bounds reads on a best-effort basis.
* <p>
* Whether this detection succeeds depends on the factory method used to create the variable argument list:
* <ul>
* <li>Variable argument lists created <em>safely</em>, using {@link #make(Consumer, MemorySession)} are capable of detecting out-of-bounds reads;</li>
* <li>Variable argument lists created <em>unsafely</em>, using {@link #ofAddress(MemoryAddress, MemorySession)} are not capable of detecting out-of-bounds reads</li>
* </ul>
* <p>
* This class is not thread safe, and all accesses should occur within a single thread
* (regardless of the memory session associated with the variable arity list).
*
Expand All @@ -74,6 +84,7 @@ sealed public interface VaList extends Addressable permits WinVaList, SysVVaList
* {@linkplain MemorySession#isAlive() alive}.
* @throws WrongThreadException if this method is called from a thread other than the thread owning
* the {@linkplain #session() session} associated with this variable argument list.
* @throws NoSuchElementException if an <a href=VaList.html#safety>out-of-bounds</a> read is detected.
*/
int nextVarg(ValueLayout.OfInt layout);

Expand All @@ -87,6 +98,7 @@ sealed public interface VaList extends Addressable permits WinVaList, SysVVaList
* {@linkplain MemorySession#isAlive() alive}.
* @throws WrongThreadException if this method is called from a thread other than the thread owning
* the {@linkplain #session() session} associated with this variable argument list.
* @throws NoSuchElementException if an <a href=VaList.html#safety>out-of-bounds</a> read is detected.
*/
long nextVarg(ValueLayout.OfLong layout);

Expand All @@ -100,6 +112,7 @@ sealed public interface VaList extends Addressable permits WinVaList, SysVVaList
* {@linkplain MemorySession#isAlive() alive}.
* @throws WrongThreadException if this method is called from a thread other than the thread owning
* the {@linkplain #session() session} associated with this variable argument list.
* @throws NoSuchElementException if an <a href=VaList.html#safety>out-of-bounds</a> read is detected.
*/
double nextVarg(ValueLayout.OfDouble layout);

Expand All @@ -113,6 +126,7 @@ sealed public interface VaList extends Addressable permits WinVaList, SysVVaList
* {@linkplain MemorySession#isAlive() alive}.
* @throws WrongThreadException if this method is called from a thread other than the thread owning
* the {@linkplain #session() session} associated with this variable argument list.
* @throws NoSuchElementException if an <a href=VaList.html#safety>out-of-bounds</a> read is detected.
*/
MemoryAddress nextVarg(ValueLayout.OfAddress layout);

Expand All @@ -135,6 +149,7 @@ sealed public interface VaList extends Addressable permits WinVaList, SysVVaList
* {@linkplain MemorySession#isAlive() alive}.
* @throws WrongThreadException if this method is called from a thread other than the thread owning
* the {@linkplain #session() session} associated with this variable argument list.
* @throws NoSuchElementException if an <a href=VaList.html#safety>out-of-bounds</a> read is detected.
*/
MemorySegment nextVarg(GroupLayout layout, SegmentAllocator allocator);

Expand All @@ -146,6 +161,7 @@ sealed public interface VaList extends Addressable permits WinVaList, SysVVaList
* {@linkplain MemorySession#isAlive() alive}.
* @throws WrongThreadException if this method is called from a thread other than the thread owning
* the {@linkplain #session() session} associated with this variable argument list.
* @throws NoSuchElementException if an <a href=VaList.html#safety>out-of-bounds</a> read is detected.
*/
void skip(MemoryLayout... layouts);

Expand Down Expand Up @@ -185,6 +201,8 @@ sealed public interface VaList extends Addressable permits WinVaList, SysVVaList
* the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
* restricted methods, and use safe and supported functionalities, where possible.
*
* @implNote variable argument lists created using this method can not detect <a href=VaList.html#safety>out-of-bounds</a> reads.
*
* @param address a memory address pointing to an existing variable argument list.
* @param session the memory session to be associated with the returned variable argument list.
* @return a new variable argument list backed by the memory region at {@code address}.
Expand Down Expand Up @@ -214,6 +232,8 @@ static VaList ofAddress(MemoryAddress address, MemorySession session) {
* Note that when there are no elements added to the created va list,
* this method will return the same as {@link #empty()}.
*
* @implNote variable argument lists created using this method can detect <a href=VaList.html#safety>out-of-bounds</a> reads.
*
* @param actions a consumer for a builder (see {@link Builder}) which can be used to specify the elements
* of the underlying variable argument list.
* @param session the memory session to be associated with the new variable arity list.
Expand Down
Expand Up @@ -56,6 +56,7 @@
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -382,13 +383,15 @@ public static boolean isVarargsIndex(FunctionDescriptor descriptor, int argIndex
return firstPos != -1 && argIndex >= firstPos;
}

public static NoSuchElementException newVaListNSEE(MemoryLayout layout) {
return new NoSuchElementException("No such element: " + layout);
}

public static class SimpleVaArg {
public final Class<?> carrier;
public final MemoryLayout layout;
public final Object value;

public SimpleVaArg(Class<?> carrier, MemoryLayout layout, Object value) {
this.carrier = carrier;
public SimpleVaArg(MemoryLayout layout, Object value) {
this.layout = layout;
this.value = value;
}
Expand Down

1 comment on commit 3164c98

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.