You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Paul King (JIRA)" <ji...@apache.org> on 2015/05/08 06:01:59 UTC
[jira] [Created] (GROOVY-7417) @EqualsAndHashCode inconsistent when
using boolean properties for classes with explicit getters
Paul King created GROOVY-7417:
---------------------------------
Summary: @EqualsAndHashCode inconsistent when using boolean properties for classes with explicit getters
Key: GROOVY-7417
URL: https://issues.apache.org/jira/browse/GROOVY-7417
Project: Groovy
Issue Type: Bug
Affects Versions: 2.4.3
Reporter: Christopher Smith
Priority: Critical
I have the following class representing a location in Amazon S3. Depending on some inner business logic, I often need to split the object key into a prefix and a file name, so I access them all through the {{getKey()}} method; with S3, the only thing that matters is the final concatenated string.
The generated {{equals}} method incorrectly returns true for any two objects with the same bucket, ignoring the key property. (I discovered this when I got some interesting results out of a JSR-330 cache.) I have marked this issue critical because it is likely to cause immediate security vulnerabilities and data loss when unequal objects are found equal.
{code}
@CompileStatic
@EqualsAndHashCode(includes = ['bucket', 'key'])
final class S3ImageLocation implements ImageLocation {
@NotNull
final String bucket
final String prefix
@NotNull
final String subKey
@PersistenceConstructor
S3ImageLocation(String bucket, String prefix, String subKey) {
this.bucket = bucket
this.prefix = prefix
this.subKey = subKey
}
S3ImageLocation(String bucket, String subKey) {
this(bucket, null, subKey)
}
@JsonIgnore
String getKey() {
prefix ? "$prefix/$subKey" : subKey
}
@Override
String toString() {
"s3://$bucket/$key"
}
S3Location toBlitlineLocation() {
new S3Location(bucket, key)
}
}
{code}
Both of the generated methods appear to be including {{bucket}} twice instead of including {{bucket}} and {{key}}.
see :7 and :29
{code}
public int hashCode();
Code:
0: invokestatic #93 // Method org/codehaus/groovy/util/HashCodeHelper.initHash:()I
3: istore_1
4: iload_1
5: pop
6: aload_0
7: ldc #94 // String bucket
9: invokestatic #100 // Method org/codehaus/groovy/runtime/InvokerHelper.getProperty:(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;
12: aload_0
13: invokestatic #106 // Method org/codehaus/groovy/runtime/DefaultGroovyMethods.is:(Ljava/lang/Object;Ljava/lang/Object;)Z
16: ifne 23
19: iconst_1
20: goto 24
23: iconst_0
24: ifeq 42
27: iload_1
28: aload_0
29: ldc #94 // String bucket
31: invokestatic #100 // Method org/codehaus/groovy/runtime/InvokerHelper.getProperty:(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;
34: invokestatic #110 // Method org/codehaus/groovy/util/HashCodeHelper.updateHash:(ILjava/lang/Object;)I
37: istore_2
38: iload_2
39: istore_1
40: iload_2
41: pop
42: iload_1
43: ireturn
44: ldc #113 // int 0
46: ireturn
{code}
see :152/:171 and :208/:219
{code}
public boolean equals(java.lang.Object);
Code:
0: aload_1
1: ifnonnull 8
4: iconst_1
5: goto 9
8: iconst_0
9: ifeq 19
12: getstatic #129 // Field java/lang/Boolean.FALSE:Ljava/lang/Boolean;
15: invokestatic #58 // Method org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformation.booleanUnbox:(Ljava/lang/Object;)Z
18: ireturn
19: aload_0
20: aload_1
21: invokestatic #106 // Method org/codehaus/groovy/runtime/DefaultGroovyMethods.is:(Ljava/lang/Object;Ljava/lang/Object;)Z
24: ifeq 34
27: getstatic #132 // Field java/lang/Boolean.TRUE:Ljava/lang/Boolean;
30: invokestatic #58 // Method org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformation.booleanUnbox:(Ljava/lang/Object;)Z
33: ireturn
34: aload_1
35: instanceof #2 // class com/artsquare/studio/img/s3/S3ImageLocation
38: ifne 45
41: iconst_1
42: goto 46
45: iconst_0
46: ifeq 56
49: getstatic #129 // Field java/lang/Boolean.FALSE:Ljava/lang/Boolean;
52: invokestatic #58 // Method org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformation.booleanUnbox:(Ljava/lang/Object;)Z
55: ireturn
56: aload_1
57: ldc #2 // class com/artsquare/studio/img/s3/S3ImageLocation
59: invokestatic #138 // Method org/codehaus/groovy/runtime/ScriptBytecodeAdapter.castToType:(Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;
62: checkcast #2 // class com/artsquare/studio/img/s3/S3ImageLocation
65: astore_2
66: aload_2
67: pop
68: aload_2
69: aload_0
70: invokevirtual #140 // Method canEqual:(Ljava/lang/Object;)Z
73: ifne 80
76: iconst_1
77: goto 81
80: iconst_0
81: ifeq 91
84: getstatic #129 // Field java/lang/Boolean.FALSE:Ljava/lang/Boolean;
87: invokestatic #58 // Method org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformation.booleanUnbox:(Ljava/lang/Object;)Z
90: ireturn
91: aload_0
92: invokevirtual #143 // Method getBucket:()Ljava/lang/String;
95: aload_2
96: invokevirtual #143 // Method getBucket:()Ljava/lang/String;
99: invokestatic #106 // Method org/codehaus/groovy/runtime/DefaultGroovyMethods.is:(Ljava/lang/Object;Ljava/lang/Object;)Z
102: ifne 109
105: iconst_1
106: goto 110
109: iconst_0
110: ifeq 274
113: aload_0
114: invokevirtual #143 // Method getBucket:()Ljava/lang/String;
117: aload_0
118: invokestatic #106 // Method org/codehaus/groovy/runtime/DefaultGroovyMethods.is:(Ljava/lang/Object;Ljava/lang/Object;)Z
121: ifeq 147
124: aload_2
125: invokevirtual #143 // Method getBucket:()Ljava/lang/String;
128: aload_2
129: invokestatic #106 // Method org/codehaus/groovy/runtime/DefaultGroovyMethods.is:(Ljava/lang/Object;Ljava/lang/Object;)Z
132: ifne 139
135: iconst_1
136: goto 140
139: iconst_0
140: ifeq 147
143: iconst_1
144: goto 148
147: iconst_0
148: ifne 189
151: aload_0
152: invokevirtual #143 // Method getBucket:()Ljava/lang/String;
155: aload_0
156: invokestatic #106 // Method org/codehaus/groovy/runtime/DefaultGroovyMethods.is:(Ljava/lang/Object;Ljava/lang/Object;)Z
159: ifne 166
162: iconst_1
163: goto 167
166: iconst_0
167: ifeq 185
170: aload_2
171: invokevirtual #143 // Method getBucket:()Ljava/lang/String;
174: aload_2
175: invokestatic #106 // Method org/codehaus/groovy/runtime/DefaultGroovyMethods.is:(Ljava/lang/Object;Ljava/lang/Object;)Z
178: ifeq 185
181: iconst_1
182: goto 186
185: iconst_0
186: ifeq 193
189: iconst_1
190: goto 194
193: iconst_0
194: ifeq 207
197: getstatic #129 // Field java/lang/Boolean.FALSE:Ljava/lang/Boolean;
200: invokestatic #58 // Method org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformation.booleanUnbox:(Ljava/lang/Object;)Z
203: ireturn
204: goto 274
207: aload_0
208: invokevirtual #143 // Method getBucket:()Ljava/lang/String;
211: aload_0
212: invokestatic #106 // Method org/codehaus/groovy/runtime/DefaultGroovyMethods.is:(Ljava/lang/Object;Ljava/lang/Object;)Z
215: ifeq 233
218: aload_2
219: invokevirtual #143 // Method getBucket:()Ljava/lang/String;
222: aload_2
223: invokestatic #106 // Method org/codehaus/groovy/runtime/DefaultGroovyMethods.is:(Ljava/lang/Object;Ljava/lang/Object;)Z
226: ifeq 233
229: iconst_1
230: goto 234
233: iconst_0
234: ifne 241
237: iconst_1
238: goto 242
241: iconst_0
242: ifeq 274
245: aload_0
246: invokevirtual #143 // Method getBucket:()Ljava/lang/String;
249: aload_2
250: invokevirtual #143 // Method getBucket:()Ljava/lang/String;
253: invokestatic #146 // Method org/codehaus/groovy/runtime/ScriptBytecodeAdapter.compareEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
256: ifne 263
259: iconst_1
260: goto 264
263: iconst_0
264: ifeq 274
267: getstatic #129 // Field java/lang/Boolean.FALSE:Ljava/lang/Boolean;
270: invokestatic #58 // Method org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformation.booleanUnbox:(Ljava/lang/Object;)Z
273: ireturn
274: getstatic #132 // Field java/lang/Boolean.TRUE:Ljava/lang/Boolean;
277: invokestatic #58 // Method org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformation.booleanUnbox:(Ljava/lang/Object;)Z
280: ireturn
281: ldc #113 // int 0
283: invokestatic #122 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
286: invokestatic #58 // Method org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformation.booleanUnbox:(Ljava/lang/Object;)Z
289: ireturn
{code}
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)