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