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