1 /*
2 * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.io;
27
28 import java.io.ObjectInputFilter.Config;
29 import java.io.ObjectStreamClass.RecordSupport;
30 import java.lang.System.Logger;
31 import java.lang.invoke.MethodHandle;
32 import java.lang.reflect.Array;
33 import java.lang.reflect.InvocationHandler;
34 import java.lang.reflect.Modifier;
35 import java.lang.reflect.Proxy;
36 import java.nio.charset.StandardCharsets;
37 import java.util.Arrays;
38 import java.util.Objects;
39
40 import jdk.internal.access.JavaLangAccess;
41 import jdk.internal.access.SharedSecrets;
42 import jdk.internal.event.DeserializationEvent;
43 import jdk.internal.misc.Unsafe;
44 import jdk.internal.util.ByteArray;
45
46 /**
47 * An ObjectInputStream deserializes primitive data and objects previously
48 * written using an ObjectOutputStream.
49 *
50 * <p><strong>Warning: Deserialization of untrusted data is inherently dangerous
51 * and should be avoided. Untrusted data should be carefully validated according to the
52 * "Serialization and Deserialization" section of the
53 * {@extLink secure_coding_guidelines_javase Secure Coding Guidelines for Java SE}.
54 * {@extLink serialization_filter_guide Serialization Filtering} describes best
55 * practices for defensive use of serial filters.
56 * </strong></p>
57 *
58 * <p>The key to disabling deserialization attacks is to prevent instances of
59 * arbitrary classes from being deserialized, thereby preventing the direct or
60 * indirect execution of their methods.
61 * {@link ObjectInputFilter} describes how to use filters and
62 * {@link ObjectInputFilter.Config} describes how to configure the filter and filter factory.
63 * Each stream has an optional deserialization filter
64 * to check the classes and resource limits during deserialization.
65 * The JVM-wide filter factory ensures that a filter can be set on every {@link ObjectInputStream}
66 * and every object read from the stream can be checked.
67 * The {@linkplain #ObjectInputStream() ObjectInputStream constructors} invoke the filter factory
68 * to select the initial filter which may be updated or replaced by {@link #setObjectInputFilter}.
69 * <p>
70 * If an ObjectInputStream has a filter, the {@link ObjectInputFilter} can check that
71 * the classes, array lengths, number of references in the stream, depth, and
72 * number of bytes consumed from the input stream are allowed and
73 * if not, can terminate deserialization.
74 *
75 * <p>ObjectOutputStream and ObjectInputStream can provide an application with
76 * persistent storage for graphs of objects when used with a FileOutputStream
77 * and FileInputStream respectively. ObjectInputStream is used to recover
78 * those objects previously serialized. Other uses include passing objects
79 * between hosts using a socket stream or for marshaling and unmarshaling
80 * arguments and parameters in a remote communication system.
81 *
82 * <p>ObjectInputStream ensures that the types of all objects in the graph
83 * created from the stream match the classes present in the Java Virtual
84 * Machine. Classes are loaded as required using the standard mechanisms.
85 *
86 * <p>Only objects that support the java.io.Serializable or
87 * java.io.Externalizable interface can be read from streams.
88 *
89 * <p>The method {@code readObject} is used to read an object from the
90 * stream. Java's safe casting should be used to get the desired type. In
91 * Java, strings and arrays are objects and are treated as objects during
92 * serialization. When read they need to be cast to the expected type.
93 *
94 * <p>Primitive data types can be read from the stream using the appropriate
95 * method on DataInput.
96 *
97 * <p>The default deserialization mechanism for objects restores the contents
98 * of each field to the value and type it had when it was written. Fields
99 * declared as transient or static are ignored by the deserialization process.
100 * References to other objects cause those objects to be read from the stream
101 * as necessary. Graphs of objects are restored correctly using a reference
102 * sharing mechanism. New objects are always allocated when deserializing,
103 * which prevents existing objects from being overwritten.
104 *
105 * <p>Reading an object is analogous to running the constructors of a new
106 * object. Memory is allocated for the object and initialized to zero (NULL).
107 * No-arg constructors are invoked for the non-serializable classes and then
108 * the fields of the serializable classes are restored from the stream starting
109 * with the serializable class closest to java.lang.object and finishing with
110 * the object's most specific class.
111 *
112 * <p>For example to read from a stream as written by the example in
113 * {@link ObjectOutputStream}:
114 * <br>
115 * {@snippet lang="java" :
116 * try (FileInputStream fis = new FileInputStream("t.tmp");
117 * ObjectInputStream ois = new ObjectInputStream(fis)) {
118 * String label = (String) ois.readObject();
119 * LocalDateTime dateTime = (LocalDateTime) ois.readObject();
120 * // Use label and dateTime
121 * } catch (Exception ex) {
122 * // handle exception
123 * }
124 * }
125 *
126 * <p>Classes control how they are serialized by implementing either the
127 * java.io.Serializable or java.io.Externalizable interfaces.
128 *
129 * <p>Implementing the Serializable interface allows object serialization to
130 * save and restore the entire state of the object and it allows classes to
131 * evolve between the time the stream is written and the time it is read. It
132 * automatically traverses references between objects, saving and restoring
133 * entire graphs.
134 *
135 * <p>Serializable classes that require special handling during the
136 * serialization and deserialization process should implement methods
137 * with the following signatures:
138 *
139 * {@snippet lang="java":
140 * private void writeObject(java.io.ObjectOutputStream stream)
141 * throws IOException;
142 * private void readObject(java.io.ObjectInputStream stream)
143 * throws IOException, ClassNotFoundException;
144 * private void readObjectNoData()
145 * throws ObjectStreamException;
146 * }
147 *
148 * <p>The method name, modifiers, return type, and number and type of
149 * parameters must match exactly for the method to be used by
150 * serialization or deserialization. The methods should only be
151 * declared to throw checked exceptions consistent with these
152 * signatures.
153 *
154 * <p>The readObject method is responsible for reading and restoring the state
155 * of the object for its particular class using data written to the stream by
156 * the corresponding writeObject method. The method does not need to concern
157 * itself with the state belonging to its superclasses or subclasses. State is
158 * restored by reading data from the ObjectInputStream for the individual
159 * fields and making assignments to the appropriate fields of the object.
160 * Reading primitive data types is supported by DataInput.
161 *
162 * <p>Any attempt to read object data which exceeds the boundaries of the
163 * custom data written by the corresponding writeObject method will cause an
164 * OptionalDataException to be thrown with an eof field value of true.
165 * Non-object reads which exceed the end of the allotted data will reflect the
166 * end of data in the same way that they would indicate the end of the stream:
167 * bytewise reads will return -1 as the byte read or number of bytes read, and
168 * primitive reads will throw EOFExceptions. If there is no corresponding
169 * writeObject method, then the end of default serialized data marks the end of
170 * the allotted data.
171 *
172 * <p>Primitive and object read calls issued from within a readExternal method
173 * behave in the same manner--if the stream is already positioned at the end of
174 * data written by the corresponding writeExternal method, object reads will
175 * throw OptionalDataExceptions with eof set to true, bytewise reads will
176 * return -1, and primitive reads will throw EOFExceptions. Note that this
177 * behavior does not hold for streams written with the old
178 * {@code ObjectStreamConstants.PROTOCOL_VERSION_1} protocol, in which the
179 * end of data written by writeExternal methods is not demarcated, and hence
180 * cannot be detected.
181 *
182 * <p>The readObjectNoData method is responsible for initializing the state of
183 * the object for its particular class in the event that the serialization
184 * stream does not list the given class as a superclass of the object being
185 * deserialized. This may occur in cases where the receiving party uses a
186 * different version of the deserialized instance's class than the sending
187 * party, and the receiver's version extends classes that are not extended by
188 * the sender's version. This may also occur if the serialization stream has
189 * been tampered; hence, readObjectNoData is useful for initializing
190 * deserialized objects properly despite a "hostile" or incomplete source
191 * stream.
192 *
193 * <p>Serialization does not read or assign values to the fields of any object
194 * that does not implement the java.io.Serializable interface. Subclasses of
195 * Objects that are not serializable can be serializable. In this case the
196 * non-serializable class must have a no-arg constructor to allow its fields to
197 * be initialized. In this case it is the responsibility of the subclass to
198 * save and restore the state of the non-serializable class. It is frequently
199 * the case that the fields of that class are accessible (public, package, or
200 * protected) or that there are get and set methods that can be used to restore
201 * the state.
202 *
203 * <p>Any exception that occurs while deserializing an object will be caught by
204 * the ObjectInputStream and abort the reading process.
205 *
206 * <p>Implementing the Externalizable interface allows the object to assume
207 * complete control over the contents and format of the object's serialized
208 * form. The methods of the Externalizable interface, writeExternal and
209 * readExternal, are called to save and restore the objects state. When
210 * implemented by a class they can write and read their own state using all of
211 * the methods of ObjectOutput and ObjectInput. It is the responsibility of
212 * the objects to handle any versioning that occurs.
213 *
214 * <p>Enum constants are deserialized differently than ordinary serializable or
215 * externalizable objects. The serialized form of an enum constant consists
216 * solely of its name; field values of the constant are not transmitted. To
217 * deserialize an enum constant, ObjectInputStream reads the constant name from
218 * the stream; the deserialized constant is then obtained by calling the static
219 * method {@code Enum.valueOf(Class, String)} with the enum constant's
220 * base type and the received constant name as arguments. Like other
221 * serializable or externalizable objects, enum constants can function as the
222 * targets of back references appearing subsequently in the serialization
223 * stream. The process by which enum constants are deserialized cannot be
224 * customized: any class-specific readObject, readObjectNoData, and readResolve
225 * methods defined by enum types are ignored during deserialization.
226 * Similarly, any serialPersistentFields or serialVersionUID field declarations
227 * are also ignored--all enum types have a fixed serialVersionUID of 0L.
228 *
229 * <a id="record-serialization"></a>
230 * <p>Records are serialized differently than ordinary serializable or externalizable
231 * objects. During deserialization the record's canonical constructor is invoked
232 * to construct the record object. Certain serialization-related methods, such
233 * as readObject and writeObject, are ignored for serializable records. See
234 * <a href="{@docRoot}/../specs/serialization/serial-arch.html#serialization-of-records">
235 * <cite>Java Object Serialization Specification,</cite> Section 1.13,
236 * "Serialization of Records"</a> for additional information.
237 *
238 * @spec serialization/index.html Java Object Serialization Specification
239 * @author Mike Warres
240 * @author Roger Riggs
241 * @see java.io.DataInput
242 * @see java.io.ObjectOutputStream
243 * @see java.io.Serializable
244 * @see <a href="{@docRoot}/../specs/serialization/input.html">
245 * <cite>Java Object Serialization Specification,</cite> Section 3, "Object Input Classes"</a>
246 * @since 1.1
247 */
248 public class ObjectInputStream
249 extends InputStream implements ObjectInput, ObjectStreamConstants
250 {
251 /** handle value representing null */
252 private static final int NULL_HANDLE = -1;
253
254 /** marker for unshared objects in internal handle table */
255 private static final Object unsharedMarker = new Object();
256
257 private static class Caches {
258
259 /**
260 * Property to permit setting a filter after objects
261 * have been read.
262 * See {@link #setObjectInputFilter(ObjectInputFilter)}
263 */
264 static final boolean SET_FILTER_AFTER_READ =
265 Boolean.getBoolean("jdk.serialSetFilterAfterRead");
266
267 /**
268 * Property to control {@link GetField#get(String, Object)} conversion of
269 * {@link ClassNotFoundException} to {@code null}. If set to {@code true}
270 * {@link GetField#get(String, Object)} returns null otherwise
271 * throwing {@link ClassNotFoundException}.
272 */
273 private static final boolean GETFIELD_CNFE_RETURNS_NULL =
274 Boolean.getBoolean("jdk.serialGetFieldCnfeReturnsNull");
275
276 /**
277 * Property to override the implementation limit on the number
278 * of interfaces allowed for Proxies. The property value is clamped to 0..65535.
279 * The maximum number of interfaces allowed for a proxy is limited to 65535 by
280 * {@link java.lang.reflect.Proxy#newProxyInstance(ClassLoader, Class[], InvocationHandler)}.
281 */
282 static final int PROXY_INTERFACE_LIMIT =
283 Math.clamp(Integer.getInteger("jdk.serialProxyInterfaceLimit", 65535), 0, 65535);
284 }
285
286 /*
287 * Separate class to defer initialization of logging until needed.
288 */
289 private static class Logging {
290 /*
291 * Logger for ObjectInputFilter results.
292 * Setup the filter logger if it is set to DEBUG or TRACE.
293 * (Assuming it will not change).
294 */
295 static final System.Logger filterLogger;
296
297 static {
298 Logger filterLog = System.getLogger("java.io.serialization");
299 filterLogger = (filterLog.isLoggable(Logger.Level.DEBUG)
300 || filterLog.isLoggable(Logger.Level.TRACE)) ? filterLog : null;
301 }
302 }
303
304 /** filter stream for handling block data conversion */
305 private final BlockDataInputStream bin;
306 /** validation callback list */
307 private final ValidationList vlist;
308 /** recursion depth */
309 private long depth;
310 /** Total number of references to any type of object, class, enum, proxy, etc. */
311 private long totalObjectRefs;
312 /** whether stream is closed */
313 private boolean closed;
314
315 /** wire handle -> obj/exception map */
316 private final HandleTable handles;
317 /** scratch field for passing handle values up/down call stack */
318 private int passHandle = NULL_HANDLE;
319 /** flag set when at end of field value block with no TC_ENDBLOCKDATA */
320 private boolean defaultDataEnd = false;
321
322 /** if true, invoke readObjectOverride() instead of readObject() */
323 private final boolean enableOverride;
324 /** if true, invoke resolveObject() */
325 private boolean enableResolve;
326
327 /**
328 * Context during upcalls to class-defined readObject methods; holds
329 * object currently being deserialized and descriptor for current class.
330 * Null when not during readObject upcall.
331 */
332 private SerialCallbackContext curContext;
333
334 /**
335 * Filter of class descriptors and classes read from the stream;
336 * may be null.
337 */
338 private ObjectInputFilter serialFilter;
339
340 /**
341 * True if the stream-specific filter has been set; initially false.
342 */
343 private boolean streamFilterSet;
344
345 /**
346 * Creates an ObjectInputStream that reads from the specified InputStream.
347 * A serialization stream header is read from the stream and verified.
348 * This constructor will block until the corresponding ObjectOutputStream
349 * has written and flushed the header.
350 *
351 * <p>The constructor initializes the deserialization filter to the filter returned
352 * by invoking the serial filter factory returned from {@link Config#getSerialFilterFactory()}
353 * with {@code null} for the current filter
354 * and the {@linkplain Config#getSerialFilter() static JVM-wide filter} for the requested filter.
355 * If the serial filter or serial filter factory properties are invalid
356 * an {@link IllegalStateException} is thrown.
357 * When the filter factory {@code apply} method is invoked it may throw a runtime exception
358 * preventing the {@code ObjectInputStream} from being constructed.
359 *
360 * @param in input stream to read from
361 * @throws StreamCorruptedException if the stream header is incorrect
362 * @throws IOException if an I/O error occurs while reading stream header
363 * @throws IllegalStateException if the initialization of {@link ObjectInputFilter.Config}
364 * fails due to invalid serial filter or serial filter factory properties.
365 * @throws NullPointerException if {@code in} is {@code null}
366 * @see ObjectInputStream#ObjectInputStream()
367 * @see ObjectInputStream#readFields()
368 * @see ObjectOutputStream#ObjectOutputStream(OutputStream)
369 */
370 @SuppressWarnings("this-escape")
371 public ObjectInputStream(InputStream in) throws IOException {
372 bin = new BlockDataInputStream(in);
373 handles = new HandleTable(10);
374 vlist = new ValidationList();
375 streamFilterSet = false;
376 serialFilter = Config.getSerialFilterFactorySingleton().apply(null, Config.getSerialFilter());
377 enableOverride = false;
378 readStreamHeader();
379 bin.setBlockDataMode(true);
380 }
381
382 /**
383 * Provide a way for subclasses that are completely reimplementing
384 * ObjectInputStream to not have to allocate private data just used by this
385 * implementation of ObjectInputStream.
386 *
387 * <p>The constructor initializes the deserialization filter to the filter returned
388 * by invoking the serial filter factory returned from {@link Config#getSerialFilterFactory()}
389 * with {@code null} for the current filter
390 * and the {@linkplain Config#getSerialFilter() static JVM-wide filter} for the requested filter.
391 * If the serial filter or serial filter factory properties are invalid
392 * an {@link IllegalStateException} is thrown.
393 * When the filter factory {@code apply} method is invoked it may throw a runtime exception
394 * preventing the {@code ObjectInputStream} from being constructed.
395 *
396 * @throws IOException if an I/O error occurs while creating this stream
397 * @throws IllegalStateException if the initialization of {@link ObjectInputFilter.Config}
398 * fails due to invalid serial filter or serial filter factory properties.
399 */
400 protected ObjectInputStream() throws IOException {
401 bin = null;
402 handles = null;
403 vlist = null;
404 streamFilterSet = false;
405 serialFilter = Config.getSerialFilterFactorySingleton().apply(null, Config.getSerialFilter());
406 enableOverride = true;
407 }
408
409 /**
410 * Read an object from the ObjectInputStream. The class of the object, the
411 * signature of the class, and the values of the non-transient and
412 * non-static fields of the class and all of its supertypes are read.
413 * Default deserializing for a class can be overridden using the writeObject
414 * and readObject methods. Objects referenced by this object are read
415 * transitively so that a complete equivalent graph of objects is
416 * reconstructed by readObject.
417 *
418 * <p>The root object is completely restored when all of its fields and the
419 * objects it references are completely restored. At this point the object
420 * validation callbacks are executed in order based on their registered
421 * priorities. The callbacks are registered by objects (in the readObject
422 * special methods) as they are individually restored.
423 *
424 * <p>The deserialization filter, when not {@code null}, is invoked for
425 * each object (regular or class) read to reconstruct the root object.
426 * See {@link #setObjectInputFilter(ObjectInputFilter) setObjectInputFilter} for details.
427 *
428 * <p>Exceptions are thrown for problems with the InputStream and for
429 * classes that should not be deserialized. All exceptions are fatal to
430 * the InputStream and leave it in an indeterminate state; it is up to the
431 * caller to ignore or recover the stream state.
432 *
433 * @throws ClassNotFoundException Class of a serialized object cannot be
434 * found.
435 * @throws InvalidClassException Something is wrong with a class used by
436 * deserialization.
437 * @throws StreamCorruptedException Control information in the
438 * stream is inconsistent.
439 * @throws OptionalDataException Primitive data was found in the
440 * stream instead of objects.
441 * @throws IOException Any of the usual Input/Output related exceptions.
442 */
443 public final Object readObject()
444 throws IOException, ClassNotFoundException {
445 return readObject(Object.class);
446 }
447
448 /**
449 * Reads a String and only a string.
450 *
451 * @return the String read
452 * @throws EOFException If end of file is reached.
453 * @throws IOException If other I/O error has occurred.
454 */
455 private String readString() throws IOException {
456 try {
457 return (String) readObject(String.class);
458 } catch (ClassNotFoundException cnf) {
459 throw new IllegalStateException(cnf);
460 }
461 }
462
463 /**
464 * Internal method to read an object from the ObjectInputStream of the expected type.
465 * Called only from {@code readObject()} and {@code readString()}.
466 * Only {@code Object.class} and {@code String.class} are supported.
467 *
468 * @param type the type expected; either Object.class or String.class
469 * @return an object of the type
470 * @throws IOException Any of the usual Input/Output related exceptions.
471 * @throws ClassNotFoundException Class of a serialized object cannot be
472 * found.
473 */
474 private final Object readObject(Class<?> type)
475 throws IOException, ClassNotFoundException
476 {
477 if (enableOverride) {
478 return readObjectOverride();
479 }
480
481 if (! (type == Object.class || type == String.class))
482 throw new AssertionError("internal error");
483
484 // if nested read, passHandle contains handle of enclosing object
485 int outerHandle = passHandle;
486 try {
487 Object obj = readObject0(type, false);
488 handles.markDependency(outerHandle, passHandle);
489 ClassNotFoundException ex = handles.lookupException(passHandle);
490 if (ex != null) {
491 throw ex;
492 }
493 if (depth == 0) {
494 vlist.doCallbacks();
495 freeze();
496 }
497 return obj;
498 } finally {
499 passHandle = outerHandle;
500 if (closed && depth == 0) {
501 clear();
502 }
503 }
504 }
505
506 /**
507 * This method is called by trusted subclasses of ObjectInputStream that
508 * constructed ObjectInputStream using the protected no-arg constructor.
509 * The subclass is expected to provide an override method with the modifier
510 * "final".
511 *
512 * @return the Object read from the stream.
513 * @throws ClassNotFoundException Class definition of a serialized object
514 * cannot be found.
515 * @throws OptionalDataException Primitive data was found in the stream
516 * instead of objects.
517 * @throws IOException if I/O errors occurred while reading from the
518 * underlying stream
519 * @see #ObjectInputStream()
520 * @see #readObject()
521 * @since 1.2
522 */
523 protected Object readObjectOverride()
524 throws IOException, ClassNotFoundException
525 {
526 return null;
527 }
528
529 /**
530 * Reads an "unshared" object from the ObjectInputStream. This method is
531 * identical to readObject, except that it prevents subsequent calls to
532 * readObject and readUnshared from returning additional references to the
533 * deserialized instance obtained via this call. Specifically:
534 * <ul>
535 * <li>If readUnshared is called to deserialize a back-reference (the
536 * stream representation of an object which has been written
537 * previously to the stream), an ObjectStreamException will be
538 * thrown.
539 *
540 * <li>If readUnshared returns successfully, then any subsequent attempts
541 * to deserialize back-references to the stream handle deserialized
542 * by readUnshared will cause an ObjectStreamException to be thrown.
543 * </ul>
544 * Deserializing an object via readUnshared invalidates the stream handle
545 * associated with the returned object. Note that this in itself does not
546 * always guarantee that the reference returned by readUnshared is unique;
547 * the deserialized object may define a readResolve method which returns an
548 * object visible to other parties, or readUnshared may return a Class
549 * object or enum constant obtainable elsewhere in the stream or through
550 * external means. If the deserialized object defines a readResolve method
551 * and the invocation of that method returns an array, then readUnshared
552 * returns a shallow clone of that array; this guarantees that the returned
553 * array object is unique and cannot be obtained a second time from an
554 * invocation of readObject or readUnshared on the ObjectInputStream,
555 * even if the underlying data stream has been manipulated.
556 *
557 * <p>The deserialization filter, when not {@code null}, is invoked for
558 * each object (regular or class) read to reconstruct the root object.
559 * See {@link #setObjectInputFilter(ObjectInputFilter) setObjectInputFilter} for details.
560 *
561 * @return reference to deserialized object
562 * @throws ClassNotFoundException if class of an object to deserialize
563 * cannot be found
564 * @throws StreamCorruptedException if control information in the stream
565 * is inconsistent
566 * @throws ObjectStreamException if object to deserialize has already
567 * appeared in stream
568 * @throws OptionalDataException if primitive data is next in stream
569 * @throws IOException if an I/O error occurs during deserialization
570 * @since 1.4
571 */
572 public Object readUnshared() throws IOException, ClassNotFoundException {
573 // if nested read, passHandle contains handle of enclosing object
574 int outerHandle = passHandle;
575 try {
576 Object obj = readObject0(Object.class, true);
577 handles.markDependency(outerHandle, passHandle);
578 ClassNotFoundException ex = handles.lookupException(passHandle);
579 if (ex != null) {
580 throw ex;
581 }
582 if (depth == 0) {
583 vlist.doCallbacks();
584 freeze();
585 }
586 return obj;
587 } finally {
588 passHandle = outerHandle;
589 if (closed && depth == 0) {
590 clear();
591 }
592 }
593 }
594
595 /**
596 * Read the non-static and non-transient fields of the current class from
597 * this stream. This may only be called from the readObject method of the
598 * class being deserialized. It will throw the NotActiveException if it is
599 * called otherwise.
600 *
601 * @throws ClassNotFoundException if the class of a serialized object
602 * could not be found.
603 * @throws IOException if an I/O error occurs.
604 * @throws NotActiveException if the stream is not currently reading
605 * objects.
606 */
607 public void defaultReadObject()
608 throws IOException, ClassNotFoundException
609 {
610 SerialCallbackContext ctx = curContext;
611 if (ctx == null) {
612 throw new NotActiveException("not in call to readObject");
613 }
614 Object curObj = ctx.getObj();
615 ObjectStreamClass curDesc = ctx.getDesc();
616 bin.setBlockDataMode(false);
617
618 // Read fields of the current descriptor into a new FieldValues
619 FieldValues values = new FieldValues(curDesc, true);
620 if (curObj != null) {
621 values.defaultCheckFieldValues(curObj);
622 values.defaultSetFieldValues(curObj);
623 }
624 bin.setBlockDataMode(true);
625 if (!curDesc.hasWriteObjectData()) {
626 /*
627 * Fix for 4360508: since stream does not contain terminating
628 * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
629 * knows to simulate end-of-custom-data behavior.
630 */
631 defaultDataEnd = true;
632 }
633 ClassNotFoundException ex = handles.lookupException(passHandle);
634 if (ex != null) {
635 throw ex;
636 }
637 }
638
639 /**
640 * Reads the persistent fields from the stream and makes them available by
641 * name.
642 *
643 * @return the {@code GetField} object representing the persistent
644 * fields of the object being deserialized
645 * @throws ClassNotFoundException if the class of a serialized object
646 * could not be found.
647 * @throws IOException if an I/O error occurs.
648 * @throws NotActiveException if the stream is not currently reading
649 * objects.
650 * @since 1.2
651 */
652 public ObjectInputStream.GetField readFields()
653 throws IOException, ClassNotFoundException
654 {
655 SerialCallbackContext ctx = curContext;
656 if (ctx == null) {
657 throw new NotActiveException("not in call to readObject");
658 }
659 ctx.checkAndSetUsed();
660 ObjectStreamClass curDesc = ctx.getDesc();
661 bin.setBlockDataMode(false);
662 // Read fields of the current descriptor into a new FieldValues
663 FieldValues values = new FieldValues(curDesc, false);
664 bin.setBlockDataMode(true);
665 if (!curDesc.hasWriteObjectData()) {
666 /*
667 * Fix for 4360508: since stream does not contain terminating
668 * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
669 * knows to simulate end-of-custom-data behavior.
670 */
671 defaultDataEnd = true;
672 }
673 return values;
674 }
675
676 /**
677 * Register an object to be validated before the graph is returned. While
678 * similar to resolveObject these validations are called after the entire
679 * graph has been reconstituted. Typically, a readObject method will
680 * register the object with the stream so that when all of the objects are
681 * restored a final set of validations can be performed.
682 *
683 * @param obj the object to receive the validation callback.
684 * @param prio controls the order of callbacks; zero is a good default.
685 * Use higher numbers to be called back earlier, lower numbers for
686 * later callbacks. Within a priority, callbacks are processed in
687 * no particular order.
688 * @throws NotActiveException The stream is not currently reading objects
689 * so it is invalid to register a callback.
690 * @throws InvalidObjectException The validation object is null.
691 */
692 public void registerValidation(ObjectInputValidation obj, int prio)
693 throws NotActiveException, InvalidObjectException
694 {
695 if (depth == 0) {
696 throw new NotActiveException("stream inactive");
697 }
698 vlist.register(obj, prio);
699 }
700
701 /**
702 * Load the local class equivalent of the specified stream class
703 * description. Subclasses may implement this method to allow classes to
704 * be fetched from an alternate source.
705 *
706 * <p>The corresponding method in {@code ObjectOutputStream} is
707 * {@code annotateClass}. This method will be invoked only once for
708 * each unique class in the stream. This method can be implemented by
709 * subclasses to use an alternate loading mechanism but must return a
710 * {@code Class} object. Once returned, if the class is not an array
711 * class, its serialVersionUID is compared to the serialVersionUID of the
712 * serialized class, and if there is a mismatch, the deserialization fails
713 * and an {@link InvalidClassException} is thrown.
714 *
715 * <p>The default implementation of this method in
716 * {@code ObjectInputStream} returns the result of calling
717 * {@snippet lang="java":
718 * Class.forName(desc.getName(), false, loader)
719 * }
720 * where {@code loader} is the first class loader on the current
721 * thread's stack (starting from the currently executing method) that is
722 * neither the {@linkplain ClassLoader#getPlatformClassLoader() platform
723 * class loader} nor its ancestor; otherwise, {@code loader} is the
724 * <em>platform class loader</em>. If this call results in a
725 * {@code ClassNotFoundException} and the name of the passed
726 * {@code ObjectStreamClass} instance is the Java language keyword
727 * for a primitive type or void, then the {@code Class} object
728 * representing that primitive type or void will be returned
729 * (e.g., an {@code ObjectStreamClass} with the name
730 * {@code "int"} will be resolved to {@code Integer.TYPE}).
731 * Otherwise, the {@code ClassNotFoundException} will be thrown to
732 * the caller of this method.
733 *
734 * @param desc an instance of class {@code ObjectStreamClass}
735 * @return a {@code Class} object corresponding to {@code desc}
736 * @throws IOException any of the usual Input/Output exceptions.
737 * @throws ClassNotFoundException if class of a serialized object cannot
738 * be found.
739 */
740 protected Class<?> resolveClass(ObjectStreamClass desc)
741 throws IOException, ClassNotFoundException
742 {
743 String name = desc.getName();
744 try {
745 return Class.forName(name, false, latestUserDefinedLoader());
746 } catch (ClassNotFoundException ex) {
747 Class<?> cl = Class.forPrimitiveName(name);
748 if (cl != null) {
749 return cl;
750 } else {
751 throw ex;
752 }
753 }
754 }
755
756 /**
757 * Returns a proxy class that implements the interfaces named in a proxy
758 * class descriptor; subclasses may implement this method to read custom
759 * data from the stream along with the descriptors for dynamic proxy
760 * classes, allowing them to use an alternate loading mechanism for the
761 * interfaces and the proxy class.
762 *
763 * <p>This method is called exactly once for each unique proxy class
764 * descriptor in the stream.
765 *
766 * <p>The corresponding method in {@code ObjectOutputStream} is
767 * {@code annotateProxyClass}. For a given subclass of
768 * {@code ObjectInputStream} that overrides this method, the
769 * {@code annotateProxyClass} method in the corresponding subclass of
770 * {@code ObjectOutputStream} must write any data or objects read by
771 * this method.
772 *
773 * <p>The default implementation of this method in
774 * {@code ObjectInputStream} returns the result of calling
775 * {@code Proxy.getProxyClass} with the list of {@code Class}
776 * objects for the interfaces that are named in the {@code interfaces}
777 * parameter. The {@code Class} object for each interface name
778 * {@code i} is the value returned by calling
779 * {@snippet lang="java":
780 * Class.forName(i, false, loader)
781 * }
782 * where {@code loader} is the first class loader on the current
783 * thread's stack (starting from the currently executing method) that is
784 * neither the {@linkplain ClassLoader#getPlatformClassLoader() platform
785 * class loader} nor its ancestor; otherwise, {@code loader} is the
786 * <em>platform class loader</em>.
787 * Unless any of the resolved interfaces are non-public, this same value
788 * of {@code loader} is also the class loader passed to
789 * {@code Proxy.getProxyClass}; if non-public interfaces are present,
790 * their class loader is passed instead (if more than one non-public
791 * interface class loader is encountered, an
792 * {@code IllegalAccessError} is thrown).
793 * If {@code Proxy.getProxyClass} throws an
794 * {@code IllegalArgumentException}, {@code resolveProxyClass}
795 * will throw a {@code ClassNotFoundException} containing the
796 * {@code IllegalArgumentException}.
797 *
798 * @param interfaces the list of interface names that were
799 * deserialized in the proxy class descriptor
800 * @return a proxy class for the specified interfaces
801 * @throws IOException any exception thrown by the underlying
802 * {@code InputStream}
803 * @throws ClassNotFoundException if the proxy class or any of the
804 * named interfaces could not be found
805 * @see ObjectOutputStream#annotateProxyClass(Class)
806 * @since 1.3
807 */
808 protected Class<?> resolveProxyClass(String[] interfaces)
809 throws IOException, ClassNotFoundException
810 {
811 ClassLoader latestLoader = latestUserDefinedLoader();
812 ClassLoader nonPublicLoader = null;
813 boolean hasNonPublicInterface = false;
814
815 // define proxy in class loader of non-public interface(s), if any
816 Class<?>[] classObjs = new Class<?>[interfaces.length];
817 for (int i = 0; i < interfaces.length; i++) {
818 Class<?> cl = Class.forName(interfaces[i], false, latestLoader);
819 if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {
820 if (hasNonPublicInterface) {
821 if (nonPublicLoader != cl.getClassLoader()) {
822 throw new IllegalAccessError(
823 "conflicting non-public interface class loaders");
824 }
825 } else {
826 nonPublicLoader = cl.getClassLoader();
827 hasNonPublicInterface = true;
828 }
829 }
830 classObjs[i] = cl;
831 }
832 try {
833 @SuppressWarnings("deprecation")
834 Class<?> proxyClass = Proxy.getProxyClass(
835 hasNonPublicInterface ? nonPublicLoader : latestLoader,
836 classObjs);
837 return proxyClass;
838 } catch (IllegalArgumentException e) {
839 throw new ClassNotFoundException(null, e);
840 }
841 }
842
843 /**
844 * This method will allow trusted subclasses of ObjectInputStream to
845 * substitute one object for another during deserialization. Replacing
846 * objects is disabled until enableResolveObject is called. The
847 * enableResolveObject method checks that the stream requesting to resolve
848 * object can be trusted. Every reference to serializable objects is passed
849 * to resolveObject. To ensure that the private state of objects is not
850 * unintentionally exposed only trusted streams may use resolveObject.
851 *
852 * <p>This method is called after an object has been read but before it is
853 * returned from readObject. The default resolveObject method just returns
854 * the same object.
855 *
856 * <p>When a subclass is replacing objects it must ensure that the
857 * substituted object is compatible with every field where the reference
858 * will be stored. Objects whose type is not a subclass of the type of the
859 * field or array element abort the deserialization by raising an exception
860 * and the object is not be stored.
861 *
862 * <p>This method is called only once when each object is first
863 * encountered. All subsequent references to the object will be redirected
864 * to the new object.
865 *
866 * @param obj object to be substituted
867 * @return the substituted object
868 * @throws IOException Any of the usual Input/Output exceptions.
869 */
870 protected Object resolveObject(Object obj) throws IOException {
871 return obj;
872 }
873
874 /**
875 * Enables the stream to do replacement of objects read from the stream. When
876 * enabled, the {@link #resolveObject} method is called for every object being
877 * deserialized.
878 *
879 * @param enable true for enabling use of {@code resolveObject} for
880 * every object being deserialized
881 * @return the previous setting before this method was invoked
882 */
883 protected boolean enableResolveObject(boolean enable) {
884 if (enable == enableResolve) {
885 return enable;
886 }
887 enableResolve = enable;
888 return !enableResolve;
889 }
890
891 /**
892 * The readStreamHeader method is provided to allow subclasses to read and
893 * verify their own stream headers. It reads and verifies the magic number
894 * and version number.
895 *
896 * @throws IOException if there are I/O errors while reading from the
897 * underlying {@code InputStream}
898 * @throws StreamCorruptedException if control information in the stream
899 * is inconsistent
900 */
901 protected void readStreamHeader()
902 throws IOException, StreamCorruptedException
903 {
904 short s0 = bin.readShort();
905 short s1 = bin.readShort();
906 if (s0 != STREAM_MAGIC || s1 != STREAM_VERSION) {
907 throw new StreamCorruptedException(
908 String.format("invalid stream header: %04X%04X", s0, s1));
909 }
910 }
911
912 /**
913 * Read a class descriptor from the serialization stream. This method is
914 * called when the ObjectInputStream expects a class descriptor as the next
915 * item in the serialization stream. Subclasses of ObjectInputStream may
916 * override this method to read in class descriptors that have been written
917 * in non-standard formats (by subclasses of ObjectOutputStream which have
918 * overridden the {@code writeClassDescriptor} method). By default,
919 * this method reads class descriptors according to the format defined in
920 * the Object Serialization specification.
921 *
922 * @return the class descriptor read
923 * @throws IOException If an I/O error has occurred.
924 * @throws ClassNotFoundException If the Class of a serialized object used
925 * in the class descriptor representation cannot be found
926 * @see java.io.ObjectOutputStream#writeClassDescriptor(java.io.ObjectStreamClass)
927 * @since 1.3
928 */
929 protected ObjectStreamClass readClassDescriptor()
930 throws IOException, ClassNotFoundException
931 {
932 ObjectStreamClass desc = new ObjectStreamClass();
933 desc.readNonProxy(this);
934 return desc;
935 }
936
937 /**
938 * Reads a byte of data. This method will block if no input is available.
939 *
940 * @return the byte read, or -1 if the end of the stream is reached.
941 * @throws IOException {@inheritDoc}
942 */
943 @Override
944 public int read() throws IOException {
945 return bin.read();
946 }
947
948 /**
949 * Reads into an array of bytes. This method will block until some input
950 * is available. Consider using java.io.DataInputStream.readFully to read
951 * exactly 'length' bytes.
952 *
953 * @param buf the buffer into which the data is read
954 * @param off the start offset in the destination array {@code buf}
955 * @param len the maximum number of bytes read
956 * @return the total number of bytes read into the buffer, or
957 * {@code -1} if there is no more data because the end of
958 * the stream has been reached.
959 * @throws NullPointerException if {@code buf} is {@code null}.
960 * @throws IndexOutOfBoundsException if {@code off} is negative,
961 * {@code len} is negative, or {@code len} is greater than
962 * {@code buf.length - off}.
963 * @throws IOException If an I/O error has occurred.
964 * @see java.io.DataInputStream#readFully(byte[],int,int)
965 */
966 @Override
967 public int read(byte[] buf, int off, int len) throws IOException {
968 if (buf == null) {
969 throw new NullPointerException();
970 }
971 Objects.checkFromIndexSize(off, len, buf.length);
972 return bin.read(buf, off, len, false);
973 }
974
975 /**
976 * Returns the number of bytes that can be read without blocking.
977 *
978 * @return the number of available bytes.
979 * @throws IOException if there are I/O errors while reading from the
980 * underlying {@code InputStream}
981 */
982 @Override
983 public int available() throws IOException {
984 return bin.available();
985 }
986
987 /**
988 * {@inheritDoc}
989 *
990 * @throws IOException {@inheritDoc}
991 */
992 @Override
993 public void close() throws IOException {
994 /*
995 * Even if stream already closed, propagate redundant close to
996 * underlying stream to stay consistent with previous implementations.
997 */
998 closed = true;
999 if (depth == 0) {
1000 clear();
1001 }
1002 bin.close();
1003 }
1004
1005 /**
1006 * Reads in a boolean.
1007 *
1008 * @return the boolean read.
1009 * @throws EOFException If end of file is reached.
1010 * @throws IOException If other I/O error has occurred.
1011 */
1012 public boolean readBoolean() throws IOException {
1013 return bin.readBoolean();
1014 }
1015
1016 /**
1017 * Reads an 8-bit byte.
1018 *
1019 * @return the 8-bit byte read.
1020 * @throws EOFException If end of file is reached.
1021 * @throws IOException If other I/O error has occurred.
1022 */
1023 public byte readByte() throws IOException {
1024 return bin.readByte();
1025 }
1026
1027 /**
1028 * Reads an unsigned 8-bit byte.
1029 *
1030 * @return the 8-bit byte read.
1031 * @throws EOFException If end of file is reached.
1032 * @throws IOException If other I/O error has occurred.
1033 */
1034 public int readUnsignedByte() throws IOException {
1035 return bin.readUnsignedByte();
1036 }
1037
1038 /**
1039 * Reads a 16-bit char.
1040 *
1041 * @return the 16-bit char read.
1042 * @throws EOFException If end of file is reached.
1043 * @throws IOException If other I/O error has occurred.
1044 */
1045 public char readChar() throws IOException {
1046 return bin.readChar();
1047 }
1048
1049 /**
1050 * Reads a 16-bit short.
1051 *
1052 * @return the 16-bit short read.
1053 * @throws EOFException If end of file is reached.
1054 * @throws IOException If other I/O error has occurred.
1055 */
1056 public short readShort() throws IOException {
1057 return bin.readShort();
1058 }
1059
1060 /**
1061 * Reads an unsigned 16-bit short.
1062 *
1063 * @return the 16-bit short read.
1064 * @throws EOFException If end of file is reached.
1065 * @throws IOException If other I/O error has occurred.
1066 */
1067 public int readUnsignedShort() throws IOException {
1068 return bin.readUnsignedShort();
1069 }
1070
1071 /**
1072 * Reads a 32-bit int.
1073 *
1074 * @return the 32-bit integer read.
1075 * @throws EOFException If end of file is reached.
1076 * @throws IOException If other I/O error has occurred.
1077 */
1078 public int readInt() throws IOException {
1079 return bin.readInt();
1080 }
1081
1082 /**
1083 * Reads a 64-bit long.
1084 *
1085 * @return the read 64-bit long.
1086 * @throws EOFException If end of file is reached.
1087 * @throws IOException If other I/O error has occurred.
1088 */
1089 public long readLong() throws IOException {
1090 return bin.readLong();
1091 }
1092
1093 /**
1094 * Reads a 32-bit float.
1095 *
1096 * @return the 32-bit float read.
1097 * @throws EOFException If end of file is reached.
1098 * @throws IOException If other I/O error has occurred.
1099 */
1100 public float readFloat() throws IOException {
1101 return bin.readFloat();
1102 }
1103
1104 /**
1105 * Reads a 64-bit double.
1106 *
1107 * @return the 64-bit double read.
1108 * @throws EOFException If end of file is reached.
1109 * @throws IOException If other I/O error has occurred.
1110 */
1111 public double readDouble() throws IOException {
1112 return bin.readDouble();
1113 }
1114
1115 /**
1116 * Reads bytes, blocking until all bytes are read.
1117 *
1118 * @param buf the buffer into which the data is read
1119 * @throws NullPointerException If {@code buf} is {@code null}.
1120 * @throws EOFException If end of file is reached.
1121 * @throws IOException If other I/O error has occurred.
1122 */
1123 public void readFully(byte[] buf) throws IOException {
1124 bin.readFully(buf, 0, buf.length, false);
1125 }
1126
1127 /**
1128 * Reads bytes, blocking until all bytes are read.
1129 *
1130 * @param buf the buffer into which the data is read
1131 * @param off the start offset into the data array {@code buf}
1132 * @param len the maximum number of bytes to read
1133 * @throws NullPointerException If {@code buf} is {@code null}.
1134 * @throws IndexOutOfBoundsException If {@code off} is negative,
1135 * {@code len} is negative, or {@code len} is greater than
1136 * {@code buf.length - off}.
1137 * @throws EOFException If end of file is reached.
1138 * @throws IOException If other I/O error has occurred.
1139 */
1140 public void readFully(byte[] buf, int off, int len) throws IOException {
1141 Objects.checkFromIndexSize(off, len, buf.length);
1142 bin.readFully(buf, off, len, false);
1143 }
1144
1145 /**
1146 * Skips bytes.
1147 *
1148 * @param len the number of bytes to be skipped
1149 * @return the actual number of bytes skipped.
1150 * @throws IOException If an I/O error has occurred.
1151 */
1152 @Override
1153 public int skipBytes(int len) throws IOException {
1154 return bin.skipBytes(len);
1155 }
1156
1157 /**
1158 * Reads in a line that has been terminated by a \n, \r, \r\n or EOF.
1159 *
1160 * @return a String copy of the line.
1161 * @throws IOException if there are I/O errors while reading from the
1162 * underlying {@code InputStream}
1163 * @deprecated This method does not properly convert bytes to characters.
1164 * see DataInputStream for the details and alternatives.
1165 */
1166 @Deprecated
1167 public String readLine() throws IOException {
1168 return bin.readLine();
1169 }
1170
1171 /**
1172 * Reads a String in
1173 * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
1174 * format.
1175 *
1176 * @return the String.
1177 * @throws IOException if there are I/O errors while reading from the
1178 * underlying {@code InputStream}
1179 * @throws UTFDataFormatException if read bytes do not represent a valid
1180 * modified UTF-8 encoding of a string
1181 */
1182 public String readUTF() throws IOException {
1183 return bin.readUTF();
1184 }
1185
1186 /**
1187 * Returns the deserialization filter for this stream.
1188 * The filter is the result of invoking the
1189 * {@link Config#getSerialFilterFactory() JVM-wide filter factory}
1190 * either by the {@linkplain #ObjectInputStream() constructor} or the most recent invocation of
1191 * {@link #setObjectInputFilter setObjectInputFilter}.
1192 *
1193 * @return the deserialization filter for the stream; may be null
1194 * @since 9
1195 */
1196 public final ObjectInputFilter getObjectInputFilter() {
1197 return serialFilter;
1198 }
1199
1200 /**
1201 * Set the deserialization filter for the stream.
1202 *
1203 * The deserialization filter is set to the filter returned by invoking the
1204 * {@linkplain Config#getSerialFilterFactory() JVM-wide filter factory}
1205 * with the {@linkplain #getObjectInputFilter() current filter} and the {@code filter} parameter.
1206 * The current filter was set in the
1207 * {@linkplain #ObjectInputStream() ObjectInputStream constructors} by invoking the
1208 * {@linkplain Config#getSerialFilterFactory() JVM-wide filter factory} and may be {@code null}.
1209 * {@linkplain #setObjectInputFilter(ObjectInputFilter)} This method} can be called
1210 * once and only once before reading any objects from the stream;
1211 * for example, by calling {@link #readObject} or {@link #readUnshared}.
1212 *
1213 * <p>It is not permitted to replace a {@code non-null} filter with a {@code null} filter.
1214 * If the {@linkplain #getObjectInputFilter() current filter} is {@code non-null},
1215 * the value returned from the filter factory must be {@code non-null}.
1216 *
1217 * <p>The filter's {@link ObjectInputFilter#checkInput checkInput} method is called
1218 * for each class and reference in the stream.
1219 * The filter can check any or all of the class, the array length, the number
1220 * of references, the depth of the graph, and the size of the input stream.
1221 * The depth is the number of nested {@linkplain #readObject readObject}
1222 * calls starting with the reading of the root of the graph being deserialized
1223 * and the current object being deserialized.
1224 * The number of references is the cumulative number of objects and references
1225 * to objects already read from the stream including the current object being read.
1226 * The filter is invoked only when reading objects from the stream and not for
1227 * primitives.
1228 * <p>
1229 * If the filter returns {@link ObjectInputFilter.Status#REJECTED Status.REJECTED},
1230 * {@code null} or throws a {@link RuntimeException},
1231 * the active {@code readObject} or {@code readUnshared}
1232 * throws {@link InvalidClassException}, otherwise deserialization
1233 * continues uninterrupted.
1234 *
1235 * @implSpec
1236 * The filter, when not {@code null}, is invoked during {@link #readObject readObject}
1237 * and {@link #readUnshared readUnshared} for each object (regular or class) in the stream.
1238 * Strings are treated as primitives and do not invoke the filter.
1239 * The filter is called for:
1240 * <ul>
1241 * <li>each object reference previously deserialized from the stream
1242 * (class is {@code null}, arrayLength is -1),
1243 * <li>each regular class (class is not {@code null}, arrayLength is -1),
1244 * <li>each interface class explicitly referenced in the stream
1245 * (it is not called for interfaces implemented by classes in the stream),
1246 * <li>each interface of a dynamic proxy and the dynamic proxy class itself
1247 * (class is not {@code null}, arrayLength is -1),
1248 * <li>each array is filtered using the array type and length of the array
1249 * (class is the array type, arrayLength is the requested length),
1250 * <li>each object replaced by its class' {@code readResolve} method
1251 * is filtered using the replacement object's class, if not {@code null},
1252 * and if it is an array, the arrayLength, otherwise -1,
1253 * <li>and each object replaced by {@link #resolveObject resolveObject}
1254 * is filtered using the replacement object's class, if not {@code null},
1255 * and if it is an array, the arrayLength, otherwise -1.
1256 * </ul>
1257 *
1258 * When the {@link ObjectInputFilter#checkInput checkInput} method is invoked
1259 * it is given access to the current class, the array length,
1260 * the current number of references already read from the stream,
1261 * the depth of nested calls to {@link #readObject readObject} or
1262 * {@link #readUnshared readUnshared},
1263 * and the implementation dependent number of bytes consumed from the input stream.
1264 * <p>
1265 * Each call to {@link #readObject readObject} or
1266 * {@link #readUnshared readUnshared} increases the depth by 1
1267 * before reading an object and decreases by 1 before returning
1268 * normally or exceptionally.
1269 * The depth starts at {@code 1} and increases for each nested object and
1270 * decrements when each nested call returns.
1271 * The count of references in the stream starts at {@code 1} and
1272 * is increased before reading an object.
1273 *
1274 * @param filter the filter, may be null
1275 * @throws IllegalStateException if an object has been read,
1276 * if the filter factory returns {@code null} when the
1277 * {@linkplain #getObjectInputFilter() current filter} is non-null, or
1278 * if the filter has already been set.
1279 * @since 9
1280 */
1281 public final void setObjectInputFilter(ObjectInputFilter filter) {
1282 if (totalObjectRefs > 0 && !Caches.SET_FILTER_AFTER_READ) {
1283 throw new IllegalStateException(
1284 "filter can not be set after an object has been read");
1285 }
1286 if (streamFilterSet) {
1287 throw new IllegalStateException("filter can not be set more than once");
1288 }
1289 streamFilterSet = true;
1290 // Delegate to serialFilterFactory to compute stream filter
1291 ObjectInputFilter next = Config.getSerialFilterFactory()
1292 .apply(serialFilter, filter);
1293 if (serialFilter != null && next == null) {
1294 throw new IllegalStateException("filter can not be replaced with null filter");
1295 }
1296 serialFilter = next;
1297 }
1298
1299 /**
1300 * Invokes the deserialization filter if non-null.
1301 *
1302 * If the filter rejects or an exception is thrown, throws InvalidClassException.
1303 *
1304 * Logs and/or commits a {@code DeserializationEvent}, if configured.
1305 *
1306 * @param clazz the class; may be null
1307 * @param arrayLength the array length requested; use {@code -1} if not creating an array
1308 * @throws InvalidClassException if it rejected by the filter or
1309 * a {@link RuntimeException} is thrown
1310 */
1311 private void filterCheck(Class<?> clazz, int arrayLength)
1312 throws InvalidClassException {
1313 // Info about the stream is not available if overridden by subclass, return 0
1314 long bytesRead = (bin == null) ? 0 : bin.getBytesRead();
1315 RuntimeException ex = null;
1316 ObjectInputFilter.Status status = null;
1317
1318 if (serialFilter != null) {
1319 try {
1320 status = serialFilter.checkInput(new FilterValues(clazz, arrayLength,
1321 totalObjectRefs, depth, bytesRead));
1322 } catch (RuntimeException e) {
1323 // Preventive interception of an exception to log
1324 status = ObjectInputFilter.Status.REJECTED;
1325 ex = e;
1326 }
1327 if (Logging.filterLogger != null) {
1328 // Debug logging of filter checks that fail; Tracing for those that succeed
1329 Logging.filterLogger.log(status == null || status == ObjectInputFilter.Status.REJECTED
1330 ? Logger.Level.DEBUG
1331 : Logger.Level.TRACE,
1332 "ObjectInputFilter {0}: {1}, array length: {2}, nRefs: {3}, depth: {4}, bytes: {5}, ex: {6}",
1333 status, clazz, arrayLength, totalObjectRefs, depth, bytesRead,
1334 Objects.toString(ex, "n/a"));
1335 }
1336 }
1337 DeserializationEvent event = new DeserializationEvent();
1338 if (event.shouldCommit()) {
1339 event.filterConfigured = serialFilter != null;
1340 event.filterStatus = status != null ? status.name() : null;
1341 event.type = clazz;
1342 event.arrayLength = arrayLength;
1343 event.objectReferences = totalObjectRefs;
1344 event.depth = depth;
1345 event.bytesRead = bytesRead;
1346 event.exceptionType = ex != null ? ex.getClass() : null;
1347 event.exceptionMessage = ex != null ? ex.getMessage() : null;
1348 event.commit();
1349 }
1350 if (serialFilter != null && (status == null || status == ObjectInputFilter.Status.REJECTED)) {
1351 throw new InvalidClassException("filter status: " + status, ex);
1352 }
1353 }
1354
1355 /**
1356 * Checks the given array type and length to ensure that creation of such
1357 * an array is permitted by this ObjectInputStream. The arrayType argument
1358 * must represent an actual array type.
1359 *
1360 * This private method is called via SharedSecrets.
1361 *
1362 * @param arrayType the array type
1363 * @param arrayLength the array length
1364 * @throws NullPointerException if arrayType is null
1365 * @throws IllegalArgumentException if arrayType isn't actually an array type
1366 * @throws StreamCorruptedException if arrayLength is negative
1367 * @throws InvalidClassException if the filter rejects creation
1368 */
1369 private void checkArray(Class<?> arrayType, int arrayLength) throws ObjectStreamException {
1370 if (! arrayType.isArray()) {
1371 throw new IllegalArgumentException("not an array type");
1372 }
1373
1374 if (arrayLength < 0) {
1375 throw new StreamCorruptedException("Array length is negative");
1376 }
1377
1378 filterCheck(arrayType, arrayLength);
1379 }
1380
1381 /**
1382 * Provide access to the persistent fields read from the input stream.
1383 */
1384 public abstract static class GetField {
1385 /**
1386 * Constructor for subclasses to call.
1387 */
1388 public GetField() {}
1389
1390 /**
1391 * Get the ObjectStreamClass that describes the fields in the stream.
1392 *
1393 * @return the descriptor class that describes the serializable fields
1394 */
1395 public abstract ObjectStreamClass getObjectStreamClass();
1396
1397 /**
1398 * Return true if the named field is defaulted and has no value in this
1399 * stream.
1400 *
1401 * @param name the name of the field
1402 * @return true, if and only if the named field is defaulted
1403 * @throws IOException if there are I/O errors while reading from
1404 * the underlying {@code InputStream}
1405 * @throws IllegalArgumentException if {@code name} does not
1406 * correspond to a serializable field
1407 */
1408 public abstract boolean defaulted(String name) throws IOException;
1409
1410 /**
1411 * Get the value of the named boolean field from the persistent field.
1412 *
1413 * @param name the name of the field
1414 * @param val the default value to use if {@code name} does not
1415 * have a value
1416 * @return the value of the named {@code boolean} field
1417 * @throws IOException if there are I/O errors while reading from the
1418 * underlying {@code InputStream}
1419 * @throws IllegalArgumentException if type of {@code name} is
1420 * not serializable or if the field type is incorrect
1421 */
1422 public abstract boolean get(String name, boolean val)
1423 throws IOException;
1424
1425 /**
1426 * Get the value of the named byte field from the persistent field.
1427 *
1428 * @param name the name of the field
1429 * @param val the default value to use if {@code name} does not
1430 * have a value
1431 * @return the value of the named {@code byte} field
1432 * @throws IOException if there are I/O errors while reading from the
1433 * underlying {@code InputStream}
1434 * @throws IllegalArgumentException if type of {@code name} is
1435 * not serializable or if the field type is incorrect
1436 */
1437 public abstract byte get(String name, byte val) throws IOException;
1438
1439 /**
1440 * Get the value of the named char field from the persistent field.
1441 *
1442 * @param name the name of the field
1443 * @param val the default value to use if {@code name} does not
1444 * have a value
1445 * @return the value of the named {@code char} field
1446 * @throws IOException if there are I/O errors while reading from the
1447 * underlying {@code InputStream}
1448 * @throws IllegalArgumentException if type of {@code name} is
1449 * not serializable or if the field type is incorrect
1450 */
1451 public abstract char get(String name, char val) throws IOException;
1452
1453 /**
1454 * Get the value of the named short field from the persistent field.
1455 *
1456 * @param name the name of the field
1457 * @param val the default value to use if {@code name} does not
1458 * have a value
1459 * @return the value of the named {@code short} field
1460 * @throws IOException if there are I/O errors while reading from the
1461 * underlying {@code InputStream}
1462 * @throws IllegalArgumentException if type of {@code name} is
1463 * not serializable or if the field type is incorrect
1464 */
1465 public abstract short get(String name, short val) throws IOException;
1466
1467 /**
1468 * Get the value of the named int field from the persistent field.
1469 *
1470 * @param name the name of the field
1471 * @param val the default value to use if {@code name} does not
1472 * have a value
1473 * @return the value of the named {@code int} field
1474 * @throws IOException if there are I/O errors while reading from the
1475 * underlying {@code InputStream}
1476 * @throws IllegalArgumentException if type of {@code name} is
1477 * not serializable or if the field type is incorrect
1478 */
1479 public abstract int get(String name, int val) throws IOException;
1480
1481 /**
1482 * Get the value of the named long field from the persistent field.
1483 *
1484 * @param name the name of the field
1485 * @param val the default value to use if {@code name} does not
1486 * have a value
1487 * @return the value of the named {@code long} field
1488 * @throws IOException if there are I/O errors while reading from the
1489 * underlying {@code InputStream}
1490 * @throws IllegalArgumentException if type of {@code name} is
1491 * not serializable or if the field type is incorrect
1492 */
1493 public abstract long get(String name, long val) throws IOException;
1494
1495 /**
1496 * Get the value of the named float field from the persistent field.
1497 *
1498 * @param name the name of the field
1499 * @param val the default value to use if {@code name} does not
1500 * have a value
1501 * @return the value of the named {@code float} field
1502 * @throws IOException if there are I/O errors while reading from the
1503 * underlying {@code InputStream}
1504 * @throws IllegalArgumentException if type of {@code name} is
1505 * not serializable or if the field type is incorrect
1506 */
1507 public abstract float get(String name, float val) throws IOException;
1508
1509 /**
1510 * Get the value of the named double field from the persistent field.
1511 *
1512 * @param name the name of the field
1513 * @param val the default value to use if {@code name} does not
1514 * have a value
1515 * @return the value of the named {@code double} field
1516 * @throws IOException if there are I/O errors while reading from the
1517 * underlying {@code InputStream}
1518 * @throws IllegalArgumentException if type of {@code name} is
1519 * not serializable or if the field type is incorrect
1520 */
1521 public abstract double get(String name, double val) throws IOException;
1522
1523 /**
1524 * Get the value of the named Object field from the persistent field.
1525 *
1526 * @param name the name of the field
1527 * @param val the default value to use if {@code name} does not
1528 * have a value
1529 * @return the value of the named {@code Object} field
1530 * @throws ClassNotFoundException Class of a serialized object cannot be found.
1531 * @throws IOException if there are I/O errors while reading from the
1532 * underlying {@code InputStream}
1533 * @throws IllegalArgumentException if type of {@code name} is
1534 * not serializable or if the field type is incorrect
1535 */
1536 public abstract Object get(String name, Object val) throws IOException, ClassNotFoundException;
1537 }
1538
1539 /**
1540 * Clears internal data structures.
1541 */
1542 private void clear() {
1543 handles.clear();
1544 vlist.clear();
1545 }
1546
1547 /**
1548 * Underlying readObject implementation.
1549 * @param type a type expected to be deserialized; non-null
1550 * @param unshared true if the object can not be a reference to a shared object, otherwise false
1551 */
1552 private Object readObject0(Class<?> type, boolean unshared) throws IOException {
1553 boolean oldMode = bin.getBlockDataMode();
1554 if (oldMode) {
1555 int remain = bin.currentBlockRemaining();
1556 if (remain > 0) {
1557 throw new OptionalDataException(remain);
1558 } else if (defaultDataEnd) {
1559 /*
1560 * Fix for 4360508: stream is currently at the end of a field
1561 * value block written via default serialization; since there
1562 * is no terminating TC_ENDBLOCKDATA tag, simulate
1563 * end-of-custom-data behavior explicitly.
1564 */
1565 throw new OptionalDataException(true);
1566 }
1567 bin.setBlockDataMode(false);
1568 }
1569
1570 byte tc;
1571 while ((tc = bin.peekByte()) == TC_RESET) {
1572 bin.readByte();
1573 handleReset();
1574 }
1575
1576 depth++;
1577 totalObjectRefs++;
1578 try {
1579 switch (tc) {
1580 case TC_NULL:
1581 return readNull();
1582
1583 case TC_REFERENCE:
1584 // check the type of the existing object
1585 return type.cast(readHandle(unshared));
1586
1587 case TC_CLASS:
1588 if (type == String.class) {
1589 throw new ClassCastException("Cannot cast a class to java.lang.String");
1590 }
1591 return readClass(unshared);
1592
1593 case TC_CLASSDESC:
1594 case TC_PROXYCLASSDESC:
1595 if (type == String.class) {
1596 throw new ClassCastException("Cannot cast a class to java.lang.String");
1597 }
1598 return readClassDesc(unshared);
1599
1600 case TC_STRING:
1601 case TC_LONGSTRING:
1602 return checkResolve(readString(unshared));
1603
1604 case TC_ARRAY:
1605 if (type == String.class) {
1606 throw new ClassCastException("Cannot cast an array to java.lang.String");
1607 }
1608 return checkResolve(readArray(unshared));
1609
1610 case TC_ENUM:
1611 if (type == String.class) {
1612 throw new ClassCastException("Cannot cast an enum to java.lang.String");
1613 }
1614 return checkResolve(readEnum(unshared));
1615
1616 case TC_OBJECT:
1617 if (type == String.class) {
1618 throw new ClassCastException("Cannot cast an object to java.lang.String");
1619 }
1620 return checkResolve(readOrdinaryObject(unshared));
1621
1622 case TC_EXCEPTION:
1623 if (type == String.class) {
1624 throw new ClassCastException("Cannot cast an exception to java.lang.String");
1625 }
1626 IOException ex = readFatalException();
1627 throw new WriteAbortedException("writing aborted", ex);
1628
1629 case TC_BLOCKDATA:
1630 case TC_BLOCKDATALONG:
1631 if (oldMode) {
1632 bin.setBlockDataMode(true);
1633 bin.peek(); // force header read
1634 throw new OptionalDataException(
1635 bin.currentBlockRemaining());
1636 } else {
1637 throw new StreamCorruptedException(
1638 "unexpected block data");
1639 }
1640
1641 case TC_ENDBLOCKDATA:
1642 if (oldMode) {
1643 throw new OptionalDataException(true);
1644 } else {
1645 throw new StreamCorruptedException(
1646 "unexpected end of block data");
1647 }
1648
1649 default:
1650 throw new StreamCorruptedException(
1651 String.format("invalid type code: %02X", tc));
1652 }
1653 } finally {
1654 depth--;
1655 bin.setBlockDataMode(oldMode);
1656 }
1657 }
1658
1659 /**
1660 * If resolveObject has been enabled and given object does not have an
1661 * exception associated with it, calls resolveObject to determine
1662 * replacement for object, and updates handle table accordingly. Returns
1663 * replacement object, or echoes provided object if no replacement
1664 * occurred. Expects that passHandle is set to given object's handle prior
1665 * to calling this method.
1666 */
1667 private Object checkResolve(Object obj) throws IOException {
1668 if (!enableResolve || handles.lookupException(passHandle) != null) {
1669 return obj;
1670 }
1671 Object rep = resolveObject(obj);
1672 if (rep != obj) {
1673 // The type of the original object has been filtered but resolveObject
1674 // may have replaced it; filter the replacement's type
1675 if (rep != null) {
1676 if (rep.getClass().isArray()) {
1677 filterCheck(rep.getClass(), Array.getLength(rep));
1678 } else {
1679 filterCheck(rep.getClass(), -1);
1680 }
1681 }
1682 handles.setObject(passHandle, rep);
1683 }
1684 return rep;
1685 }
1686
1687 /**
1688 * Reads string without allowing it to be replaced in stream. Called from
1689 * within ObjectStreamClass.read().
1690 */
1691 String readTypeString() throws IOException {
1692 int oldHandle = passHandle;
1693 try {
1694 byte tc = bin.peekByte();
1695 return switch (tc) {
1696 case TC_NULL -> (String) readNull();
1697 case TC_REFERENCE -> (String) readHandle(false);
1698 case TC_STRING, TC_LONGSTRING -> readString(false);
1699 default -> throw new StreamCorruptedException(
1700 String.format("invalid type code: %02X", tc));
1701 };
1702 } finally {
1703 passHandle = oldHandle;
1704 }
1705 }
1706
1707 /**
1708 * Reads in null code, sets passHandle to NULL_HANDLE and returns null.
1709 */
1710 private Object readNull() throws IOException {
1711 if (bin.readByte() != TC_NULL) {
1712 throw new InternalError();
1713 }
1714 passHandle = NULL_HANDLE;
1715 return null;
1716 }
1717
1718 /**
1719 * Reads in object handle, sets passHandle to the read handle, and returns
1720 * object associated with the handle.
1721 */
1722 private Object readHandle(boolean unshared) throws IOException {
1723 if (bin.readByte() != TC_REFERENCE) {
1724 throw new InternalError();
1725 }
1726 passHandle = bin.readInt() - baseWireHandle;
1727 if (passHandle < 0 || passHandle >= handles.size()) {
1728 throw new StreamCorruptedException(
1729 String.format("invalid handle value: %08X", passHandle +
1730 baseWireHandle));
1731 }
1732 if (unshared) {
1733 // REMIND: what type of exception to throw here?
1734 throw new InvalidObjectException(
1735 "cannot read back reference as unshared");
1736 }
1737
1738 Object obj = handles.lookupObject(passHandle);
1739 if (obj == unsharedMarker) {
1740 // REMIND: what type of exception to throw here?
1741 throw new InvalidObjectException(
1742 "cannot read back reference to unshared object");
1743 }
1744 filterCheck(null, -1); // just a check for number of references, depth, no class
1745 return obj;
1746 }
1747
1748 /**
1749 * Reads in and returns class object. Sets passHandle to class object's
1750 * assigned handle. Returns null if class is unresolvable (in which case a
1751 * ClassNotFoundException will be associated with the class' handle in the
1752 * handle table).
1753 */
1754 private Class<?> readClass(boolean unshared) throws IOException {
1755 if (bin.readByte() != TC_CLASS) {
1756 throw new InternalError();
1757 }
1758 ObjectStreamClass desc = readClassDesc(false);
1759 Class<?> cl = desc.forClass();
1760 passHandle = handles.assign(unshared ? unsharedMarker : cl);
1761
1762 ClassNotFoundException resolveEx = desc.getResolveException();
1763 if (resolveEx != null) {
1764 handles.markException(passHandle, resolveEx);
1765 }
1766
1767 handles.finish(passHandle);
1768 return cl;
1769 }
1770
1771 /**
1772 * Reads in and returns (possibly null) class descriptor. Sets passHandle
1773 * to class descriptor's assigned handle. If class descriptor cannot be
1774 * resolved to a class in the local VM, a ClassNotFoundException is
1775 * associated with the class descriptor's handle.
1776 */
1777 private ObjectStreamClass readClassDesc(boolean unshared)
1778 throws IOException
1779 {
1780 byte tc = bin.peekByte();
1781
1782 return switch (tc) {
1783 case TC_NULL -> (ObjectStreamClass) readNull();
1784 case TC_PROXYCLASSDESC -> readProxyDesc(unshared);
1785 case TC_CLASSDESC -> readNonProxyDesc(unshared);
1786 case TC_REFERENCE -> {
1787 var d = (ObjectStreamClass) readHandle(unshared);
1788 // Should only reference initialized class descriptors
1789 d.checkInitialized();
1790 yield d;
1791 }
1792 default -> throw new StreamCorruptedException(
1793 String.format("invalid type code: %02X", tc));
1794 };
1795 }
1796
1797 /**
1798 * Reads in and returns class descriptor for a dynamic proxy class. Sets
1799 * passHandle to proxy class descriptor's assigned handle. If proxy class
1800 * descriptor cannot be resolved to a class in the local VM, a
1801 * ClassNotFoundException is associated with the descriptor's handle.
1802 */
1803 private ObjectStreamClass readProxyDesc(boolean unshared)
1804 throws IOException
1805 {
1806 if (bin.readByte() != TC_PROXYCLASSDESC) {
1807 throw new InternalError();
1808 }
1809
1810 ObjectStreamClass desc = new ObjectStreamClass();
1811 int descHandle = handles.assign(unshared ? unsharedMarker : desc);
1812 passHandle = NULL_HANDLE;
1813
1814 int numIfaces = bin.readInt();
1815 if (numIfaces > 65535) {
1816 // Report specification limit exceeded
1817 throw new InvalidObjectException("interface limit exceeded: " +
1818 numIfaces +
1819 ", limit: " + Caches.PROXY_INTERFACE_LIMIT);
1820 }
1821 String[] ifaces = new String[numIfaces];
1822 for (int i = 0; i < numIfaces; i++) {
1823 ifaces[i] = bin.readUTF();
1824 }
1825
1826 // Recheck against implementation limit and throw with interface names
1827 if (numIfaces > Caches.PROXY_INTERFACE_LIMIT) {
1828 throw new InvalidObjectException("interface limit exceeded: " +
1829 numIfaces +
1830 ", limit: " + Caches.PROXY_INTERFACE_LIMIT +
1831 "; " + Arrays.toString(ifaces));
1832 }
1833 Class<?> cl = null;
1834 ClassNotFoundException resolveEx = null;
1835 bin.setBlockDataMode(true);
1836 try {
1837 if ((cl = resolveProxyClass(ifaces)) == null) {
1838 resolveEx = new ClassNotFoundException("null class");
1839 } else if (!Proxy.isProxyClass(cl)) {
1840 throw new InvalidClassException("Not a proxy");
1841 } else {
1842 // Filter the interfaces
1843 for (Class<?> clazz : cl.getInterfaces()) {
1844 filterCheck(clazz, -1);
1845 }
1846 }
1847 } catch (ClassNotFoundException ex) {
1848 resolveEx = ex;
1849 } catch (IllegalAccessError aie) {
1850 throw new InvalidClassException(aie.getMessage(), aie);
1851 } catch (OutOfMemoryError oome) {
1852 throw genInvalidObjectException(oome, ifaces);
1853 }
1854
1855 // Call filterCheck on the class before reading anything else
1856 filterCheck(cl, -1);
1857
1858 skipCustomData();
1859
1860 try {
1861 totalObjectRefs++;
1862 depth++;
1863 desc.initProxy(cl, resolveEx, readClassDesc(false));
1864 } catch (OutOfMemoryError oome) {
1865 throw genInvalidObjectException(oome, ifaces);
1866 } finally {
1867 depth--;
1868 }
1869
1870 handles.finish(descHandle);
1871 passHandle = descHandle;
1872 return desc;
1873 }
1874
1875 // Generate an InvalidObjectException for an OutOfMemoryError
1876 // Use String.concat() to avoid string formatting invoke dynamic
1877 private static InvalidObjectException genInvalidObjectException(OutOfMemoryError oome,
1878 String[] ifaces) {
1879 return new InvalidObjectException("Proxy interface limit exceeded: "
1880 .concat(Arrays.toString(ifaces)), oome);
1881 }
1882
1883 /**
1884 * Reads in and returns class descriptor for a class that is not a dynamic
1885 * proxy class. Sets passHandle to class descriptor's assigned handle. If
1886 * class descriptor cannot be resolved to a class in the local VM, a
1887 * ClassNotFoundException is associated with the descriptor's handle.
1888 */
1889 private ObjectStreamClass readNonProxyDesc(boolean unshared)
1890 throws IOException
1891 {
1892 if (bin.readByte() != TC_CLASSDESC) {
1893 throw new InternalError();
1894 }
1895
1896 ObjectStreamClass desc = new ObjectStreamClass();
1897 int descHandle = handles.assign(unshared ? unsharedMarker : desc);
1898 passHandle = NULL_HANDLE;
1899
1900 ObjectStreamClass readDesc;
1901 try {
1902 readDesc = readClassDescriptor();
1903 } catch (ClassNotFoundException ex) {
1904 throw new InvalidClassException("failed to read class descriptor",
1905 ex);
1906 }
1907
1908 Class<?> cl = null;
1909 ClassNotFoundException resolveEx = null;
1910 bin.setBlockDataMode(true);
1911 try {
1912 if ((cl = resolveClass(readDesc)) == null) {
1913 resolveEx = new ClassNotFoundException("null class");
1914 }
1915 } catch (ClassNotFoundException ex) {
1916 resolveEx = ex;
1917 }
1918
1919 // Call filterCheck on the class before reading anything else
1920 filterCheck(cl, -1);
1921
1922 skipCustomData();
1923
1924 try {
1925 totalObjectRefs++;
1926 depth++;
1927 desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false));
1928
1929 if (cl != null) {
1930 // Check that serial filtering has been done on the local class descriptor's superclass,
1931 // in case it does not appear in the stream.
1932
1933 // Find the next super descriptor that has a local class descriptor.
1934 // Descriptors for which there is no local class are ignored.
1935 ObjectStreamClass superLocal = null;
1936 for (ObjectStreamClass sDesc = desc.getSuperDesc(); sDesc != null; sDesc = sDesc.getSuperDesc()) {
1937 if ((superLocal = sDesc.getLocalDesc()) != null) {
1938 break;
1939 }
1940 }
1941
1942 // Scan local descriptor superclasses for a match with the local descriptor of the super found above.
1943 // For each super descriptor before the match, invoke the serial filter on the class.
1944 // The filter is invoked for each class that has not already been filtered
1945 // but would be filtered if the instance had been serialized by this Java runtime.
1946 for (ObjectStreamClass lDesc = desc.getLocalDesc().getSuperDesc();
1947 lDesc != null && lDesc != superLocal;
1948 lDesc = lDesc.getSuperDesc()) {
1949 filterCheck(lDesc.forClass(), -1);
1950 }
1951 }
1952 } finally {
1953 depth--;
1954 }
1955
1956 handles.finish(descHandle);
1957 passHandle = descHandle;
1958
1959 return desc;
1960 }
1961
1962 /**
1963 * Reads in and returns new string. Sets passHandle to new string's
1964 * assigned handle.
1965 */
1966 private String readString(boolean unshared) throws IOException {
1967 byte tc = bin.readByte();
1968 String str = switch (tc) {
1969 case TC_STRING -> bin.readUTF();
1970 case TC_LONGSTRING -> bin.readLongUTF();
1971 default -> throw new StreamCorruptedException(
1972 String.format("invalid type code: %02X", tc));
1973 };
1974 passHandle = handles.assign(unshared ? unsharedMarker : str);
1975 handles.finish(passHandle);
1976 return str;
1977 }
1978
1979 /**
1980 * Reads in and returns array object, or null if array class is
1981 * unresolvable. Sets passHandle to array's assigned handle.
1982 */
1983 private Object readArray(boolean unshared) throws IOException {
1984 if (bin.readByte() != TC_ARRAY) {
1985 throw new InternalError();
1986 }
1987
1988 ObjectStreamClass desc = readClassDesc(false);
1989 int len = bin.readInt();
1990 if (len < 0) {
1991 throw new StreamCorruptedException("Array length is negative");
1992 }
1993 filterCheck(desc.forClass(), len);
1994
1995 Object array = null;
1996 Class<?> cl, ccl = null;
1997 if ((cl = desc.forClass()) != null) {
1998 ccl = cl.getComponentType();
1999 array = Array.newInstance(ccl, len);
2000 }
2001
2002 int arrayHandle = handles.assign(unshared ? unsharedMarker : array);
2003 ClassNotFoundException resolveEx = desc.getResolveException();
2004 if (resolveEx != null) {
2005 handles.markException(arrayHandle, resolveEx);
2006 }
2007
2008 if (ccl == null) {
2009 for (int i = 0; i < len; i++) {
2010 readObject0(Object.class, false);
2011 }
2012 } else if (ccl.isPrimitive()) {
2013 if (ccl == Integer.TYPE) {
2014 bin.readInts((int[]) array, 0, len);
2015 } else if (ccl == Byte.TYPE) {
2016 bin.readFully((byte[]) array, 0, len, true);
2017 } else if (ccl == Long.TYPE) {
2018 bin.readLongs((long[]) array, 0, len);
2019 } else if (ccl == Float.TYPE) {
2020 bin.readFloats((float[]) array, 0, len);
2021 } else if (ccl == Double.TYPE) {
2022 bin.readDoubles((double[]) array, 0, len);
2023 } else if (ccl == Short.TYPE) {
2024 bin.readShorts((short[]) array, 0, len);
2025 } else if (ccl == Character.TYPE) {
2026 bin.readChars((char[]) array, 0, len);
2027 } else if (ccl == Boolean.TYPE) {
2028 bin.readBooleans((boolean[]) array, 0, len);
2029 } else {
2030 throw new InternalError();
2031 }
2032 } else {
2033 Object[] oa = (Object[]) array;
2034 for (int i = 0; i < len; i++) {
2035 oa[i] = readObject0(Object.class, false);
2036 handles.markDependency(arrayHandle, passHandle);
2037 }
2038 }
2039
2040 handles.finish(arrayHandle);
2041 passHandle = arrayHandle;
2042 return array;
2043 }
2044
2045 /**
2046 * Reads in and returns enum constant, or null if enum type is
2047 * unresolvable. Sets passHandle to enum constant's assigned handle.
2048 */
2049 private Enum<?> readEnum(boolean unshared) throws IOException {
2050 if (bin.readByte() != TC_ENUM) {
2051 throw new InternalError();
2052 }
2053
2054 ObjectStreamClass desc = readClassDesc(false);
2055 if (!desc.isEnum()) {
2056 throw new InvalidClassException("non-enum class: " + desc);
2057 }
2058
2059 int enumHandle = handles.assign(unshared ? unsharedMarker : null);
2060 ClassNotFoundException resolveEx = desc.getResolveException();
2061 if (resolveEx != null) {
2062 handles.markException(enumHandle, resolveEx);
2063 }
2064
2065 String name = readString(false);
2066 Enum<?> result = null;
2067 Class<?> cl = desc.forClass();
2068 if (cl != null) {
2069 try {
2070 @SuppressWarnings("unchecked")
2071 Enum<?> en = Enum.valueOf((Class)cl, name);
2072 result = en;
2073 } catch (IllegalArgumentException ex) {
2074 throw new InvalidObjectException("enum constant " +
2075 name + " does not exist in " + cl, ex);
2076 }
2077 if (!unshared) {
2078 handles.setObject(enumHandle, result);
2079 }
2080 }
2081
2082 handles.finish(enumHandle);
2083 passHandle = enumHandle;
2084 return result;
2085 }
2086
2087 /**
2088 * Reads and returns "ordinary" (i.e., not a String, Class,
2089 * ObjectStreamClass, array, or enum constant) object, or null if object's
2090 * class is unresolvable (in which case a ClassNotFoundException will be
2091 * associated with object's handle). Sets passHandle to object's assigned
2092 * handle.
2093 */
2094 private Object readOrdinaryObject(boolean unshared)
2095 throws IOException
2096 {
2097 if (bin.readByte() != TC_OBJECT) {
2098 throw new InternalError();
2099 }
2100
2101 ObjectStreamClass desc = readClassDesc(false);
2102 desc.checkDeserialize();
2103
2104 Class<?> cl = desc.forClass();
2105 if (cl == String.class || cl == Class.class
2106 || cl == ObjectStreamClass.class) {
2107 throw new InvalidClassException("invalid class descriptor");
2108 }
2109
2110 Object obj;
2111 try {
2112 obj = desc.isInstantiable() ? desc.newInstance() : null;
2113 } catch (Exception ex) {
2114 throw new InvalidClassException(desc.forClass().getName(),
2115 "unable to create instance", ex);
2116 }
2117
2118 passHandle = handles.assign(unshared ? unsharedMarker : obj);
2119 ClassNotFoundException resolveEx = desc.getResolveException();
2120 if (resolveEx != null) {
2121 handles.markException(passHandle, resolveEx);
2122 }
2123
2124 final boolean isRecord = desc.isRecord();
2125 if (isRecord) {
2126 assert obj == null;
2127 obj = readRecord(desc);
2128 if (!unshared)
2129 handles.setObject(passHandle, obj);
2130 } else if (desc.isExternalizable()) {
2131 readExternalData((Externalizable) obj, desc);
2132 } else {
2133 readSerialData(obj, desc);
2134 }
2135
2136 handles.finish(passHandle);
2137
2138 if (obj != null &&
2139 handles.lookupException(passHandle) == null &&
2140 desc.hasReadResolveMethod())
2141 {
2142 Object rep = desc.invokeReadResolve(obj);
2143 if (unshared && rep.getClass().isArray()) {
2144 rep = cloneArray(rep);
2145 }
2146 if (rep != obj) {
2147 // Filter the replacement object
2148 if (rep != null) {
2149 if (rep.getClass().isArray()) {
2150 filterCheck(rep.getClass(), Array.getLength(rep));
2151 } else {
2152 filterCheck(rep.getClass(), -1);
2153 }
2154 }
2155 handles.setObject(passHandle, obj = rep);
2156 }
2157 }
2158
2159 return obj;
2160 }
2161
2162 /**
2163 * If obj is non-null, reads externalizable data by invoking readExternal()
2164 * method of obj; otherwise, attempts to skip over externalizable data.
2165 * Expects that passHandle is set to obj's handle before this method is
2166 * called.
2167 */
2168 private void readExternalData(Externalizable obj, ObjectStreamClass desc)
2169 throws IOException
2170 {
2171 SerialCallbackContext oldContext = curContext;
2172 if (oldContext != null)
2173 oldContext.check();
2174 curContext = null;
2175 try {
2176 boolean blocked = desc.hasBlockExternalData();
2177 if (blocked) {
2178 bin.setBlockDataMode(true);
2179 }
2180 if (obj != null) {
2181 try {
2182 obj.readExternal(this);
2183 } catch (ClassNotFoundException ex) {
2184 /*
2185 * In most cases, the handle table has already propagated
2186 * a CNFException to passHandle at this point; this mark
2187 * call is included to address cases where the readExternal
2188 * method has cons'ed and thrown a new CNFException of its
2189 * own.
2190 */
2191 handles.markException(passHandle, ex);
2192 }
2193 }
2194 if (blocked) {
2195 skipCustomData();
2196 }
2197 } finally {
2198 if (oldContext != null)
2199 oldContext.check();
2200 curContext = oldContext;
2201 }
2202 /*
2203 * At this point, if the externalizable data was not written in
2204 * block-data form and either the externalizable class doesn't exist
2205 * locally (i.e., obj == null) or readExternal() just threw a
2206 * CNFException, then the stream is probably in an inconsistent state,
2207 * since some (or all) of the externalizable data may not have been
2208 * consumed. Since there's no "correct" action to take in this case,
2209 * we mimic the behavior of past serialization implementations and
2210 * blindly hope that the stream is in sync; if it isn't and additional
2211 * externalizable data remains in the stream, a subsequent read will
2212 * most likely throw a StreamCorruptedException.
2213 */
2214 }
2215
2216 /**
2217 * Reads and returns a record.
2218 * If an exception is marked for any of the fields, the dependency
2219 * mechanism marks the record as having an exception.
2220 * Null is returned from readRecord and later the exception is thrown at
2221 * the exit of {@link #readObject(Class)}.
2222 **/
2223 private Object readRecord(ObjectStreamClass desc) throws IOException {
2224 ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
2225 if (slots.length != 1) {
2226 // skip any superclass stream field values
2227 for (int i = 0; i < slots.length-1; i++) {
2228 if (slots[i].hasData) {
2229 new FieldValues(slots[i].desc, true);
2230 }
2231 }
2232 }
2233
2234 FieldValues fieldValues = new FieldValues(desc, true);
2235 if (handles.lookupException(passHandle) != null) {
2236 return null; // slot marked with exception, don't create record
2237 }
2238
2239 // get canonical record constructor adapted to take two arguments:
2240 // - byte[] primValues
2241 // - Object[] objValues
2242 // and return Object
2243 MethodHandle ctrMH = RecordSupport.deserializationCtr(desc);
2244
2245 try {
2246 return (Object) ctrMH.invokeExact(fieldValues.primValues, fieldValues.objValues);
2247 } catch (Exception e) {
2248 throw new InvalidObjectException(e.getMessage(), e);
2249 } catch (Error e) {
2250 throw e;
2251 } catch (Throwable t) {
2252 throw new InvalidObjectException("ReflectiveOperationException " +
2253 "during deserialization", t);
2254 }
2255 }
2256
2257 /**
2258 * Reads (or attempts to skip, if obj is null or is tagged with a
2259 * ClassNotFoundException) instance data for each serializable class of
2260 * object in stream, from superclass to subclass. Expects that passHandle
2261 * is set to obj's handle before this method is called.
2262 */
2263 private void readSerialData(Object obj, ObjectStreamClass desc)
2264 throws IOException
2265 {
2266 ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
2267 // Best effort Failure Atomicity; slotValues will be non-null if field
2268 // values can be set after reading all field data in the hierarchy.
2269 // Field values can only be set after reading all data if there are no
2270 // user observable methods in the hierarchy, readObject(NoData). The
2271 // top most Serializable class in the hierarchy can be skipped.
2272 FieldValues[] slotValues = null;
2273
2274 boolean hasSpecialReadMethod = false;
2275 for (int i = 1; i < slots.length; i++) {
2276 ObjectStreamClass slotDesc = slots[i].desc;
2277 if (slotDesc.hasReadObjectMethod()
2278 || slotDesc.hasReadObjectNoDataMethod()) {
2279 hasSpecialReadMethod = true;
2280 break;
2281 }
2282 }
2283 // No special read methods, can store values and defer setting.
2284 if (!hasSpecialReadMethod)
2285 slotValues = new FieldValues[slots.length];
2286
2287 for (int i = 0; i < slots.length; i++) {
2288 ObjectStreamClass slotDesc = slots[i].desc;
2289
2290 if (slots[i].hasData) {
2291 if (obj == null || handles.lookupException(passHandle) != null) {
2292 // Read fields of the current descriptor into a new FieldValues and discard
2293 new FieldValues(slotDesc, true);
2294 } else if (slotDesc.hasReadObjectMethod()) {
2295 SerialCallbackContext oldContext = curContext;
2296 if (oldContext != null)
2297 oldContext.check();
2298 try {
2299 curContext = new SerialCallbackContext(obj, slotDesc);
2300
2301 bin.setBlockDataMode(true);
2302 slotDesc.invokeReadObject(obj, this);
2303 } catch (ClassNotFoundException ex) {
2304 /*
2305 * In most cases, the handle table has already
2306 * propagated a CNFException to passHandle at this
2307 * point; this mark call is included to address cases
2308 * where the custom readObject method has cons'ed and
2309 * thrown a new CNFException of its own.
2310 */
2311 handles.markException(passHandle, ex);
2312 } finally {
2313 curContext.setUsed();
2314 if (oldContext!= null)
2315 oldContext.check();
2316 curContext = oldContext;
2317 }
2318
2319 /*
2320 * defaultDataEnd may have been set indirectly by custom
2321 * readObject() method when calling defaultReadObject() or
2322 * readFields(); clear it to restore normal read behavior.
2323 */
2324 defaultDataEnd = false;
2325 } else {
2326 // Read fields of the current descriptor into a new FieldValues
2327 FieldValues values = new FieldValues(slotDesc, true);
2328 if (slotValues != null) {
2329 slotValues[i] = values;
2330 } else if (obj != null) {
2331 if (handles.lookupException(passHandle) == null) {
2332 // passHandle NOT marked with an exception; set field values
2333 values.defaultCheckFieldValues(obj);
2334 values.defaultSetFieldValues(obj);
2335 }
2336 }
2337 }
2338
2339 if (slotDesc.hasWriteObjectData()) {
2340 skipCustomData();
2341 } else {
2342 bin.setBlockDataMode(false);
2343 }
2344 } else {
2345 if (obj != null &&
2346 slotDesc.hasReadObjectNoDataMethod() &&
2347 handles.lookupException(passHandle) == null)
2348 {
2349 slotDesc.invokeReadObjectNoData(obj);
2350 }
2351 }
2352 }
2353
2354 if (obj != null && slotValues != null && handles.lookupException(passHandle) == null) {
2355 // passHandle NOT marked with an exception
2356 // Check that the non-primitive types are assignable for all slots
2357 // before assigning.
2358 for (int i = 0; i < slots.length; i++) {
2359 if (slotValues[i] != null)
2360 slotValues[i].defaultCheckFieldValues(obj);
2361 }
2362 for (int i = 0; i < slots.length; i++) {
2363 if (slotValues[i] != null)
2364 slotValues[i].defaultSetFieldValues(obj);
2365 }
2366 }
2367 }
2368
2369 /**
2370 * Skips over all block data and objects until TC_ENDBLOCKDATA is
2371 * encountered.
2372 */
2373 private void skipCustomData() throws IOException {
2374 int oldHandle = passHandle;
2375 for (;;) {
2376 if (bin.getBlockDataMode()) {
2377 bin.skipBlockData();
2378 bin.setBlockDataMode(false);
2379 }
2380 switch (bin.peekByte()) {
2381 case TC_BLOCKDATA:
2382 case TC_BLOCKDATALONG:
2383 bin.setBlockDataMode(true);
2384 break;
2385
2386 case TC_ENDBLOCKDATA:
2387 bin.readByte();
2388 passHandle = oldHandle;
2389 return;
2390
2391 default:
2392 readObject0(Object.class, false);
2393 break;
2394 }
2395 }
2396 }
2397
2398 /**
2399 * Reads in and returns IOException that caused serialization to abort.
2400 * All stream state is discarded prior to reading in fatal exception. Sets
2401 * passHandle to fatal exception's handle.
2402 */
2403 private IOException readFatalException() throws IOException {
2404 if (bin.readByte() != TC_EXCEPTION) {
2405 throw new InternalError();
2406 }
2407 clear();
2408 // Check that an object follows the TC_EXCEPTION typecode
2409 byte tc = bin.peekByte();
2410 if (tc != TC_OBJECT &&
2411 tc != TC_REFERENCE) {
2412 throw new StreamCorruptedException(
2413 String.format("invalid type code: %02X", tc));
2414 }
2415 return (IOException) readObject0(Object.class, false);
2416 }
2417
2418 /**
2419 * If recursion depth is 0, clears internal data structures; otherwise,
2420 * throws a StreamCorruptedException. This method is called when a
2421 * TC_RESET typecode is encountered.
2422 */
2423 private void handleReset() throws StreamCorruptedException {
2424 if (depth > 0) {
2425 throw new StreamCorruptedException(
2426 "unexpected reset; recursion depth: " + depth);
2427 }
2428 clear();
2429 }
2430
2431 /**
2432 * Returns the first non-null and non-platform class loader (not counting
2433 * class loaders of generated reflection implementation classes) up the
2434 * execution stack, or the platform class loader if only code from the
2435 * bootstrap and platform class loader is on the stack.
2436 */
2437 private static ClassLoader latestUserDefinedLoader() {
2438 return jdk.internal.misc.VM.latestUserDefinedLoader();
2439 }
2440
2441 /**
2442 * Default GetField implementation.
2443 */
2444 private final class FieldValues extends GetField {
2445
2446 /** class descriptor describing serializable fields */
2447 private final ObjectStreamClass desc;
2448 /** primitive field values */
2449 final byte[] primValues;
2450 /** object field values */
2451 final Object[] objValues;
2452 /** object field value handles */
2453 private final int[] objHandles;
2454
2455 /**
2456 * Creates FieldValues object for reading fields defined in given
2457 * class descriptor.
2458 * @param desc the ObjectStreamClass to read
2459 * @param recordDependencies if true, record the dependencies
2460 * from current PassHandle and the object's read.
2461 */
2462 FieldValues(ObjectStreamClass desc, boolean recordDependencies) throws IOException {
2463 this.desc = desc;
2464
2465 int primDataSize = desc.getPrimDataSize();
2466 primValues = (primDataSize > 0) ? new byte[primDataSize] : null;
2467 if (primDataSize > 0) {
2468 bin.readFully(primValues, 0, primDataSize, false);
2469 }
2470
2471 int numObjFields = desc.getNumObjFields();
2472 objValues = (numObjFields > 0) ? new Object[numObjFields] : null;
2473 objHandles = (numObjFields > 0) ? new int[numObjFields] : null;
2474 if (numObjFields > 0) {
2475 int objHandle = passHandle;
2476 ObjectStreamField[] fields = desc.getFields(false);
2477 int numPrimFields = fields.length - objValues.length;
2478 for (int i = 0; i < objValues.length; i++) {
2479 ObjectStreamField f = fields[numPrimFields + i];
2480 objValues[i] = readObject0(Object.class, f.isUnshared());
2481 objHandles[i] = passHandle;
2482 if (recordDependencies && f.getField() != null) {
2483 handles.markDependency(objHandle, passHandle);
2484 }
2485 }
2486 passHandle = objHandle;
2487 }
2488 }
2489
2490 public ObjectStreamClass getObjectStreamClass() {
2491 return desc;
2492 }
2493
2494 public boolean defaulted(String name) {
2495 return (getFieldOffset(name, null) < 0);
2496 }
2497
2498 public boolean get(String name, boolean val) {
2499 int off = getFieldOffset(name, Boolean.TYPE);
2500 return (off >= 0) ? ByteArray.getBoolean(primValues, off) : val;
2501 }
2502
2503 public byte get(String name, byte val) {
2504 int off = getFieldOffset(name, Byte.TYPE);
2505 return (off >= 0) ? primValues[off] : val;
2506 }
2507
2508 public char get(String name, char val) {
2509 int off = getFieldOffset(name, Character.TYPE);
2510 return (off >= 0) ? ByteArray.getChar(primValues, off) : val;
2511 }
2512
2513 public short get(String name, short val) {
2514 int off = getFieldOffset(name, Short.TYPE);
2515 return (off >= 0) ? ByteArray.getShort(primValues, off) : val;
2516 }
2517
2518 public int get(String name, int val) {
2519 int off = getFieldOffset(name, Integer.TYPE);
2520 return (off >= 0) ? ByteArray.getInt(primValues, off) : val;
2521 }
2522
2523 public float get(String name, float val) {
2524 int off = getFieldOffset(name, Float.TYPE);
2525 return (off >= 0) ? ByteArray.getFloat(primValues, off) : val;
2526 }
2527
2528 public long get(String name, long val) {
2529 int off = getFieldOffset(name, Long.TYPE);
2530 return (off >= 0) ? ByteArray.getLong(primValues, off) : val;
2531 }
2532
2533 public double get(String name, double val) {
2534 int off = getFieldOffset(name, Double.TYPE);
2535 return (off >= 0) ? ByteArray.getDouble(primValues, off) : val;
2536 }
2537
2538 public Object get(String name, Object val) throws ClassNotFoundException {
2539 int off = getFieldOffset(name, Object.class);
2540 if (off >= 0) {
2541 int objHandle = objHandles[off];
2542 handles.markDependency(passHandle, objHandle);
2543 ClassNotFoundException ex = handles.lookupException(objHandle);
2544 if (ex == null)
2545 return objValues[off];
2546 if (Caches.GETFIELD_CNFE_RETURNS_NULL) {
2547 // Revert to the prior behavior; return null instead of CNFE
2548 return null;
2549 }
2550 throw ex;
2551 } else {
2552 return val;
2553 }
2554 }
2555
2556 /** Throws ClassCastException if any value is not assignable. */
2557 void defaultCheckFieldValues(Object obj) {
2558 if (objValues != null)
2559 desc.checkObjFieldValueTypes(obj, objValues);
2560 }
2561
2562 private void defaultSetFieldValues(Object obj) {
2563 if (primValues != null)
2564 desc.setPrimFieldValues(obj, primValues);
2565 if (objValues != null)
2566 desc.setObjFieldValues(obj, objValues);
2567 }
2568
2569 /**
2570 * Returns offset of field with given name and type. A specified type
2571 * of null matches all types, Object.class matches all non-primitive
2572 * types, and any other non-null type matches assignable types only.
2573 * If no matching field is found in the (incoming) class
2574 * descriptor but a matching field is present in the associated local
2575 * class descriptor, returns -1. Throws IllegalArgumentException if
2576 * neither incoming nor local class descriptor contains a match.
2577 */
2578 private int getFieldOffset(String name, Class<?> type) {
2579 ObjectStreamField field = desc.getField(name, type);
2580 if (field != null) {
2581 return field.getOffset();
2582 } else if (desc.getLocalDesc().getField(name, type) != null) {
2583 return -1;
2584 } else {
2585 throw new IllegalArgumentException("no such field " + name +
2586 " with type " + type);
2587 }
2588 }
2589 }
2590
2591 /**
2592 * Prioritized list of callbacks to be performed once object graph has been
2593 * completely deserialized.
2594 */
2595 private static class ValidationList {
2596
2597 private static class Callback {
2598 final ObjectInputValidation obj;
2599 final int priority;
2600 Callback next;
2601
2602 Callback(ObjectInputValidation obj, int priority, Callback next) {
2603 this.obj = obj;
2604 this.priority = priority;
2605 this.next = next;
2606 }
2607 }
2608
2609 /** linked list of callbacks */
2610 private Callback list;
2611
2612 /**
2613 * Creates new (empty) ValidationList.
2614 */
2615 ValidationList() {
2616 }
2617
2618 /**
2619 * Registers callback. Throws InvalidObjectException if callback
2620 * object is null.
2621 */
2622 void register(ObjectInputValidation obj, int priority)
2623 throws InvalidObjectException
2624 {
2625 if (obj == null) {
2626 throw new InvalidObjectException("null callback");
2627 }
2628
2629 Callback prev = null, cur = list;
2630 while (cur != null && priority < cur.priority) {
2631 prev = cur;
2632 cur = cur.next;
2633 }
2634 if (prev != null) {
2635 prev.next = new Callback(obj, priority, cur);
2636 } else {
2637 list = new Callback(obj, priority, list);
2638 }
2639 }
2640
2641 /**
2642 * Invokes all registered callbacks and clears the callback list.
2643 * Callbacks with higher priorities are called first; those with equal
2644 * priorities may be called in any order. If any of the callbacks
2645 * throws an InvalidObjectException, the callback process is terminated
2646 * and the exception propagated upwards.
2647 */
2648 void doCallbacks() throws InvalidObjectException {
2649 try {
2650 while (list != null) {
2651 list.obj.validateObject();
2652 list = list.next;
2653 }
2654 } catch (InvalidObjectException ex) {
2655 list = null;
2656 throw ex;
2657 }
2658 }
2659
2660 /**
2661 * Resets the callback list to its initial (empty) state.
2662 */
2663 public void clear() {
2664 list = null;
2665 }
2666 }
2667
2668 /**
2669 * Hold a snapshot of values to be passed to an ObjectInputFilter.
2670 */
2671 static class FilterValues implements ObjectInputFilter.FilterInfo {
2672 final Class<?> clazz;
2673 final long arrayLength;
2674 final long totalObjectRefs;
2675 final long depth;
2676 final long streamBytes;
2677
2678 public FilterValues(Class<?> clazz, long arrayLength, long totalObjectRefs,
2679 long depth, long streamBytes) {
2680 this.clazz = clazz;
2681 this.arrayLength = arrayLength;
2682 this.totalObjectRefs = totalObjectRefs;
2683 this.depth = depth;
2684 this.streamBytes = streamBytes;
2685 }
2686
2687 @Override
2688 public Class<?> serialClass() {
2689 return clazz;
2690 }
2691
2692 @Override
2693 public long arrayLength() {
2694 return arrayLength;
2695 }
2696
2697 @Override
2698 public long references() {
2699 return totalObjectRefs;
2700 }
2701
2702 @Override
2703 public long depth() {
2704 return depth;
2705 }
2706
2707 @Override
2708 public long streamBytes() {
2709 return streamBytes;
2710 }
2711 }
2712
2713 /**
2714 * Input stream supporting single-byte peek operations.
2715 */
2716 private static class PeekInputStream extends InputStream {
2717
2718 /** underlying stream */
2719 private final InputStream in;
2720 /** peeked byte */
2721 private int peekb = -1;
2722 /** total bytes read from the stream */
2723 private long totalBytesRead = 0;
2724
2725 /**
2726 * Creates new PeekInputStream on top of given underlying stream.
2727 */
2728 PeekInputStream(InputStream in) {
2729 this.in = in;
2730 }
2731
2732 /**
2733 * Peeks at next byte value in stream. Similar to read(), except
2734 * that it does not consume the read value.
2735 */
2736 int peek() throws IOException {
2737 if (peekb >= 0) {
2738 return peekb;
2739 }
2740 peekb = in.read();
2741 totalBytesRead += peekb >= 0 ? 1 : 0;
2742 return peekb;
2743 }
2744
2745 public int read() throws IOException {
2746 if (peekb >= 0) {
2747 int v = peekb;
2748 peekb = -1;
2749 return v;
2750 } else {
2751 int nbytes = in.read();
2752 totalBytesRead += nbytes >= 0 ? 1 : 0;
2753 return nbytes;
2754 }
2755 }
2756
2757 public int read(byte[] b, int off, int len) throws IOException {
2758 int nbytes;
2759 if (len == 0) {
2760 return 0;
2761 } else if (peekb < 0) {
2762 nbytes = in.read(b, off, len);
2763 totalBytesRead += nbytes >= 0 ? nbytes : 0;
2764 return nbytes;
2765 } else {
2766 b[off++] = (byte) peekb;
2767 len--;
2768 peekb = -1;
2769 nbytes = in.read(b, off, len);
2770 totalBytesRead += nbytes >= 0 ? nbytes : 0;
2771 return (nbytes >= 0) ? (nbytes + 1) : 1;
2772 }
2773 }
2774
2775 void readFully(byte[] b, int off, int len) throws IOException {
2776 int n = 0;
2777 while (n < len) {
2778 int count = read(b, off + n, len - n);
2779 if (count < 0) {
2780 throw new EOFException();
2781 }
2782 n += count;
2783 }
2784 }
2785
2786 public long skip(long n) throws IOException {
2787 if (n <= 0) {
2788 return 0;
2789 }
2790 int skipped = 0;
2791 if (peekb >= 0) {
2792 peekb = -1;
2793 skipped++;
2794 n--;
2795 }
2796 n = skipped + in.skip(n);
2797 totalBytesRead += n;
2798 return n;
2799 }
2800
2801 public int available() throws IOException {
2802 return in.available() + ((peekb >= 0) ? 1 : 0);
2803 }
2804
2805 public void close() throws IOException {
2806 in.close();
2807 }
2808
2809 public long getBytesRead() {
2810 return totalBytesRead;
2811 }
2812 }
2813
2814 private static final Unsafe UNSAFE = Unsafe.getUnsafe();
2815
2816 /**
2817 * Performs a "freeze" action, required to adhere to final field semantics.
2818 *
2819 * <p> This method can be called unconditionally before returning the graph,
2820 * from the topmost readObject call, since it is expected that the
2821 * additional cost of the freeze action is negligible compared to
2822 * reconstituting even the most simple graph.
2823 *
2824 * <p> Nested calls to readObject do not issue freeze actions because the
2825 * sub-graph returned from a nested call is not guaranteed to be fully
2826 * initialized yet (possible cycles).
2827 */
2828 private void freeze() {
2829 // Issue a StoreStore|StoreLoad fence, which is at least sufficient
2830 // to provide final-freeze semantics.
2831 UNSAFE.storeFence();
2832 }
2833
2834 /**
2835 * Input stream with two modes: in default mode, inputs data written in the
2836 * same format as DataOutputStream; in "block data" mode, inputs data
2837 * bracketed by block data markers (see object serialization specification
2838 * for details). Buffering depends on block data mode: when in default
2839 * mode, no data is buffered in advance; when in block data mode, all data
2840 * for the current data block is read in at once (and buffered).
2841 */
2842 private class BlockDataInputStream
2843 extends InputStream implements DataInput
2844 {
2845 /** maximum data block length */
2846 private static final int MAX_BLOCK_SIZE = 1024;
2847 /** maximum data block header length */
2848 private static final int MAX_HEADER_SIZE = 5;
2849 /** (tunable) length of char buffer (for reading strings) */
2850 private static final int CHAR_BUF_SIZE = 256;
2851 /** readBlockHeader() return value indicating header read may block */
2852 private static final int HEADER_BLOCKED = -2;
2853 /** access to internal methods to count ASCII and inflate latin1/ASCII bytes to char */
2854 private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
2855
2856 /** buffer for reading general/block data */
2857 private final byte[] buf = new byte[MAX_BLOCK_SIZE];
2858 /** buffer for reading block data headers */
2859 private final byte[] hbuf = new byte[MAX_HEADER_SIZE];
2860 /** char buffer for fast string reads */
2861 private final char[] cbuf = new char[CHAR_BUF_SIZE];
2862
2863 /** block data mode */
2864 private boolean blkmode = false;
2865
2866 // block data state fields; values meaningful only when blkmode true
2867 /** current offset into buf */
2868 private int pos = 0;
2869 /** end offset of valid data in buf, or -1 if no more block data */
2870 private int end = -1;
2871 /** number of bytes in current block yet to be read from stream */
2872 private int unread = 0;
2873
2874 /** underlying stream (wrapped in peekable filter stream) */
2875 private final PeekInputStream in;
2876 /** loopback stream (for data reads that span data blocks) */
2877 private final DataInputStream din;
2878
2879 /**
2880 * Creates new BlockDataInputStream on top of given underlying stream.
2881 * Block data mode is turned off by default.
2882 */
2883 BlockDataInputStream(InputStream in) {
2884 this.in = new PeekInputStream(in);
2885 din = new DataInputStream(this);
2886 }
2887
2888 /**
2889 * Sets block data mode to the given mode (true == on, false == off)
2890 * and returns the previous mode value. If the new mode is the same as
2891 * the old mode, no action is taken. Throws IllegalStateException if
2892 * block data mode is being switched from on to off while unconsumed
2893 * block data is still present in the stream.
2894 */
2895 boolean setBlockDataMode(boolean newmode) throws IOException {
2896 if (blkmode == newmode) {
2897 return blkmode;
2898 }
2899 if (newmode) {
2900 pos = 0;
2901 end = 0;
2902 unread = 0;
2903 } else if (pos < end) {
2904 throw new IllegalStateException("unread block data");
2905 }
2906 blkmode = newmode;
2907 return !blkmode;
2908 }
2909
2910 /**
2911 * Returns true if the stream is currently in block data mode, false
2912 * otherwise.
2913 */
2914 boolean getBlockDataMode() {
2915 return blkmode;
2916 }
2917
2918 /**
2919 * If in block data mode, skips to the end of the current group of data
2920 * blocks (but does not unset block data mode). If not in block data
2921 * mode, throws an IllegalStateException.
2922 */
2923 void skipBlockData() throws IOException {
2924 if (!blkmode) {
2925 throw new IllegalStateException("not in block data mode");
2926 }
2927 while (end >= 0) {
2928 refill();
2929 }
2930 }
2931
2932 /**
2933 * Attempts to read in the next block data header (if any). If
2934 * canBlock is false and a full header cannot be read without possibly
2935 * blocking, returns HEADER_BLOCKED, else if the next element in the
2936 * stream is a block data header, returns the block data length
2937 * specified by the header, else returns -1.
2938 */
2939 private int readBlockHeader(boolean canBlock) throws IOException {
2940 if (defaultDataEnd) {
2941 /*
2942 * Fix for 4360508: stream is currently at the end of a field
2943 * value block written via default serialization; since there
2944 * is no terminating TC_ENDBLOCKDATA tag, simulate
2945 * end-of-custom-data behavior explicitly.
2946 */
2947 return -1;
2948 }
2949 try {
2950 for (;;) {
2951 int avail = canBlock ? Integer.MAX_VALUE : in.available();
2952 if (avail == 0) {
2953 return HEADER_BLOCKED;
2954 }
2955
2956 int tc = in.peek();
2957 switch (tc) {
2958 case TC_BLOCKDATA:
2959 if (avail < 2) {
2960 return HEADER_BLOCKED;
2961 }
2962 in.readFully(hbuf, 0, 2);
2963 return hbuf[1] & 0xFF;
2964
2965 case TC_BLOCKDATALONG:
2966 if (avail < 5) {
2967 return HEADER_BLOCKED;
2968 }
2969 in.readFully(hbuf, 0, 5);
2970 int len = ByteArray.getInt(hbuf, 1);
2971 if (len < 0) {
2972 throw new StreamCorruptedException(
2973 "illegal block data header length: " +
2974 len);
2975 }
2976 return len;
2977
2978 /*
2979 * TC_RESETs may occur in between data blocks.
2980 * Unfortunately, this case must be parsed at a lower
2981 * level than other typecodes, since primitive data
2982 * reads may span data blocks separated by a TC_RESET.
2983 */
2984 case TC_RESET:
2985 in.read();
2986 handleReset();
2987 break;
2988
2989 default:
2990 if (tc >= 0 && (tc < TC_BASE || tc > TC_MAX)) {
2991 throw new StreamCorruptedException(
2992 String.format("invalid type code: %02X",
2993 tc));
2994 }
2995 return -1;
2996 }
2997 }
2998 } catch (EOFException ex) {
2999 throw new StreamCorruptedException(
3000 "unexpected EOF while reading block data header");
3001 }
3002 }
3003
3004 /**
3005 * Refills internal buffer buf with block data. Any data in buf at the
3006 * time of the call is considered consumed. Sets the pos, end, and
3007 * unread fields to reflect the new amount of available block data; if
3008 * the next element in the stream is not a data block, sets pos and
3009 * unread to 0 and end to -1.
3010 */
3011 private void refill() throws IOException {
3012 try {
3013 do {
3014 pos = 0;
3015 if (unread > 0) {
3016 int n =
3017 in.read(buf, 0, Math.min(unread, MAX_BLOCK_SIZE));
3018 if (n >= 0) {
3019 end = n;
3020 unread -= n;
3021 } else {
3022 throw new StreamCorruptedException(
3023 "unexpected EOF in middle of data block");
3024 }
3025 } else {
3026 int n = readBlockHeader(true);
3027 if (n >= 0) {
3028 end = 0;
3029 unread = n;
3030 } else {
3031 end = -1;
3032 unread = 0;
3033 }
3034 }
3035 } while (pos == end);
3036 } catch (IOException ex) {
3037 pos = 0;
3038 end = -1;
3039 unread = 0;
3040 throw ex;
3041 }
3042 }
3043
3044 /**
3045 * If in block data mode, returns the number of unconsumed bytes
3046 * remaining in the current data block. If not in block data mode,
3047 * throws an IllegalStateException.
3048 */
3049 int currentBlockRemaining() {
3050 if (blkmode) {
3051 return (end >= 0) ? (end - pos) + unread : 0;
3052 } else {
3053 throw new IllegalStateException();
3054 }
3055 }
3056
3057 /**
3058 * Peeks at (but does not consume) and returns the next byte value in
3059 * the stream, or -1 if the end of the stream/block data (if in block
3060 * data mode) has been reached.
3061 */
3062 int peek() throws IOException {
3063 if (blkmode) {
3064 if (pos == end) {
3065 refill();
3066 }
3067 return (end >= 0) ? (buf[pos] & 0xFF) : -1;
3068 } else {
3069 return in.peek();
3070 }
3071 }
3072
3073 /**
3074 * Peeks at (but does not consume) and returns the next byte value in
3075 * the stream, or throws EOFException if end of stream/block data has
3076 * been reached.
3077 */
3078 byte peekByte() throws IOException {
3079 int val = peek();
3080 if (val < 0) {
3081 throw new EOFException();
3082 }
3083 return (byte) val;
3084 }
3085
3086
3087 /* ----------------- generic input stream methods ------------------ */
3088 /*
3089 * The following methods are equivalent to their counterparts in
3090 * InputStream, except that they interpret data block boundaries and
3091 * read the requested data from within data blocks when in block data
3092 * mode.
3093 */
3094
3095 public int read() throws IOException {
3096 if (blkmode) {
3097 if (pos == end) {
3098 refill();
3099 }
3100 return (end >= 0) ? (buf[pos++] & 0xFF) : -1;
3101 } else {
3102 return in.read();
3103 }
3104 }
3105
3106 public int read(byte[] b, int off, int len) throws IOException {
3107 return read(b, off, len, false);
3108 }
3109
3110 public long skip(long len) throws IOException {
3111 long remain = len;
3112 while (remain > 0) {
3113 if (blkmode) {
3114 if (pos == end) {
3115 refill();
3116 }
3117 if (end < 0) {
3118 break;
3119 }
3120 int nread = (int) Math.min(remain, end - pos);
3121 remain -= nread;
3122 pos += nread;
3123 } else {
3124 int nread = (int) Math.min(remain, MAX_BLOCK_SIZE);
3125 if ((nread = in.read(buf, 0, nread)) < 0) {
3126 break;
3127 }
3128 remain -= nread;
3129 }
3130 }
3131 return len - remain;
3132 }
3133
3134 public int available() throws IOException {
3135 if (blkmode) {
3136 if ((pos == end) && (unread == 0)) {
3137 int n;
3138 while ((n = readBlockHeader(false)) == 0) ;
3139 switch (n) {
3140 case HEADER_BLOCKED:
3141 break;
3142
3143 case -1:
3144 pos = 0;
3145 end = -1;
3146 break;
3147
3148 default:
3149 pos = 0;
3150 end = 0;
3151 unread = n;
3152 break;
3153 }
3154 }
3155 // avoid unnecessary call to in.available() if possible
3156 int unreadAvail = (unread > 0) ?
3157 Math.min(in.available(), unread) : 0;
3158 return (end >= 0) ? (end - pos) + unreadAvail : 0;
3159 } else {
3160 return in.available();
3161 }
3162 }
3163
3164 public void close() throws IOException {
3165 if (blkmode) {
3166 pos = 0;
3167 end = -1;
3168 unread = 0;
3169 }
3170 in.close();
3171 }
3172
3173 /**
3174 * Attempts to read len bytes into byte array b at offset off. Returns
3175 * the number of bytes read, or -1 if the end of stream/block data has
3176 * been reached. If copy is true, reads values into an intermediate
3177 * buffer before copying them to b (to avoid exposing a reference to
3178 * b).
3179 */
3180 int read(byte[] b, int off, int len, boolean copy) throws IOException {
3181 if (len == 0) {
3182 return 0;
3183 } else if (blkmode) {
3184 if (pos == end) {
3185 refill();
3186 }
3187 if (end < 0) {
3188 return -1;
3189 }
3190 int nread = Math.min(len, end - pos);
3191 System.arraycopy(buf, pos, b, off, nread);
3192 pos += nread;
3193 return nread;
3194 } else if (copy) {
3195 int nread = in.read(buf, 0, Math.min(len, MAX_BLOCK_SIZE));
3196 if (nread > 0) {
3197 System.arraycopy(buf, 0, b, off, nread);
3198 }
3199 return nread;
3200 } else {
3201 return in.read(b, off, len);
3202 }
3203 }
3204
3205 /* ----------------- primitive data input methods ------------------ */
3206 /*
3207 * The following methods are equivalent to their counterparts in
3208 * DataInputStream, except that they interpret data block boundaries
3209 * and read the requested data from within data blocks when in block
3210 * data mode.
3211 */
3212
3213 public void readFully(byte[] b) throws IOException {
3214 readFully(b, 0, b.length, false);
3215 }
3216
3217 public void readFully(byte[] b, int off, int len) throws IOException {
3218 readFully(b, off, len, false);
3219 }
3220
3221 public void readFully(byte[] b, int off, int len, boolean copy)
3222 throws IOException
3223 {
3224 while (len > 0) {
3225 int n = read(b, off, len, copy);
3226 if (n < 0) {
3227 throw new EOFException();
3228 }
3229 off += n;
3230 len -= n;
3231 }
3232 }
3233
3234 public int skipBytes(int n) throws IOException {
3235 return din.skipBytes(n);
3236 }
3237
3238 public boolean readBoolean() throws IOException {
3239 int v = read();
3240 if (v < 0) {
3241 throw new EOFException();
3242 }
3243 return (v != 0);
3244 }
3245
3246 public byte readByte() throws IOException {
3247 int v = read();
3248 if (v < 0) {
3249 throw new EOFException();
3250 }
3251 return (byte) v;
3252 }
3253
3254 public int readUnsignedByte() throws IOException {
3255 int v = read();
3256 if (v < 0) {
3257 throw new EOFException();
3258 }
3259 return v;
3260 }
3261
3262 public char readChar() throws IOException {
3263 if (!blkmode) {
3264 pos = 0;
3265 in.readFully(buf, 0, 2);
3266 } else if (end - pos < 2) {
3267 return din.readChar();
3268 }
3269 char v = ByteArray.getChar(buf, pos);
3270 pos += 2;
3271 return v;
3272 }
3273
3274 public short readShort() throws IOException {
3275 if (!blkmode) {
3276 pos = 0;
3277 in.readFully(buf, 0, 2);
3278 } else if (end - pos < 2) {
3279 return din.readShort();
3280 }
3281 short v = ByteArray.getShort(buf, pos);
3282 pos += 2;
3283 return v;
3284 }
3285
3286 public int readUnsignedShort() throws IOException {
3287 if (!blkmode) {
3288 pos = 0;
3289 in.readFully(buf, 0, 2);
3290 } else if (end - pos < 2) {
3291 return din.readUnsignedShort();
3292 }
3293 int v = ByteArray.getShort(buf, pos) & 0xFFFF;
3294 pos += 2;
3295 return v;
3296 }
3297
3298 public int readInt() throws IOException {
3299 if (!blkmode) {
3300 pos = 0;
3301 in.readFully(buf, 0, 4);
3302 } else if (end - pos < 4) {
3303 return din.readInt();
3304 }
3305 int v = ByteArray.getInt(buf, pos);
3306 pos += 4;
3307 return v;
3308 }
3309
3310 public float readFloat() throws IOException {
3311 if (!blkmode) {
3312 pos = 0;
3313 in.readFully(buf, 0, 4);
3314 } else if (end - pos < 4) {
3315 return din.readFloat();
3316 }
3317 float v = ByteArray.getFloat(buf, pos);
3318 pos += 4;
3319 return v;
3320 }
3321
3322 public long readLong() throws IOException {
3323 if (!blkmode) {
3324 pos = 0;
3325 in.readFully(buf, 0, 8);
3326 } else if (end - pos < 8) {
3327 return din.readLong();
3328 }
3329 long v = ByteArray.getLong(buf, pos);
3330 pos += 8;
3331 return v;
3332 }
3333
3334 public double readDouble() throws IOException {
3335 if (!blkmode) {
3336 pos = 0;
3337 in.readFully(buf, 0, 8);
3338 } else if (end - pos < 8) {
3339 return din.readDouble();
3340 }
3341 double v = ByteArray.getDouble(buf, pos);
3342 pos += 8;
3343 return v;
3344 }
3345
3346 public String readUTF() throws IOException {
3347 return readUTFBody(readUnsignedShort());
3348 }
3349
3350 @SuppressWarnings("deprecation")
3351 public String readLine() throws IOException {
3352 return din.readLine(); // deprecated, not worth optimizing
3353 }
3354
3355 /* -------------- primitive data array input methods --------------- */
3356 /*
3357 * The following methods read in spans of primitive data values.
3358 * Though equivalent to calling the corresponding primitive read
3359 * methods repeatedly, these methods are optimized for reading groups
3360 * of primitive data values more efficiently.
3361 */
3362
3363 void readBooleans(boolean[] v, int off, int len) throws IOException {
3364 int stop, endoff = off + len;
3365 while (off < endoff) {
3366 if (!blkmode) {
3367 int span = Math.min(endoff - off, MAX_BLOCK_SIZE);
3368 in.readFully(buf, 0, span);
3369 stop = off + span;
3370 pos = 0;
3371 } else if (end - pos < 1) {
3372 v[off++] = din.readBoolean();
3373 continue;
3374 } else {
3375 stop = Math.min(endoff, off + end - pos);
3376 }
3377
3378 while (off < stop) {
3379 v[off++] = ByteArray.getBoolean(buf, pos++);
3380 }
3381 }
3382 }
3383
3384 void readChars(char[] v, int off, int len) throws IOException {
3385 int stop, endoff = off + len;
3386 while (off < endoff) {
3387 if (!blkmode) {
3388 int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);
3389 in.readFully(buf, 0, span << 1);
3390 stop = off + span;
3391 pos = 0;
3392 } else if (end - pos < 2) {
3393 v[off++] = din.readChar();
3394 continue;
3395 } else {
3396 stop = Math.min(endoff, off + ((end - pos) >> 1));
3397 }
3398
3399 while (off < stop) {
3400 v[off++] = ByteArray.getChar(buf, pos);
3401 pos += 2;
3402 }
3403 }
3404 }
3405
3406 void readShorts(short[] v, int off, int len) throws IOException {
3407 int stop, endoff = off + len;
3408 while (off < endoff) {
3409 if (!blkmode) {
3410 int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);
3411 in.readFully(buf, 0, span << 1);
3412 stop = off + span;
3413 pos = 0;
3414 } else if (end - pos < 2) {
3415 v[off++] = din.readShort();
3416 continue;
3417 } else {
3418 stop = Math.min(endoff, off + ((end - pos) >> 1));
3419 }
3420
3421 while (off < stop) {
3422 v[off++] = ByteArray.getShort(buf, pos);
3423 pos += 2;
3424 }
3425 }
3426 }
3427
3428 void readInts(int[] v, int off, int len) throws IOException {
3429 int stop, endoff = off + len;
3430 while (off < endoff) {
3431 if (!blkmode) {
3432 int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);
3433 in.readFully(buf, 0, span << 2);
3434 stop = off + span;
3435 pos = 0;
3436 } else if (end - pos < 4) {
3437 v[off++] = din.readInt();
3438 continue;
3439 } else {
3440 stop = Math.min(endoff, off + ((end - pos) >> 2));
3441 }
3442
3443 while (off < stop) {
3444 v[off++] = ByteArray.getInt(buf, pos);
3445 pos += 4;
3446 }
3447 }
3448 }
3449
3450 void readFloats(float[] v, int off, int len) throws IOException {
3451 int stop, endoff = off + len;
3452 while (off < endoff) {
3453 if (!blkmode) {
3454 int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);
3455 in.readFully(buf, 0, span << 2);
3456 stop = off + span;
3457 pos = 0;
3458 } else if (end - pos < 4) {
3459 v[off++] = din.readFloat();
3460 continue;
3461 } else {
3462 stop = Math.min(endoff, ((end - pos) >> 2));
3463 }
3464
3465 while (off < stop) {
3466 v[off++] = ByteArray.getFloat(buf, pos);
3467 pos += 4;
3468 }
3469 }
3470 }
3471
3472 void readLongs(long[] v, int off, int len) throws IOException {
3473 int stop, endoff = off + len;
3474 while (off < endoff) {
3475 if (!blkmode) {
3476 int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);
3477 in.readFully(buf, 0, span << 3);
3478 stop = off + span;
3479 pos = 0;
3480 } else if (end - pos < 8) {
3481 v[off++] = din.readLong();
3482 continue;
3483 } else {
3484 stop = Math.min(endoff, off + ((end - pos) >> 3));
3485 }
3486
3487 while (off < stop) {
3488 v[off++] = ByteArray.getLong(buf, pos);
3489 pos += 8;
3490 }
3491 }
3492 }
3493
3494 void readDoubles(double[] v, int off, int len) throws IOException {
3495 int stop, endoff = off + len;
3496 while (off < endoff) {
3497 if (!blkmode) {
3498 int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);
3499 in.readFully(buf, 0, span << 3);
3500 stop = off + span;
3501 pos = 0;
3502 } else if (end - pos < 8) {
3503 v[off++] = din.readDouble();
3504 continue;
3505 } else {
3506 stop = Math.min(endoff - off, ((end - pos) >> 3));
3507 }
3508
3509 while (off < stop) {
3510 v[off++] = ByteArray.getDouble(buf, pos);
3511 pos += 8;
3512 }
3513 }
3514 }
3515
3516 /**
3517 * Reads in string written in "long" UTF format. "Long" UTF format is
3518 * identical to standard UTF, except that it uses an 8 byte header
3519 * (instead of the standard 2 bytes) to convey the UTF encoding length.
3520 */
3521 String readLongUTF() throws IOException {
3522 return readUTFBody(readLong());
3523 }
3524
3525 /**
3526 * Reads in the "body" (i.e., the UTF representation minus the 2-byte
3527 * or 8-byte length header) of a UTF encoding, which occupies the next
3528 * utflen bytes.
3529 */
3530 private String readUTFBody(long utflen) throws IOException {
3531 if (!blkmode) {
3532 end = pos = 0;
3533 }
3534
3535 StringBuilder sbuf;
3536 if (utflen > 0 && utflen < Integer.MAX_VALUE) {
3537 // Scan for leading ASCII chars
3538 int avail = end - pos;
3539 int ascii = JLA.countPositives(buf, pos, Math.min(avail, (int)utflen));
3540 if (ascii == utflen) {
3541 // Complete match, consume the buf[pos ... pos + ascii] range and return.
3542 // Modified UTF-8 and ISO-8859-1 are both ASCII-compatible encodings bytes
3543 // thus we can treat the range as ISO-8859-1 and avoid a redundant scan
3544 // in the String constructor
3545 String utf = new String(buf, pos, ascii, StandardCharsets.ISO_8859_1);
3546 pos += ascii;
3547 return utf;
3548 }
3549 // Avoid allocating a StringBuilder if there's enough data in buf and
3550 // cbuf is large enough
3551 if (avail >= utflen && utflen <= CHAR_BUF_SIZE) {
3552 JLA.inflateBytesToChars(buf, pos, cbuf, 0, ascii);
3553 pos += ascii;
3554 int cbufPos = readUTFSpan(ascii, utflen - ascii);
3555 return new String(cbuf, 0, cbufPos);
3556 }
3557 // a reasonable initial capacity based on the UTF length
3558 int initialCapacity = Math.min((int)utflen, 0xFFFF);
3559 sbuf = new StringBuilder(initialCapacity);
3560 } else {
3561 sbuf = new StringBuilder();
3562 }
3563
3564 while (utflen > 0) {
3565 int avail = end - pos;
3566 if (avail >= 3 || (long) avail == utflen) {
3567 int cbufPos = readUTFSpan(0, utflen);
3568 // pos has advanced: adjust utflen by the difference in
3569 // available bytes
3570 utflen -= avail - (end - pos);
3571 sbuf.append(cbuf, 0, cbufPos);
3572 } else {
3573 if (blkmode) {
3574 // near block boundary, read one byte at a time
3575 utflen -= readUTFChar(sbuf, utflen);
3576 } else {
3577 // shift and refill buffer manually
3578 if (avail > 0) {
3579 System.arraycopy(buf, pos, buf, 0, avail);
3580 }
3581 pos = 0;
3582 end = (int) Math.min(MAX_BLOCK_SIZE, utflen);
3583 in.readFully(buf, avail, end - avail);
3584 }
3585 }
3586 }
3587
3588 return sbuf.toString();
3589 }
3590
3591 /**
3592 * Reads span of UTF-encoded characters out of internal buffer
3593 * (starting at offset pos), consuming no more than utflen bytes.
3594 * Appends read characters to cbuf. Returns the current position
3595 * in cbuf.
3596 */
3597 private int readUTFSpan(int cpos, long utflen)
3598 throws IOException
3599 {
3600 int start = pos;
3601 int avail = Math.min(end - pos, CHAR_BUF_SIZE);
3602 // stop short of last char unless all of utf bytes in buffer
3603 int stop = start + ((utflen > avail) ? avail - 2 : (int) utflen);
3604 boolean outOfBounds = false;
3605
3606 try {
3607 while (pos < stop) {
3608 int b1, b2, b3;
3609 b1 = buf[pos++] & 0xFF;
3610 switch (b1 >> 4) {
3611 case 0, 1, 2, 3, 4, 5, 6, 7 -> // 1 byte format: 0xxxxxxx
3612 cbuf[cpos++] = (char) b1;
3613 case 12, 13 -> { // 2 byte format: 110xxxxx 10xxxxxx
3614 b2 = buf[pos++];
3615 if ((b2 & 0xC0) != 0x80) {
3616 throw new UTFDataFormatException();
3617 }
3618 cbuf[cpos++] = (char) (((b1 & 0x1F) << 6) |
3619 ((b2 & 0x3F) << 0));
3620 }
3621 case 14 -> { // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
3622 b3 = buf[pos + 1];
3623 b2 = buf[pos + 0];
3624 pos += 2;
3625 if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
3626 throw new UTFDataFormatException();
3627 }
3628 cbuf[cpos++] = (char) (((b1 & 0x0F) << 12) |
3629 ((b2 & 0x3F) << 6) |
3630 ((b3 & 0x3F) << 0));
3631 }
3632 default -> throw new UTFDataFormatException(); // 10xx xxxx, 1111 xxxx
3633 }
3634 }
3635 } catch (ArrayIndexOutOfBoundsException ex) {
3636 outOfBounds = true;
3637 } finally {
3638 if (outOfBounds || (pos - start) > utflen) {
3639 /*
3640 * Fix for 4450867: if a malformed utf char causes the
3641 * conversion loop to scan past the expected end of the utf
3642 * string, only consume the expected number of utf bytes.
3643 */
3644 pos = start + (int) utflen;
3645 throw new UTFDataFormatException();
3646 }
3647 }
3648 return cpos;
3649 }
3650
3651 /**
3652 * Reads in single UTF-encoded character one byte at a time, appends
3653 * the character to sbuf, and returns the number of bytes consumed.
3654 * This method is used when reading in UTF strings written in block
3655 * data mode to handle UTF-encoded characters which (potentially)
3656 * straddle block-data boundaries.
3657 */
3658 private int readUTFChar(StringBuilder sbuf, long utflen)
3659 throws IOException
3660 {
3661 int b1, b2, b3;
3662 b1 = readByte() & 0xFF;
3663 switch (b1 >> 4) {
3664 case 0, 1, 2, 3, 4, 5, 6, 7 -> { // 1 byte format: 0xxxxxxx
3665 sbuf.append((char) b1);
3666 return 1;
3667 }
3668 case 12, 13 -> { // 2 byte format: 110xxxxx 10xxxxxx
3669 if (utflen < 2) {
3670 throw new UTFDataFormatException();
3671 }
3672 b2 = readByte();
3673 if ((b2 & 0xC0) != 0x80) {
3674 throw new UTFDataFormatException();
3675 }
3676 sbuf.append((char) (((b1 & 0x1F) << 6) |
3677 ((b2 & 0x3F) << 0)));
3678 return 2;
3679 }
3680 case 14 -> { // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
3681 if (utflen < 3) {
3682 if (utflen == 2) {
3683 readByte(); // consume remaining byte
3684 }
3685 throw new UTFDataFormatException();
3686 }
3687 b2 = readByte();
3688 b3 = readByte();
3689 if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
3690 throw new UTFDataFormatException();
3691 }
3692 sbuf.append((char) (((b1 & 0x0F) << 12) |
3693 ((b2 & 0x3F) << 6) |
3694 ((b3 & 0x3F) << 0)));
3695 return 3;
3696 }
3697 default -> throw new UTFDataFormatException(); // 10xx xxxx, 1111 xxxx
3698 }
3699 }
3700
3701 /**
3702 * {@return the number of bytes read from the input stream}
3703 */
3704 long getBytesRead() {
3705 return in.getBytesRead();
3706 }
3707 }
3708
3709 /**
3710 * Unsynchronized table which tracks wire handle to object mappings, as
3711 * well as ClassNotFoundExceptions associated with deserialized objects.
3712 * This class implements an exception-propagation algorithm for
3713 * determining which objects should have ClassNotFoundExceptions associated
3714 * with them, taking into account cycles and discontinuities (e.g., skipped
3715 * fields) in the object graph.
3716 *
3717 * <p>General use of the table is as follows: during deserialization, a
3718 * given object is first assigned a handle by calling the assign method.
3719 * This method leaves the assigned handle in an "open" state, wherein
3720 * dependencies on the exception status of other handles can be registered
3721 * by calling the markDependency method, or an exception can be directly
3722 * associated with the handle by calling markException. When a handle is
3723 * tagged with an exception, the HandleTable assumes responsibility for
3724 * propagating the exception to any other objects which depend
3725 * (transitively) on the exception-tagged object.
3726 *
3727 * <p>Once all exception information/dependencies for the handle have been
3728 * registered, the handle should be "closed" by calling the finish method
3729 * on it. The act of finishing a handle allows the exception propagation
3730 * algorithm to aggressively prune dependency links, lessening the
3731 * performance/memory impact of exception tracking.
3732 *
3733 * <p>Note that the exception propagation algorithm used depends on handles
3734 * being assigned/finished in LIFO order; however, for simplicity as well
3735 * as memory conservation, it does not enforce this constraint.
3736 */
3737 // REMIND: add full description of exception propagation algorithm?
3738 private static final class HandleTable {
3739
3740 /* status codes indicating whether object has associated exception */
3741 private static final byte STATUS_OK = 1;
3742 private static final byte STATUS_UNKNOWN = 2;
3743 private static final byte STATUS_EXCEPTION = 3;
3744
3745 /** array mapping handle -> object status */
3746 byte[] status;
3747 /** array mapping handle -> object/exception (depending on status) */
3748 Object[] entries;
3749 /** array mapping handle -> list of dependent handles (if any) */
3750 HandleList[] deps;
3751 /** lowest unresolved dependency */
3752 int lowDep = -1;
3753 /** number of handles in table */
3754 int size = 0;
3755
3756 /**
3757 * Creates handle table with the given initial capacity.
3758 */
3759 HandleTable(int initialCapacity) {
3760 status = new byte[initialCapacity];
3761 entries = new Object[initialCapacity];
3762 deps = new HandleList[initialCapacity];
3763 }
3764
3765 /**
3766 * Assigns next available handle to given object, and returns assigned
3767 * handle. Once object has been completely deserialized (and all
3768 * dependencies on other objects identified), the handle should be
3769 * "closed" by passing it to finish().
3770 */
3771 int assign(Object obj) {
3772 if (size >= entries.length) {
3773 grow();
3774 }
3775 status[size] = STATUS_UNKNOWN;
3776 entries[size] = obj;
3777 return size++;
3778 }
3779
3780 /**
3781 * Registers a dependency (in exception status) of one handle on
3782 * another. The dependent handle must be "open" (i.e., assigned, but
3783 * not finished yet). No action is taken if either dependent or target
3784 * handle is NULL_HANDLE. Additionally, no action is taken if the
3785 * dependent and target are the same.
3786 */
3787 void markDependency(int dependent, int target) {
3788 if (dependent == target || dependent == NULL_HANDLE || target == NULL_HANDLE) {
3789 return;
3790 }
3791 switch (status[dependent]) {
3792
3793 case STATUS_UNKNOWN:
3794 switch (status[target]) {
3795 case STATUS_OK:
3796 // ignore dependencies on objs with no exception
3797 break;
3798
3799 case STATUS_EXCEPTION:
3800 // eagerly propagate exception
3801 markException(dependent,
3802 (ClassNotFoundException) entries[target]);
3803 break;
3804
3805 case STATUS_UNKNOWN:
3806 // add to dependency list of target
3807 if (deps[target] == null) {
3808 deps[target] = new HandleList();
3809 }
3810 deps[target].add(dependent);
3811
3812 // remember lowest unresolved target seen
3813 if (lowDep < 0 || lowDep > target) {
3814 lowDep = target;
3815 }
3816 break;
3817
3818 default:
3819 throw new InternalError();
3820 }
3821 break;
3822
3823 case STATUS_EXCEPTION:
3824 break;
3825
3826 default:
3827 throw new InternalError();
3828 }
3829 }
3830
3831 /**
3832 * Associates a ClassNotFoundException (if one not already associated)
3833 * with the currently active handle and propagates it to other
3834 * referencing objects as appropriate. The specified handle must be
3835 * "open" (i.e., assigned, but not finished yet).
3836 */
3837 void markException(int handle, ClassNotFoundException ex) {
3838 switch (status[handle]) {
3839 case STATUS_UNKNOWN:
3840 status[handle] = STATUS_EXCEPTION;
3841 entries[handle] = ex;
3842
3843 // propagate exception to dependents
3844 HandleList dlist = deps[handle];
3845 if (dlist != null) {
3846 int ndeps = dlist.size();
3847 for (int i = 0; i < ndeps; i++) {
3848 markException(dlist.get(i), ex);
3849 }
3850 deps[handle] = null;
3851 }
3852 break;
3853
3854 case STATUS_EXCEPTION:
3855 break;
3856
3857 default:
3858 throw new InternalError();
3859 }
3860 }
3861
3862 /**
3863 * Marks given handle as finished, meaning that no new dependencies
3864 * will be marked for handle. Calls to the assign and finish methods
3865 * must occur in LIFO order.
3866 */
3867 void finish(int handle) {
3868 int end;
3869 if (lowDep < 0) {
3870 // no pending unknowns, only resolve current handle
3871 end = handle + 1;
3872 } else if (lowDep >= handle) {
3873 // pending unknowns now clearable, resolve all upward handles
3874 end = size;
3875 lowDep = -1;
3876 } else {
3877 // unresolved backrefs present, can't resolve anything yet
3878 return;
3879 }
3880
3881 // change STATUS_UNKNOWN -> STATUS_OK in selected span of handles
3882 for (int i = handle; i < end; i++) {
3883 switch (status[i]) {
3884 case STATUS_UNKNOWN:
3885 status[i] = STATUS_OK;
3886 deps[i] = null;
3887 break;
3888
3889 case STATUS_OK:
3890 case STATUS_EXCEPTION:
3891 break;
3892
3893 default:
3894 throw new InternalError();
3895 }
3896 }
3897 }
3898
3899 /**
3900 * Assigns a new object to the given handle. The object previously
3901 * associated with the handle is forgotten. This method has no effect
3902 * if the given handle already has an exception associated with it.
3903 * This method may be called at any time after the handle is assigned.
3904 */
3905 void setObject(int handle, Object obj) {
3906 switch (status[handle]) {
3907 case STATUS_UNKNOWN:
3908 case STATUS_OK:
3909 entries[handle] = obj;
3910 break;
3911
3912 case STATUS_EXCEPTION:
3913 break;
3914
3915 default:
3916 throw new InternalError();
3917 }
3918 }
3919
3920 /**
3921 * Looks up and returns object associated with the given handle.
3922 * Returns null if the given handle is NULL_HANDLE, or if it has an
3923 * associated ClassNotFoundException.
3924 */
3925 Object lookupObject(int handle) {
3926 return (handle != NULL_HANDLE &&
3927 status[handle] != STATUS_EXCEPTION) ?
3928 entries[handle] : null;
3929 }
3930
3931 /**
3932 * Looks up and returns ClassNotFoundException associated with the
3933 * given handle. Returns null if the given handle is NULL_HANDLE, or
3934 * if there is no ClassNotFoundException associated with the handle.
3935 */
3936 ClassNotFoundException lookupException(int handle) {
3937 return (handle != NULL_HANDLE &&
3938 status[handle] == STATUS_EXCEPTION) ?
3939 (ClassNotFoundException) entries[handle] : null;
3940 }
3941
3942 /**
3943 * Resets table to its initial state.
3944 */
3945 void clear() {
3946 Arrays.fill(status, 0, size, (byte) 0);
3947 Arrays.fill(entries, 0, size, null);
3948 Arrays.fill(deps, 0, size, null);
3949 lowDep = -1;
3950 size = 0;
3951 }
3952
3953 /**
3954 * Returns number of handles registered in table.
3955 */
3956 int size() {
3957 return size;
3958 }
3959
3960 /**
3961 * Expands capacity of internal arrays.
3962 */
3963 private void grow() {
3964 int newCapacity = (entries.length << 1) + 1;
3965
3966 byte[] newStatus = new byte[newCapacity];
3967 Object[] newEntries = new Object[newCapacity];
3968 HandleList[] newDeps = new HandleList[newCapacity];
3969
3970 System.arraycopy(status, 0, newStatus, 0, size);
3971 System.arraycopy(entries, 0, newEntries, 0, size);
3972 System.arraycopy(deps, 0, newDeps, 0, size);
3973
3974 status = newStatus;
3975 entries = newEntries;
3976 deps = newDeps;
3977 }
3978
3979 /**
3980 * Simple growable list of (integer) handles.
3981 */
3982 private static class HandleList {
3983 private int[] list = new int[4];
3984 private int size = 0;
3985
3986 public HandleList() {
3987 }
3988
3989 public void add(int handle) {
3990 if (size >= list.length) {
3991 int[] newList = new int[list.length << 1];
3992 System.arraycopy(list, 0, newList, 0, list.length);
3993 list = newList;
3994 }
3995 list[size++] = handle;
3996 }
3997
3998 public int get(int index) {
3999 if (index >= size) {
4000 throw new ArrayIndexOutOfBoundsException();
4001 }
4002 return list[index];
4003 }
4004
4005 public int size() {
4006 return size;
4007 }
4008 }
4009 }
4010
4011 /**
4012 * Method for cloning arrays in case of using unsharing reading
4013 */
4014 private static Object cloneArray(Object array) {
4015 if (array instanceof Object[]) {
4016 return ((Object[]) array).clone();
4017 } else if (array instanceof boolean[]) {
4018 return ((boolean[]) array).clone();
4019 } else if (array instanceof byte[]) {
4020 return ((byte[]) array).clone();
4021 } else if (array instanceof char[]) {
4022 return ((char[]) array).clone();
4023 } else if (array instanceof double[]) {
4024 return ((double[]) array).clone();
4025 } else if (array instanceof float[]) {
4026 return ((float[]) array).clone();
4027 } else if (array instanceof int[]) {
4028 return ((int[]) array).clone();
4029 } else if (array instanceof long[]) {
4030 return ((long[]) array).clone();
4031 } else if (array instanceof short[]) {
4032 return ((short[]) array).clone();
4033 } else {
4034 throw new AssertionError();
4035 }
4036 }
4037
4038 static {
4039 SharedSecrets.setJavaObjectInputStreamAccess(ObjectInputStream::checkArray);
4040 SharedSecrets.setJavaObjectInputStreamReadString(ObjectInputStream::readString);
4041 }
4042
4043 }