diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/StackMapGenerator.java b/src/java.base/share/classes/jdk/internal/classfile/impl/StackMapGenerator.java index 71ce907efc4..3fafc9fdc8b 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/StackMapGenerator.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/StackMapGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2024, Alibaba Group Holding Limited. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -1110,6 +1110,9 @@ public final class StackMapGenerator { locals[localsSize++] = type; } } + if (locals != null && localsSize < locals.length) { + Arrays.fill(locals, localsSize, locals.length, Type.TOP_TYPE); + } this.localsSize = localsSize; } diff --git a/test/jdk/jdk/classfile/StackMapsTest.java b/test/jdk/jdk/classfile/StackMapsTest.java index b2f94596622..7cf6234e88f 100644 --- a/test/jdk/jdk/classfile/StackMapsTest.java +++ b/test/jdk/jdk/classfile/StackMapsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @summary Testing Classfile stack maps generator. - * @bug 8305990 8320222 8320618 8335475 8338623 8338661 8343436 + * @bug 8305990 8320222 8320618 8335475 8338623 8338661 8343436 8386700 * @build testdata.* * @run junit StackMapsTest */ @@ -415,4 +415,29 @@ class StackMapsTest { assertEquals(2, code.maxLocals()); assertEquals(2, code.maxStack()); } + + @Test + void testStaleLocals() { + byte[] bytes = ClassFile.of().build(ClassDesc.of("Repro"), clb -> clb + .withMethodBody("m", MethodTypeDesc.of(CD_void, CD_int), ACC_STATIC, cob -> { + var cond = cob.newLabel(); + var back = cob.newLabel(); + var fwd = cob.newLabel(); + cob.iconst_0() + .istore(1) // stale slot 1 holding of a long incorrectly clears slot 0 in the second round + .iload(1) + .ifeq(cond) // conditional branch triggers merge of frames + .goto_(fwd) + .labelBinding(cond) + .iload(0) // invalid stack frame when slot 0 is cleared + .pop() + .labelBinding(back) + .return_() + .labelBinding(fwd) + .lconst_0() + .lstore(0) // long overrides slots 0 and 1 + .goto_(back); // back jump with modified locals triggers second round with stale slots + })); + assertEmpty(ClassFile.of().verify(bytes)); + } }