< prev index next >

test/jdk/java/io/Serializable/records/BadCanonicalCtrTest.java

Print this page

  1 /*
  2  * Copyright (c) 2019, 2025, 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.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 
 24 /*
 25  * @test
 26  * @bug 8246774
 27  * @summary InvalidClassException is thrown when the canonical constructor
 28  *          cannot be found during deserialization.
 29  * @library /test/lib
 30  * @run junit BadCanonicalCtrTest
 31  */
 32 
 33 import java.io.ByteArrayInputStream;
 34 import java.io.ByteArrayOutputStream;
 35 import java.io.IOException;
 36 import java.io.InvalidClassException;
 37 import java.io.ObjectInputStream;
 38 import java.io.ObjectOutputStream;
 39 import java.io.ObjectStreamClass;
 40 import java.lang.classfile.ClassTransform;
 41 import java.lang.classfile.ClassFile;
 42 import java.lang.classfile.MethodModel;

 43 import java.lang.constant.MethodTypeDesc;
 44 
 45 import jdk.test.lib.compiler.InMemoryJavaCompiler;
 46 import jdk.test.lib.ByteCodeLoader;
 47 import static java.lang.System.out;
 48 import static java.lang.classfile.ClassFile.ACC_PUBLIC;
 49 import static java.lang.constant.ConstantDescs.CD_Object;
 50 import static java.lang.constant.ConstantDescs.CD_void;
 51 import static java.lang.constant.ConstantDescs.INIT_NAME;
 52 import static java.lang.constant.ConstantDescs.MTD_void;
 53 
 54 import org.junit.jupiter.api.Assertions;
 55 import static org.junit.jupiter.api.Assertions.assertTrue;
 56 import org.junit.jupiter.api.BeforeAll;
 57 import org.junit.jupiter.api.TestInstance;
 58 import org.junit.jupiter.params.ParameterizedTest;
 59 import org.junit.jupiter.params.provider.MethodSource;
 60 
 61 /**
 62  * Checks that an InvalidClassException is thrown when the canonical
 63  * constructor cannot be found during deserialization.
 64  */
 65 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
 66 public class BadCanonicalCtrTest {
 67 
 68     // ClassLoader for creating instances of the records to test with.
 69     ClassLoader goodRecordClassLoader;
 70     // ClassLoader that can be used during deserialization. Loads record
 71     // classes where the canonical constructor has been removed.
 72     ClassLoader missingCtrClassLoader;

203     }
204 
205     // -- machinery for augmenting record class bytes --
206 
207     /**
208      * Removes the constructor from the given class bytes.
209      * Assumes just a single, canonical, constructor.
210      */
211     static byte[] removeConstructor(byte[] classBytes) {
212         var cf = ClassFile.of();
213         return cf.transformClass(cf.parse(classBytes), ClassTransform.dropping(ce ->
214                 ce instanceof MethodModel mm && mm.methodName().equalsString(INIT_NAME)));
215     }
216 
217     /**
218      * Modifies the descriptor of the constructor from the given class bytes.
219      * Assumes just a single, canonical, constructor.
220      */
221     static byte[] modifyConstructor(byte[] classBytes) {
222         var cf = ClassFile.of();

223         return cf.transformClass(cf.parse(classBytes), ClassTransform.dropping(ce ->
224                         ce instanceof MethodModel mm && mm.methodName().equalsString(INIT_NAME))
225                 .andThen(ClassTransform.endHandler(clb -> clb.withMethodBody(INIT_NAME,
226                         MethodTypeDesc.of(CD_void, CD_Object), ACC_PUBLIC, cob -> {


















227                             cob.aload(0);
228                             cob.invokespecial(Record.class.describeConstable().orElseThrow(),
229                                     INIT_NAME, MTD_void);
230                             cob.return_();
231                         }))));
232     }
233 }

  1 /*
  2  * Copyright (c) 2019, 2026, 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.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 
 24 /*
 25  * @test
 26  * @bug 8246774
 27  * @summary InvalidClassException is thrown when the canonical constructor
 28  *          cannot be found during deserialization.
 29  * @library /test/lib
 30  * @run junit BadCanonicalCtrTest
 31  */
 32 
 33 import java.io.ByteArrayInputStream;
 34 import java.io.ByteArrayOutputStream;
 35 import java.io.IOException;
 36 import java.io.InvalidClassException;
 37 import java.io.ObjectInputStream;
 38 import java.io.ObjectOutputStream;
 39 import java.io.ObjectStreamClass;
 40 import java.lang.classfile.ClassTransform;
 41 import java.lang.classfile.ClassFile;
 42 import java.lang.classfile.MethodModel;
 43 import java.lang.classfile.TypeKind;
 44 import java.lang.constant.MethodTypeDesc;
 45 
 46 import jdk.test.lib.compiler.InMemoryJavaCompiler;
 47 import jdk.test.lib.ByteCodeLoader;
 48 import static java.lang.System.out;
 49 import static java.lang.classfile.ClassFile.*;
 50 import static java.lang.constant.ConstantDescs.*;



 51 
 52 import org.junit.jupiter.api.Assertions;
 53 import static org.junit.jupiter.api.Assertions.assertTrue;
 54 import org.junit.jupiter.api.BeforeAll;
 55 import org.junit.jupiter.api.TestInstance;
 56 import org.junit.jupiter.params.ParameterizedTest;
 57 import org.junit.jupiter.params.provider.MethodSource;
 58 
 59 /**
 60  * Checks that an InvalidClassException is thrown when the canonical
 61  * constructor cannot be found during deserialization.
 62  */
 63 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
 64 public class BadCanonicalCtrTest {
 65 
 66     // ClassLoader for creating instances of the records to test with.
 67     ClassLoader goodRecordClassLoader;
 68     // ClassLoader that can be used during deserialization. Loads record
 69     // classes where the canonical constructor has been removed.
 70     ClassLoader missingCtrClassLoader;

201     }
202 
203     // -- machinery for augmenting record class bytes --
204 
205     /**
206      * Removes the constructor from the given class bytes.
207      * Assumes just a single, canonical, constructor.
208      */
209     static byte[] removeConstructor(byte[] classBytes) {
210         var cf = ClassFile.of();
211         return cf.transformClass(cf.parse(classBytes), ClassTransform.dropping(ce ->
212                 ce instanceof MethodModel mm && mm.methodName().equalsString(INIT_NAME)));
213     }
214 
215     /**
216      * Modifies the descriptor of the constructor from the given class bytes.
217      * Assumes just a single, canonical, constructor.
218      */
219     static byte[] modifyConstructor(byte[] classBytes) {
220         var cf = ClassFile.of();
221         var classModel = cf.parse(classBytes);
222         return cf.transformClass(cf.parse(classBytes), ClassTransform.dropping(ce ->
223                         ce instanceof MethodModel mm && mm.methodName().equalsString(INIT_NAME))
224                 .andThen(ClassTransform.endHandler(clb -> clb.withMethodBody(INIT_NAME,
225                         MethodTypeDesc.of(CD_void, CD_Object), ACC_PUBLIC, cob -> {
226                             // Initialize strict fields, if any
227                             for (var field : classModel.fields()) {
228                                 if ((field.flags().flagsMask() & (ACC_STRICT_INIT | ACC_STATIC)) != ACC_STRICT_INIT) {
229                                     continue;
230                                 }
231                                 var fieldType = field.fieldTypeSymbol();
232                                 cob.aload(0);
233                                 switch (TypeKind.from(fieldType).asLoadable()) {
234                                     case INT -> cob.iconst_0();
235                                     case LONG -> cob.lconst_0();
236                                     case FLOAT -> cob.fconst_0();
237                                     case DOUBLE -> cob.dconst_0();
238                                     case REFERENCE -> cob.aconst_null();
239                                     default -> throw new IllegalArgumentException(fieldType.descriptorString());
240                                 }
241                                 var cp = cob.constantPool();
242                                 cob.putfield(cp.fieldRefEntry(classModel.thisClass(), cp.nameAndTypeEntry(field.fieldName(), field.fieldType())));
243                             }
244                             cob.aload(0);
245                             cob.invokespecial(Record.class.describeConstable().orElseThrow(),
246                                     INIT_NAME, MTD_void);
247                             cob.return_();
248                         }))));
249     }
250 }
< prev index next >