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