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
Bad bytecode generated by scalac allowing null values through "if (x != null)" blocks #10041
Comments
Imported From: https://issues.scala-lang.org/browse/SI-10041?orig=1
|
@adriaanm said: |
@retronym said: public static final scala.Tuple2 $anonfun$parse$38(scala.runtime.IntRef, long, gsa.shared.units.Currency, scala.math.BigDecimal, gsa.shared.accounting.AccountingDate, gsa.furnace.core.EventState);
descriptor: (Lscala/runtime/IntRef;JLgsa/shared/units/Currency;Lscala/math/BigDecimal;Lgsa/shared/accounting/AccountingDate;Lgsa/furnace/core/EventState;)Lscala/Tuple2;
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
Code:
stack=7, locals=8, args_size=6
0: lload_1
1: lload_1
2: invokestatic #351 // Method gsa/furnace/client/ListedTransactionUpdateBuilder.from:(JJ)Lgsa/furnace/client/ListedTransactionUpdateBuilder;
5: astore 7
7: aload_3
8: ifnull 105
11: aload 4
13: ifnull 105
16: aload 7
18: aload_3
19: aload 4
21: invokevirtual #357 // Method scala/math/BigDecimal.bigDecimal:()Ljava/math/BigDecimal;
24: invokevirtual #361 // Method gsa/furnace/client/ListedTransactionUpdateBuilder.settlement:(Lgsa/shared/units/Currency;Ljava/math/BigDecimal;)Lgsa/furnace/client/ListedTransactionUpdateBuilder;
27: pop
28: aload 7
30: invokevirtual #365 // Method gsa/furnace/client/ListedTransactionUpdateBuilder.getDescriptor:()Lgsa/furnace/common/UpdateListedTransactionDescriptor;
33: invokevirtual #371 // Method gsa/furnace/common/UpdateListedTransactionDescriptor.getSettlementFxRate:()Lgsa/furnace/common/msg/OptionalField;
36: invokevirtual #376 // Method gsa/furnace/common/msg/OptionalField.isSet:()Z
39: ifeq 102
42: aload 7
44: invokevirtual #365 // Method gsa/furnace/client/ListedTransactionUpdateBuilder.getDescriptor:()Lgsa/furnace/common/UpdateListedTransactionDescriptor;
47: invokevirtual #371 // Method gsa/furnace/common/UpdateListedTransactionDescriptor.getSettlementFxRate:()Lgsa/furnace/common/msg/OptionalField;
50: invokevirtual #380 // Method gsa/furnace/common/msg/OptionalField.getValue:()Ljava/lang/Object;
53: ifnonnull 102
56: aload 4
58: invokevirtual #357 // Method scala/math/BigDecimal.bigDecimal:()Ljava/math/BigDecimal;
61: ifnonnull 76
64: getstatic #297 // Field scala/Predef$.MODULE$:Lscala/Predef$;
67: ldc_w #382 // String NULL NOOOO!!!
70: invokevirtual #386 // Method scala/Predef$.println:(Ljava/lang/Object;)V
73: goto 76
76: aload_0
77: aload_0
78: getfield #390 // Field scala/runtime/IntRef.elem:I
81: iconst_1
82: iadd
83: putfield #390 // Field scala/runtime/IntRef.elem:I
86: getstatic #297 // Field scala/Predef$.MODULE$:Lscala/Predef$;
89: aload_0
90: getfield #390 // Field scala/runtime/IntRef.elem:I
93: invokestatic #396 // Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
96: invokevirtual #386 // Method scala/Predef$.println:(Ljava/lang/Object;)V
99: goto 102
102: goto 105
105: aload 5
107: ifnull 120
110: aload 7
112: aload 5
114: invokevirtual #400 // Method gsa/furnace/client/ListedTransactionUpdateBuilder.settlementDate:(Lgsa/shared/accounting/AccountingDate;)Lgsa/furnace/client/ListedTransactionUpdateBuilder;
117: goto 123
120: getstatic #406 // Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
123: pop
124: aload 6
126: ifnull 139
129: aload 7
131: aload 6
133: invokevirtual #409 // Method gsa/furnace/client/ListedTransactionUpdateBuilder.state:(Lgsa/furnace/core/EventState;)Lgsa/furnace/client/ListedTransactionUpdateBuilder;
136: goto 142
139: getstatic #406 // Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
142: pop
143: getstatic #412 // Field scala/Predef$ArrowAssoc$.MODULE$:Lscala/Predef$ArrowAssoc$;
146: getstatic #297 // Field scala/Predef$.MODULE$:Lscala/Predef$;
149: new #13 // class gsa/furnace/scala/package$OrigEvId
152: dup
153: getstatic #415 // Field gsa/furnace/scala/package$TxnId$.MODULE$:Lgsa/furnace/scala/package$TxnId$;
156: lload_1
157: invokevirtual #418 // Method gsa/furnace/scala/package$TxnId$.apply:(J)J
160: invokespecial #421 // Method gsa/furnace/scala/package$OrigEvId."<init>":(J)V
163: invokevirtual #424 // Method scala/Predef$.ArrowAssoc:(Ljava/lang/Object;)Ljava/lang/Object;
166: aload 7
168: invokevirtual #428 // Method scala/Predef$ArrowAssoc$.$minus$greater$extension:(Ljava/lang/Object;Ljava/lang/Object;)Lscala/Tuple2;
171: areturn
LocalVariableTable:
Start Length Slot Name Signature
5 166 7 ltub Lgsa/furnace/client/ListedTransactionUpdateBuilder;
0 172 0 a$1 Lscala/runtime/IntRef;
0 172 1 txnId$2 J
0 172 3 ccy$1 Lgsa/shared/units/Currency;
0 172 4 rate$1 Lscala/math/BigDecimal;
0 172 5 settDate$2 Lgsa/shared/accounting/AccountingDate;
0 172 6 state Lgsa/furnace/core/EventState;
LineNumberTable:
line 214: 0
line 215: 7
line 216: 16
line 217: 28
line 218: 56
line 219: 76
line 220: 86
line 217: 102
line 223: 105
line 224: 124
line 226: 146
StackMapTable: number_of_entries = 7
frame_type = 252 /* append */
offset_delta = 76
locals = [ class gsa/furnace/client/ListedTransactionUpdateBuilder ]
frame_type = 25 /* same */
frame_type = 2 /* same */
frame_type = 14 /* same */
frame_type = 66 /* same_locals_1_stack_item */
stack = [ class java/lang/Object ]
frame_type = 15 /* same */
frame_type = 66 /* same_locals_1_stack_item */
stack = [ class java/lang/Object ]
MethodParameters:
Name Flags
a$1 final
txnId$2 final
ccy$1 final
rate$1 final
settDate$2 final
state final |
@retronym said (edited on Nov 11, 2016 12:51:47 AM UTC): Should be fixed in JDK 1.8.0_112 and higher. |
@retronym said: |
I have some code like this:
Within this block we are seeing a
NullPointerException
thrown at runtime on the indicated line. This should obviously be impossible because that can only happen ifrate
isnull
and yet the code is inside an if-block protected against that condition. I have the following observations:-Djava.compiler=NONE
and @oxntr (on Twitter) said this description "screams JIT"ltub.settlement(ccy, rate.bigDecimal)
is supposed to set update descriptor fields for currency and rate; I have seen the currency field get set to the rate (the field is a generic class and hence the type it is holding is erased)I have tried to put together a minimal example but have been unable to do so (i.e. I cannot reproduce the problem), hence I'm supplying the disassembled bytecode (using javap), assuming that people who can read bytecode might be able to find some obvious issue in what has been generated (although this may be tricky, if the issue is connected to how JIT is compiling that bytecode).
I have supplied some minimal source code; this depends on our projects and scalaz - you will not be able to compile or run it. I hope, however, that you will be able to see how the problematic lines (13-19 in the attached file) relate to the generated bytecode (for example, I'm pretty sure that line 14 in the scala file relates to line 185 in the bytecode).
The text was updated successfully, but these errors were encountered: