RFR: 8204322: "+=" applied to String operands can provoke side effects
Vicente Romero
vicente.romero at oracle.com
Wed Jun 6 15:55:57 UTC 2018
Hi,
On 06/06/2018 11:50 AM, B. Blaser wrote:
> Hi Vicente,
>
> On 6 June 2018 at 15:23, Vicente Romero <vicente.romero at oracle.com> wrote:
>> Please review the fix for [1] at [2]. Javac was generating incorrect code
>> for the case when the `+=` operand was applied to Strings and it is visible
>> for test cases like:
>>
>> public class Test {
>> static int test() {
>> System.out.println("evaluated");
>> return 0;
>> }
>>
>> public static void main(String[] args) {
>> String[] array = {""};
>> array[test()] += "a";
>> }
>> }
>>
>> the string "evaluated" is printed twice. Some items were missing in the
>> stack, the solution is to duplicate those missing items plus not to evaluate
>> the lhs expression twice.
>>
>> Thanks in advance for the comments,
>> Vicente
>>
>> Thanks to Aleksey Shipilev for the great regression test.
>>
>> [1] https://bugs.openjdk.java.net/browse/JDK-8204322
>> [2] http://cr.openjdk.java.net/~vromero/8204322/webrev.01/
>>
> I hope I'm not too late, but I was also trying to solve this problem
> (here under).
> So, our solutions are quite identical (yours being a bit better), but
> I think you could avoid 'boolean first' using 'arg == args.head'
just pushed it a while ago :( but yes I like your suggestion I will
leave a note for a future improvement
> instead.
>
> Cheers,
> Bernard
Thanks,
Vicente
>
>
> diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java
> b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java
> --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java
> +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java
> @@ -261,18 +261,18 @@
> public Item makeConcat(JCTree.JCAssignOp tree) {
> List<JCTree> args = collectAll(tree.lhs, tree.rhs);
> Item l = gen.genExpr(tree.lhs, tree.lhs.type);
> - emit(args, tree.type, tree.pos());
> + emit(l, args, tree.type, tree.pos());
> return l;
> }
>
> @Override
> public Item makeConcat(JCTree.JCBinary tree) {
> List<JCTree> args = collectAll(tree.lhs, tree.rhs);
> - emit(args, tree.type, tree.pos());
> + emit(null, args, tree.type, tree.pos());
> return gen.getItems().makeStackItem(syms.stringType);
> }
>
> - protected abstract void emit(List<JCTree> args, Type type,
> JCDiagnostic.DiagnosticPosition pos);
> + protected abstract void emit(Item lhs, List<JCTree> args,
> Type type, JCDiagnostic.DiagnosticPosition pos);
>
> /** Peel the argument list into smaller chunks. */
> protected List<List<JCTree>> split(List<JCTree> args) {
> @@ -318,7 +318,7 @@
> }
>
> /** Emit the indy concat for all these arguments, possibly
> peeling along the way */
> - protected void emit(List<JCTree> args, Type type,
> JCDiagnostic.DiagnosticPosition pos) {
> + protected void emit(Item lhs, List<JCTree> args, Type type,
> JCDiagnostic.DiagnosticPosition pos) {
> List<List<JCTree>> split = split(args);
>
> for (List<JCTree> t : split) {
> @@ -333,7 +333,13 @@
> } else {
> dynamicArgs.add(sharpestAccessible(arg.type));
> }
> - gen.genExpr(arg, arg.type).load();
> +
> + if (lhs != null && arg == args.head) {
> + lhs.duplicate();
> + lhs.load();
> + }
> + else
> + gen.genExpr(arg, arg.type).load();
> }
>
> doCall(type, pos, dynamicArgs.toList());
> @@ -402,7 +408,7 @@
> }
>
> @Override
> - protected void emit(List<JCTree> args, Type type,
> JCDiagnostic.DiagnosticPosition pos) {
> + protected void emit(Item lhs, List<JCTree> args, Type type,
> JCDiagnostic.DiagnosticPosition pos) {
> List<List<JCTree>> split = split(args);
>
> for (List<JCTree> t : split) {
> @@ -433,7 +439,13 @@
> // Ordinary arguments come through the
> dynamic arguments.
> recipe.append(TAG_ARG);
> dynamicArgs.add(sharpestAccessible(arg.type));
> - gen.genExpr(arg, arg.type).load();
> +
> + if (lhs != null && arg == args.head) {
> + lhs.duplicate();
> + lhs.load();
> + }
> + else
> + gen.genExpr(arg, arg.type).load();
> }
> }
More information about the compiler-dev
mailing list