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