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