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