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