-
CSR
-
Resolution: Approved
-
P3
-
None
-
behavioral
-
minimal
-
Out-of-bounds reads were already an invalid use case, we now just throw and exception. The existing API is also an incubator API (moved to preview in 19).
-
Java API
Summary
Change the VaList::nextVarg
methods to try and detect out-of-bounds reads, and throw NoSuchElementException
in such cases.
Problem
Reads from VaLists created in Java, using the VaList::make
method, should be safe. However, in practice out-of-bounds reads can occur, which have the potential to crash the VM on some platforms.
Solution
Detect out-of-bounds reads for VaLists created from Java using VaList::make
, and throw NoSuchElementException
in those cases.
Specification
The javadoc of VaList
has the following diff:
@@ -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).
*
@@ -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);
@@ -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);
@@ -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);
@@ -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);
@@ -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);
@@ -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);
@@ -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}.
@@ -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.
- csr of
-
JDK-8289148 j.l.foreign.VaList::nextVarg call could throw IndexOutOfBoundsException or even crash the VM
- Resolved