Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[regression] java.lang.VerifyError: Operand stack overflow #1256

Closed
snjeza opened this issue Jul 31, 2023 · 12 comments · Fixed by #1265
Closed

[regression] java.lang.VerifyError: Operand stack overflow #1256

snjeza opened this issue Jul 31, 2023 · 12 comments · Fixed by #1265
Labels
bug Something isn't working regression Something was broken by a previous change

Comments

@snjeza
Copy link
Contributor

snjeza commented Jul 31, 2023

Related issues

Steps to reproduce

  • create the following class
public class Test {
	public static void main(String[] args) {
		String value = "abc";
		value.equalsIgnoreCase("" + null);
		System.out.println(value.substring(1));
	}
}
  • run it
    It throws
Error: Unable to initialize main class org.sample.Test
Caused by: java.lang.VerifyError: Operand stack overflow
Exception Details:
  Location:
    org/sample/Test.main([Ljava/lang/String;)V @17: iconst_1
  Reason:
    Exceeded max stack size.
  Current Frame:
    bci: @17
    flags: { }
    locals: { '[Ljava/lang/String;', 'java/lang/String' }
    stack: { 'java/io/PrintStream', 'java/lang/String' }
  Bytecode:
    0000000: 1210 4c2b ba00 1200 00b6 0016 57b2 001c
    0000010: 2b04 b600 22b6 0026 b1                 

A workaorund
set org.eclipse.jdt.core.compiler.codegen.useStringConcatFactory = disabled

The issue has been caused by be45d8f

It can't be reproduced in Eclipse <= I20230628-1800

@iloveeclipse iloveeclipse added bug Something isn't working regression Something was broken by a previous change labels Jul 31, 2023
@iloveeclipse
Copy link
Member

@jarthana : could you please take a look?

@snjeza
Copy link
Contributor Author

snjeza commented Jul 31, 2023

A potential patch:

diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/Expression.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/Expression.java
index 7e091ed000..1b61a45530 100644
--- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/Expression.java
+++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/Expression.java
@@ -966,14 +966,9 @@ public void buildStringForConcatation(BlockScope blockScope, CodeStream codeStre
 				addArgumentToRecipe(blockScope, codeStream, recipe, this.resolvedType, argTypes);
 				break;
 			default :
-				if (this.resolvedType.id == TypeIds.T_null) {
-					// Optimize it, avoid aconst_null, simply append the String Literal
-					recipe.append((String) null);
-				} else {
-					generateCode(blockScope, codeStream, true);
-					codeStream.invokeStringValueOf(typeID);
-					addArgumentToRecipe(blockScope, codeStream, recipe, blockScope.getJavaLangString(), argTypes);
-				}
+				generateCode(blockScope, codeStream, true);
+				codeStream.invokeStringValueOf(typeID);
+				addArgumentToRecipe(blockScope, codeStream, recipe, blockScope.getJavaLangString(), argTypes);
 				break;
 		}
 	} else {

@iloveeclipse
Copy link
Member

A potential patch:

  1. Does it passes the tests?
  2. Could you provide a regression test?

@snjeza
Copy link
Contributor Author

snjeza commented Jul 31, 2023

@iloveeclipse I will try.

@snjeza
Copy link
Contributor Author

snjeza commented Jul 31, 2023

Does it passes the tests?
Could you provide a regression test?

@iloveeclipse I have updated the regression tests.

@iloveeclipse
Copy link
Member

I have updated the regression tests.

Thanks. But can you please add your own test (with the snippet from bug description) that shows the fix is working?

@snjeza
Copy link
Contributor Author

snjeza commented Jul 31, 2023

But can you please add your own test (with the snippet from bug description) that shows the fix is working

Yes, I can.
@iloveeclipse I have added it - 9a33f67#diff-621ae34c3c2a3c4ab0ed4676ffdbba5af95c72e7437dad5b7448c9251c7754afR1128

@jarthana
Copy link
Member

jarthana commented Aug 3, 2023

I think the reason why the fix works is it increments the stack length by way of valueOf, which makes enough room for the subsequent iconst_1 operation. Of course, the problem was we were short on stack length to begin with is the cause and hence the fix works. Perhaps we should investigate why the stack is insufficient.

If I make the following change, I don't see the problem:

//		System.out.println(value.substring(1));
		String str = value.substring(1);

@jarthana
Copy link
Member

jarthana commented Aug 3, 2023

OK, I see that right after the concat statement, the stackDepth goes down by one. The reason is, we don't really add any stackDepth for the null operand as a result of this code but later the invokedynamic makes decrements the stackDepth by one (because arguments - returntypes = -1) :

				if (this.resolvedType.id == TypeIds.T_null) {
					// Optimize it, avoid aconst_null, simply append the String Literal
					recipe.append((String) null);
				}

We have two options:

  1. We either remove the optimization and put back the aconstnull or
  2. just plainly increment the stackDepth by 1 to account for the reduction we expect to happen later.

I am inclined to go with the first.

@snjeza Your patch works, but it generates lot of additional code for the null constant. What do you think of the options I just mentioned?

@snjeza
Copy link
Contributor Author

snjeza commented Aug 3, 2023

  1. just plainly increment the stackDepth by 1 to account for the reduction we expect to happen later.

@jarthana This works fine.
I have updated the PR - 77bab66

@jarthana
Copy link
Member

jarthana commented Aug 3, 2023

  1. just plainly increment the stackDepth by 1 to account for the reduction we expect to happen later.

@jarthana This works fine. I have updated the PR - 77bab66

@snjeza
Thinking again, the approach to just increment the stackDepth is probably kludge. And it's not enough just to increment it. We must also adjust the stackMax if required as can be seen in many other places that increment that count.

Here's an alternate fix : #1265

@snjeza
Copy link
Contributor Author

snjeza commented Aug 3, 2023

@snjeza
Thinking again, the approach to just increment the stackDepth is probably kludge. And it's not enough just to increment it. We must also adjust the stackMax if required as can be seen in many other places that increment that count.
Here's an alternate fix : #1265

@jarthana #1265 fixes the issue, but ConstantTest.test009() should be fixed.

jarthana added a commit that referenced this issue Aug 3, 2023
Optimizing away the aconstnull doesn't increment the stackdepth, which is causing the issue. The fix puts it back.

Co-authored-by: Snjezana Peco <snjezana.peco@redhat.com>
robstryker pushed a commit to robstryker/eclipse.jdt.core that referenced this issue Jul 18, 2024
…t#1256 (eclipse-jdt#1265)

Optimizing away the aconstnull doesn't increment the stackdepth, which is causing the issue. The fix puts it back.

Co-authored-by: Snjezana Peco <snjezana.peco@redhat.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working regression Something was broken by a previous change
Projects
None yet
3 participants