mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8212328: Exceptional throw cases
Reviewed-by: smarks, rriggs, igerasim, ahgross, skoivu
This commit is contained in:
parent
27e83c186a
commit
12802b7e8d
1 changed files with 56 additions and 27 deletions
|
@ -25,8 +25,8 @@
|
|||
|
||||
package java.lang;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* The {@code Throwable} class is the superclass of all errors and
|
||||
|
@ -904,24 +904,36 @@ public class Throwable implements Serializable {
|
|||
private void readObject(ObjectInputStream s)
|
||||
throws IOException, ClassNotFoundException {
|
||||
s.defaultReadObject(); // read in all fields
|
||||
if (suppressedExceptions != null) {
|
||||
List<Throwable> suppressed = null;
|
||||
if (suppressedExceptions.isEmpty()) {
|
||||
// Use the sentinel for a zero-length list
|
||||
suppressed = SUPPRESSED_SENTINEL;
|
||||
} else { // Copy Throwables to new list
|
||||
suppressed = new ArrayList<>(1);
|
||||
for (Throwable t : suppressedExceptions) {
|
||||
|
||||
// Set suppressed exceptions and stack trace elements fields
|
||||
// to marker values until the contents from the serial stream
|
||||
// are validated.
|
||||
List<Throwable> candidateSuppressedExceptions = suppressedExceptions;
|
||||
suppressedExceptions = SUPPRESSED_SENTINEL;
|
||||
|
||||
StackTraceElement[] candidateStackTrace = stackTrace;
|
||||
stackTrace = UNASSIGNED_STACK.clone();
|
||||
|
||||
if (candidateSuppressedExceptions != null) {
|
||||
int suppressedSize = validateSuppressedExceptionsList(candidateSuppressedExceptions);
|
||||
if (suppressedSize > 0) { // Copy valid Throwables to new list
|
||||
var suppList = new ArrayList<Throwable>(Math.min(100, suppressedSize));
|
||||
|
||||
for (Throwable t : candidateSuppressedExceptions) {
|
||||
// Enforce constraints on suppressed exceptions in
|
||||
// case of corrupt or malicious stream.
|
||||
Objects.requireNonNull(t, NULL_CAUSE_MESSAGE);
|
||||
if (t == this)
|
||||
throw new IllegalArgumentException(SELF_SUPPRESSION_MESSAGE);
|
||||
suppressed.add(t);
|
||||
suppList.add(t);
|
||||
}
|
||||
// If there are any invalid suppressed exceptions,
|
||||
// implicitly use the sentinel value assigned earlier.
|
||||
suppressedExceptions = suppList;
|
||||
}
|
||||
suppressedExceptions = suppressed;
|
||||
} // else a null suppressedExceptions field remains null
|
||||
} else {
|
||||
suppressedExceptions = null;
|
||||
}
|
||||
|
||||
/*
|
||||
* For zero-length stack traces, use a clone of
|
||||
|
@ -932,24 +944,41 @@ public class Throwable implements Serializable {
|
|||
* the stackTrace needs to be constructed from the information
|
||||
* in backtrace.
|
||||
*/
|
||||
if (stackTrace != null) {
|
||||
if (stackTrace.length == 0) {
|
||||
stackTrace = UNASSIGNED_STACK.clone();
|
||||
} else if (stackTrace.length == 1 &&
|
||||
if (candidateStackTrace != null) {
|
||||
// Work from a clone of the candidateStackTrace to ensure
|
||||
// consistency of checks.
|
||||
candidateStackTrace = candidateStackTrace.clone();
|
||||
if (candidateStackTrace.length >= 1) {
|
||||
if (candidateStackTrace.length == 1 &&
|
||||
// Check for the marker of an immutable stack trace
|
||||
SentinelHolder.STACK_TRACE_ELEMENT_SENTINEL.equals(stackTrace[0])) {
|
||||
stackTrace = null;
|
||||
} else { // Verify stack trace elements are non-null.
|
||||
for(StackTraceElement ste : stackTrace) {
|
||||
Objects.requireNonNull(ste, "null StackTraceElement in serial stream.");
|
||||
SentinelHolder.STACK_TRACE_ELEMENT_SENTINEL.equals(candidateStackTrace[0])) {
|
||||
stackTrace = null;
|
||||
} else { // Verify stack trace elements are non-null.
|
||||
for (StackTraceElement ste : candidateStackTrace) {
|
||||
Objects.requireNonNull(ste, "null StackTraceElement in serial stream.");
|
||||
}
|
||||
stackTrace = candidateStackTrace;
|
||||
}
|
||||
}
|
||||
}
|
||||
// A null stackTrace field in the serial form can result from
|
||||
// an exception serialized without that field in older JDK
|
||||
// releases; treat such exceptions as having empty stack
|
||||
// traces by leaving stackTrace assigned to a clone of
|
||||
// UNASSIGNED_STACK.
|
||||
}
|
||||
|
||||
private int validateSuppressedExceptionsList(List<Throwable> deserSuppressedExceptions)
|
||||
throws IOException {
|
||||
if (!Object.class.getModule().
|
||||
equals(deserSuppressedExceptions.getClass().getModule())) {
|
||||
throw new StreamCorruptedException("List implementation not in base module.");
|
||||
} else {
|
||||
// A null stackTrace field in the serial form can result
|
||||
// from an exception serialized without that field in
|
||||
// older JDK releases; treat such exceptions as having
|
||||
// empty stack traces.
|
||||
stackTrace = UNASSIGNED_STACK.clone();
|
||||
int size = deserSuppressedExceptions.size();
|
||||
if (size < 0) {
|
||||
throw new StreamCorruptedException("Negative list size reported.");
|
||||
}
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue