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