mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-15 08:34:30 +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;
|
package java.lang;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@code Throwable} class is the superclass of all errors and
|
* 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)
|
private void readObject(ObjectInputStream s)
|
||||||
throws IOException, ClassNotFoundException {
|
throws IOException, ClassNotFoundException {
|
||||||
s.defaultReadObject(); // read in all fields
|
s.defaultReadObject(); // read in all fields
|
||||||
if (suppressedExceptions != null) {
|
|
||||||
List<Throwable> suppressed = null;
|
// Set suppressed exceptions and stack trace elements fields
|
||||||
if (suppressedExceptions.isEmpty()) {
|
// to marker values until the contents from the serial stream
|
||||||
// Use the sentinel for a zero-length list
|
// are validated.
|
||||||
suppressed = SUPPRESSED_SENTINEL;
|
List<Throwable> candidateSuppressedExceptions = suppressedExceptions;
|
||||||
} else { // Copy Throwables to new list
|
suppressedExceptions = SUPPRESSED_SENTINEL;
|
||||||
suppressed = new ArrayList<>(1);
|
|
||||||
for (Throwable t : suppressedExceptions) {
|
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
|
// Enforce constraints on suppressed exceptions in
|
||||||
// case of corrupt or malicious stream.
|
// case of corrupt or malicious stream.
|
||||||
Objects.requireNonNull(t, NULL_CAUSE_MESSAGE);
|
Objects.requireNonNull(t, NULL_CAUSE_MESSAGE);
|
||||||
if (t == this)
|
if (t == this)
|
||||||
throw new IllegalArgumentException(SELF_SUPPRESSION_MESSAGE);
|
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 {
|
||||||
} // else a null suppressedExceptions field remains null
|
suppressedExceptions = null;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For zero-length stack traces, use a clone of
|
* 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
|
* the stackTrace needs to be constructed from the information
|
||||||
* in backtrace.
|
* in backtrace.
|
||||||
*/
|
*/
|
||||||
if (stackTrace != null) {
|
if (candidateStackTrace != null) {
|
||||||
if (stackTrace.length == 0) {
|
// Work from a clone of the candidateStackTrace to ensure
|
||||||
stackTrace = UNASSIGNED_STACK.clone();
|
// consistency of checks.
|
||||||
} else if (stackTrace.length == 1 &&
|
candidateStackTrace = candidateStackTrace.clone();
|
||||||
|
if (candidateStackTrace.length >= 1) {
|
||||||
|
if (candidateStackTrace.length == 1 &&
|
||||||
// Check for the marker of an immutable stack trace
|
// Check for the marker of an immutable stack trace
|
||||||
SentinelHolder.STACK_TRACE_ELEMENT_SENTINEL.equals(stackTrace[0])) {
|
SentinelHolder.STACK_TRACE_ELEMENT_SENTINEL.equals(candidateStackTrace[0])) {
|
||||||
stackTrace = null;
|
stackTrace = null;
|
||||||
} else { // Verify stack trace elements are non-null.
|
} else { // Verify stack trace elements are non-null.
|
||||||
for(StackTraceElement ste : stackTrace) {
|
for (StackTraceElement ste : candidateStackTrace) {
|
||||||
Objects.requireNonNull(ste, "null StackTraceElement in serial stream.");
|
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 {
|
} else {
|
||||||
// A null stackTrace field in the serial form can result
|
int size = deserSuppressedExceptions.size();
|
||||||
// from an exception serialized without that field in
|
if (size < 0) {
|
||||||
// older JDK releases; treat such exceptions as having
|
throw new StreamCorruptedException("Negative list size reported.");
|
||||||
// empty stack traces.
|
}
|
||||||
stackTrace = UNASSIGNED_STACK.clone();
|
return size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue