Skip to content

Commit

Permalink
Fix casting bug in compound assignment for String (#65329)
Browse files Browse the repository at this point in the history
This change fixes a bug where when doing compound assignment involving String concatenation, the 
right-hand side will fail to cast to String appropriately and throw a ClassCastException.
  • Loading branch information
jdconrad committed Nov 20, 2020
1 parent 56605e4 commit 89ec7db
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -935,6 +935,7 @@ public void visitAssignment(EAssignment userAssignmentNode, SemanticScope semant
Class<?> rightValueType = semanticScope.getDecoration(userRightNode, ValueType.class).getValueType();

Class<?> compoundType;
boolean isConcatenation = false;
Class<?> shiftType = null;
boolean isShift = false;

Expand All @@ -946,6 +947,7 @@ public void visitAssignment(EAssignment userAssignmentNode, SemanticScope semant
compoundType = AnalyzerCaster.promoteNumeric(leftValueType, rightValueType, true);
} else if (operation == Operation.ADD) {
compoundType = AnalyzerCaster.promoteAdd(leftValueType, rightValueType);
isConcatenation = compoundType == String.class;
} else if (operation == Operation.SUB) {
compoundType = AnalyzerCaster.promoteNumeric(leftValueType, rightValueType, true);
} else if (operation == Operation.LSH) {
Expand Down Expand Up @@ -975,7 +977,9 @@ public void visitAssignment(EAssignment userAssignmentNode, SemanticScope semant
"cannot apply [" + operation.symbol + "=] to types [" + leftValueType + "] and [" + rightValueType + "]"));
}

if (isShift) {
if (isConcatenation) {
semanticScope.putDecoration(userRightNode, new TargetType(rightValueType));
} else if (isShift) {
if (compoundType == def.class) {
// shifts are promoted independently, but for the def type, we need object.
semanticScope.putDecoration(userRightNode, new TargetType(def.class));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -345,4 +345,93 @@ public void testBoxedDefCalls() {
expectScriptThrows(ClassCastException.class, () -> exec("def x = 2.0; def y = 1; y.compareTo(x);"));
expectScriptThrows(ClassCastException.class, () -> exec("float f = 1.0f; def y = 1; y.compareTo(f);"));
}

public void testCompoundAssignmentStringCasts() {
assertEquals("s71", exec("String s = 's'; byte c = 71; s += c; return s"));
assertEquals("s71", exec("String s = 's'; short c = 71; s += c; return s"));
assertEquals("sG", exec("String s = 's'; char c = 71; s += c; return s"));
assertEquals("s71", exec("String s = 's'; int c = 71; s += c; return s"));
assertEquals("s71", exec("String s = 's'; long c = 71; s += c; return s"));
assertEquals("s71.0", exec("String s = 's'; float c = 71; s += c; return s"));
assertEquals("s71.0", exec("String s = 's'; double c = 71; s += c; return s"));
assertEquals("s71", exec("String s = 's'; String c = '71'; s += c; return s"));
assertEquals("s[71]", exec("String s = 's'; List c = [71]; s += c; return s"));

assertEquals("s71s", exec("String s = 's'; byte c = 71; s += c + s; return s"));
assertEquals("s71s", exec("String s = 's'; short c = 71; s += c + s; return s"));
assertEquals("sGs", exec("String s = 's'; char c = 71; s += c + s; return s"));
assertEquals("s71s", exec("String s = 's'; int c = 71; s += c + s; return s"));
assertEquals("s71s", exec("String s = 's'; long c = 71; s += c + s; return s"));
assertEquals("s71.0s", exec("String s = 's'; float c = 71; s += c + s; return s"));
assertEquals("s71.0s", exec("String s = 's'; double c = 71; s += c + s; return s"));
assertEquals("s71s", exec("String s = 's'; String c = '71'; s += c + s; return s"));
assertEquals("s[71]s", exec("String s = 's'; List c = [71]; s += c + s; return s"));

assertEquals("s142", exec("String s = 's'; byte c = 71; s += c + c; return s"));
assertEquals("s142", exec("String s = 's'; short c = 71; s += c + c; return s"));
assertEquals("s142", exec("String s = 's'; char c = 71; s += c + c; return s"));
assertEquals("s142", exec("String s = 's'; int c = 71; s += c + c; return s"));
assertEquals("s142", exec("String s = 's'; long c = 71; s += c + c; return s"));
assertEquals("s142.0", exec("String s = 's'; float c = 71; s += c + c; return s"));
assertEquals("s142.0", exec("String s = 's'; double c = 71; s += c + c; return s"));
assertEquals("s7171", exec("String s = 's'; String c = '71'; s += c + c; return s"));

assertEquals("s7171", exec("String s = 's'; byte c = 71; s += c + '' + c; return s"));
assertEquals("s7171", exec("String s = 's'; short c = 71; s += c + '' + c; return s"));
assertEquals("sGG", exec("String s = 's'; char c = 71; s += c + '' + c; return s"));
assertEquals("s7171", exec("String s = 's'; int c = 71; s += c + '' + c; return s"));
assertEquals("s7171", exec("String s = 's'; long c = 71; s += c + '' + c; return s"));
assertEquals("s71.071.0", exec("String s = 's'; float c = 71; s += c + '' + c; return s"));
assertEquals("s71.071.0", exec("String s = 's'; double c = 71; s += c + '' + c; return s"));
assertEquals("s7171", exec("String s = 's'; String c = '71'; s += c + '' + c; return s"));
assertEquals("s[71][71]", exec("String s = 's'; List c = [71]; s += c + '' + c; return s"));

assertEquals("s142", exec("String s = 's'; byte c = 71; s += c + c + ''; return s"));
assertEquals("s142", exec("String s = 's'; short c = 71; s += c + c + ''; return s"));
assertEquals("s142", exec("String s = 's'; char c = 71; s += c + c + ''; return s"));
assertEquals("s142", exec("String s = 's'; int c = 71; s += c + c + ''; return s"));
assertEquals("s142", exec("String s = 's'; long c = 71; s += c + c + ''; return s"));
assertEquals("s142.0", exec("String s = 's'; float c = 71; s += c + c + ''; return s"));
assertEquals("s142.0", exec("String s = 's'; double c = 71; s += c + c + ''; return s"));
assertEquals("s7171", exec("String s = 's'; String c = '71'; s += c + c + ''; return s"));

assertEquals("s7171", exec("String s = 's'; byte c = 71; s += '' + c + c; return s"));
assertEquals("s7171", exec("String s = 's'; short c = 71; s += '' + c + c; return s"));
assertEquals("sGG", exec("String s = 's'; char c = 71; s += '' + c + c; return s"));
assertEquals("s7171", exec("String s = 's'; int c = 71; s += '' + c + c; return s"));
assertEquals("s7171", exec("String s = 's'; long c = 71; s += '' + c + c; return s"));
assertEquals("s71.071.0", exec("String s = 's'; float c = 71; s += '' + c + c; return s"));
assertEquals("s71.071.0", exec("String s = 's'; double c = 71; s += '' + c + c; return s"));
assertEquals("s7171", exec("String s = 's'; String c = '71'; s += '' + c + c; return s"));
assertEquals("s[71][71]", exec("String s = 's'; List c = [71]; s += '' + c + c; return s"));

assertEquals("s71s71", exec("String s = 's'; byte c = 71; s += c + s + c; return s"));
assertEquals("s71s71", exec("String s = 's'; short c = 71; s += c + s + c; return s"));
assertEquals("sGsG", exec("String s = 's'; char c = 71; s += c + s + c; return s"));
assertEquals("s71s71", exec("String s = 's'; int c = 71; s += c + s + c; return s"));
assertEquals("s71s71", exec("String s = 's'; long c = 71; s += c + s + c; return s"));
assertEquals("s71.0s71.0", exec("String s = 's'; float c = 71; s += c + s + c; return s"));
assertEquals("s71.0s71.0", exec("String s = 's'; double c = 71; s += c + s + c; return s"));
assertEquals("s71s71", exec("String s = 's'; String c = '71'; s += c + s + c; return s"));
assertEquals("s[71]s[71]", exec("String s = 's'; List c = [71]; s += c + s + c; return s"));

assertEquals("s142s", exec("String s = 's'; byte c = 71; s += c + c + s; return s"));
assertEquals("s142s", exec("String s = 's'; short c = 71; s += c + c + s; return s"));
assertEquals("s142s", exec("String s = 's'; char c = 71; s += c + c + s; return s"));
assertEquals("s142s", exec("String s = 's'; int c = 71; s += c + c + s; return s"));
assertEquals("s142s", exec("String s = 's'; long c = 71; s += c + c + s; return s"));
assertEquals("s142.0s", exec("String s = 's'; float c = 71; s += c + c + s; return s"));
assertEquals("s142.0s", exec("String s = 's'; double c = 71; s += c + c + s; return s"));
assertEquals("s7171s", exec("String s = 's'; String c = '71'; s += c + c + s; return s"));

assertEquals("ss7171", exec("String s = 's'; byte c = 71; s += s + c + c; return s"));
assertEquals("ss7171", exec("String s = 's'; short c = 71; s += s + c + c; return s"));
assertEquals("ssGG", exec("String s = 's'; char c = 71; s += s + c + c; return s"));
assertEquals("ss7171", exec("String s = 's'; int c = 71; s += s + c + c; return s"));
assertEquals("ss7171", exec("String s = 's'; long c = 71; s += s + c + c; return s"));
assertEquals("ss71.071.0", exec("String s = 's'; float c = 71; s += s + c + c; return s"));
assertEquals("ss71.071.0", exec("String s = 's'; double c = 71; s += s + c + c; return s"));
assertEquals("ss7171", exec("String s = 's'; String c = '71'; s += s + c + c; return s"));
assertEquals("ss[71][71]", exec("String s = 's'; List c = [71]; s += s + c + c; return s"));
}
}

0 comments on commit 89ec7db

Please sign in to comment.