@@ -101,11 +101,11 @@ private BugInstance toBugInstance(Detector detector, String type) {
101
101
private final BugReporter bugReporter ;
102
102
private final BugAccumulator bugAccumulator ;
103
103
104
- private final Set <XField > interestingFields = new HashSet <>();
104
+ private final Set <XField > fieldsForAtomicityCheck = new HashSet <>();
105
105
private final Set <XField > combinedAtomicFields = new HashSet <>();
106
106
107
- private final Map <Method , Map <XField , List <BugPrototype >>> interestingFieldCalls = new HashMap <>();
108
- private final Map <Method , List <BugPrototype >> interestingLocalVariableCalls = new HashMap <>();
107
+ private final Map <Method , Map <XField , List <BugPrototype >>> fieldAccessBugPrototypes = new HashMap <>();
108
+ private final Map <Method , List <BugPrototype >> localVariableInvocations = new HashMap <>();
109
109
110
110
private final Set <XMethod > unsynchronizedPrivateMethods = new HashSet <>();
111
111
@@ -118,13 +118,13 @@ public AtomicOperationsCombinedDetector(BugReporter bugReporter) {
118
118
public void visitClassContext (ClassContext classContext ) {
119
119
try {
120
120
for (Method method : classContext .getMethodsInCallOrder ()) {
121
- collectInterestingFields (classContext , method );
121
+ collectFieldsForAtomicityCheck (classContext , method );
122
122
}
123
123
for (Method method : classContext .getMethodsInCallOrder ()) {
124
- analyzeInterestingFields (classContext , method );
124
+ analyzeFieldsForAtomicityViolations (classContext , method );
125
125
}
126
126
removePresynchronizedPrivateMethodCalls ();
127
- accumulateInterestingFields ();
127
+ accumulateFieldsForAtomicityAnalysis ();
128
128
accumulateLocalVariables ();
129
129
} catch (CheckedAnalysisException e ) {
130
130
bugReporter .logError (String .format ("Detector %s caught exception while analyzing class %s" ,
@@ -134,7 +134,7 @@ public void visitClassContext(ClassContext classContext) {
134
134
}
135
135
}
136
136
137
- private void collectInterestingFields (ClassContext classContext , Method method ) throws CFGBuilderException {
137
+ private void collectFieldsForAtomicityCheck (ClassContext classContext , Method method ) throws CFGBuilderException {
138
138
CFG cfg = classContext .getCFG (method );
139
139
ConstantPoolGen cpg = classContext .getConstantPoolGen ();
140
140
@@ -145,22 +145,22 @@ private void collectInterestingFields(ClassContext classContext, Method method)
145
145
if (instruction instanceof PUTFIELD ) {
146
146
OpcodeStack stack = OpcodeStackScanner .getStackAt (classContext .getJavaClass (), method , handle .getPosition ());
147
147
OpcodeStack .Item stackItem = stack .getStackItem (0 );
148
- if (isInterestingField (stackItem .getReturnValueOf ())) {
149
- interestingFields .add (XFactory .createXField ((FieldInstruction ) instruction , cpg ));
148
+ if (isAtomicField (stackItem .getReturnValueOf ())) {
149
+ fieldsForAtomicityCheck .add (XFactory .createXField ((FieldInstruction ) instruction , cpg ));
150
150
}
151
151
}
152
152
}
153
153
}
154
154
155
- private static boolean isInterestingField (ClassMember classMember ) {
155
+ private static boolean isAtomicField (ClassMember classMember ) {
156
156
if (classMember == null ) {
157
157
return false ;
158
158
}
159
159
return CollectionAnalysis .isSynchronizedCollection (classMember )
160
160
|| (classMember .getClassName ().startsWith ("java.util.concurrent.atomic" ) && classMember .getSignature ().endsWith (")V" ));
161
161
}
162
162
163
- private void analyzeInterestingFields (ClassContext classContext , Method method ) throws CheckedAnalysisException {
163
+ private void analyzeFieldsForAtomicityViolations (ClassContext classContext , Method method ) throws CheckedAnalysisException {
164
164
if (Const .CONSTRUCTOR_NAME .equals (method .getName ()) || Const .STATIC_INITIALIZER_NAME .equals (method .getName ()) || method .isSynchronized ()) {
165
165
return ;
166
166
}
@@ -184,57 +184,57 @@ private void analyzeInterestingFields(ClassContext classContext, Method method)
184
184
synchronizedBlock = false ;
185
185
} else if (instruction instanceof PUTFIELD && !synchronizedBlock && !MethodAnalysis .isDuplicatedLocation (methodDescriptor , pc )) {
186
186
XField xField = XFactory .createXField ((FieldInstruction ) instruction , cpg );
187
- if (interestingFields .contains (xField )) {
187
+ if (fieldsForAtomicityCheck .contains (xField )) {
188
188
bugPrototype .invokedField = xField ;
189
- interestingFieldCalls .computeIfAbsent (method , value -> new HashMap <>())
189
+ fieldAccessBugPrototypes .computeIfAbsent (method , value -> new HashMap <>())
190
190
.computeIfAbsent (xField , value -> new LinkedList <>())
191
191
.add (bugPrototype );
192
192
}
193
193
} else if (instruction instanceof InvokeInstruction && !(instruction instanceof INVOKEDYNAMIC )
194
194
&& !synchronizedBlock && !MethodAnalysis .isDuplicatedLocation (methodDescriptor , pc )) {
195
195
OpcodeStack stack = OpcodeStackScanner .getStackAt (javaClass , method , pc );
196
- Optional <XField > interestingField = getInterestingField (stack );
196
+ Optional <XField > fieldRequiringAtomicityCheck = findFieldRequiringAtomicityCheck (stack );
197
197
XMethod xMethod = XFactory .createXMethod ((InvokeInstruction ) instruction , cpg );
198
- if (interestingField .isPresent ()) {
199
- bugPrototype .invokedField = interestingField .get ();
198
+ if (fieldRequiringAtomicityCheck .isPresent ()) {
199
+ bugPrototype .invokedField = fieldRequiringAtomicityCheck .get ();
200
200
bugPrototype .invokedMethod = xMethod ;
201
- interestingFieldCalls .computeIfAbsent (method , value -> new HashMap <>())
202
- .computeIfAbsent (interestingField .get (), value -> new LinkedList <>())
201
+ fieldAccessBugPrototypes .computeIfAbsent (method , value -> new HashMap <>())
202
+ .computeIfAbsent (fieldRequiringAtomicityCheck .get (), value -> new LinkedList <>())
203
203
.add (bugPrototype );
204
204
205
205
if (javaClass .getClassName ().equals (xMethod .getClassName ())) {
206
206
unsynchronizedPrivateMethods .add (xMethod );
207
207
}
208
208
} else if (stack .getStackDepth () > 0 ) {
209
209
OpcodeStack .Item stackItem = stack .getStackItem (0 );
210
- if (isInterestingLocalVariable (stackItem )) {
210
+ if (isLocalVariableRequiringAtomicityCheck (stackItem )) {
211
211
LocalVariableAnnotation annotation = LocalVariableAnnotation .getLocalVariableAnnotation (method , stackItem , pc );
212
212
if (annotation != null ) {
213
213
bugPrototype .localVariableAnnotation = annotation ;
214
214
bugPrototype .invokedMethod = xMethod ;
215
- interestingLocalVariableCalls .computeIfAbsent (method , value -> new LinkedList <>())
215
+ localVariableInvocations .computeIfAbsent (method , value -> new LinkedList <>())
216
216
.add (bugPrototype );
217
217
}
218
218
} else if (isAtomicOperationsCombined (stack )) {
219
- combinedAtomicFields .addAll (getInterestingFieldsInCall (location , callListDataflow ));
219
+ combinedAtomicFields .addAll (findFieldsInvolvedInAtomicOperations (location , callListDataflow ));
220
220
}
221
221
}
222
222
}
223
223
}
224
224
}
225
225
226
- private Optional <XField > getInterestingField (OpcodeStack stack ) {
226
+ private Optional <XField > findFieldRequiringAtomicityCheck (OpcodeStack stack ) {
227
227
if (stack .getStackDepth () > 1 && stack .getStackItem (0 ).getReturnValueOf () != null ) {
228
228
return Optional .empty ();
229
229
}
230
230
return IntStream .range (0 , stack .getStackDepth ())
231
231
.mapToObj (stack ::getStackItem )
232
232
.map (OpcodeStack .Item ::getXField )
233
- .filter (interestingFields ::contains )
233
+ .filter (fieldsForAtomicityCheck ::contains )
234
234
.findFirst ();
235
235
}
236
236
237
- private static boolean isInterestingLocalVariable (OpcodeStack .Item stackItem ) {
237
+ private static boolean isLocalVariableRequiringAtomicityCheck (OpcodeStack .Item stackItem ) {
238
238
return isAtomicSignature (stackItem .getSignature ())
239
239
&& (stackItem .getReturnValueOf () == null || !stackItem .getReturnValueOf ().getName ().contains (Const .CONSTRUCTOR_NAME ));
240
240
}
@@ -253,21 +253,21 @@ private static boolean isAtomicReference(OpcodeStack.Item stackItem) {
253
253
return stackItem .getReturnValueOf () != null && stackItem .getReturnValueOf ().getClassName ().startsWith ("java.util.concurrent.atomic" );
254
254
}
255
255
256
- private Set <XField > getInterestingFieldsInCall (Location location , CallListDataflow callListDataflow ) throws DataflowAnalysisException {
257
- Set <XField > interestingFieldsInCallList = new HashSet <>();
256
+ private Set <XField > findFieldsInvolvedInAtomicOperations (Location location , CallListDataflow callListDataflow ) throws DataflowAnalysisException {
257
+ Set <XField > involvedFields = new HashSet <>();
258
258
CallList factAtLocation = callListDataflow .getFactAtLocation (location );
259
259
Iterator <Call > callIterator = factAtLocation .callIterator ();
260
260
while (callIterator .hasNext ()) {
261
261
Call call = callIterator .next ();
262
262
call .getAttributes ().stream ()
263
- .filter (interestingFields ::contains )
264
- .forEach (interestingFieldsInCallList ::add );
263
+ .filter (fieldsForAtomicityCheck ::contains )
264
+ .forEach (involvedFields ::add );
265
265
}
266
- return interestingFieldsInCallList ;
266
+ return involvedFields ;
267
267
}
268
268
269
269
private void removePresynchronizedPrivateMethodCalls () {
270
- interestingLocalVariableCalls .entrySet ().removeIf (entry -> entry .getKey ().isPrivate ()
270
+ localVariableInvocations .entrySet ().removeIf (entry -> entry .getKey ().isPrivate ()
271
271
&& unsynchronizedPrivateMethods .stream ().noneMatch (privMethod -> equalMethods (entry .getKey (), privMethod )));
272
272
}
273
273
@@ -280,44 +280,44 @@ public void report() {
280
280
bugAccumulator .reportAccumulatedBugs ();
281
281
}
282
282
283
- private void accumulateInterestingFields () {
284
- Set <XField > interestingFieldsWithMultipleCalls = interestingFieldCalls .values ().stream ()
283
+ private void accumulateFieldsForAtomicityAnalysis () {
284
+ Set <XField > fieldsToProcess = fieldAccessBugPrototypes .values ().stream ()
285
285
.flatMap (map -> map .entrySet ().stream ())
286
286
.filter (entry -> entry .getValue ().size () > 1 )
287
287
.map (Map .Entry ::getKey )
288
288
.collect (Collectors .toSet ());
289
289
290
- interestingFieldCalls .entrySet ().stream ()
290
+ fieldAccessBugPrototypes .entrySet ().stream ()
291
291
.flatMap (entry -> entry .getValue ().entrySet ().stream ())
292
- .forEach (entry -> processFieldData (entry .getKey (), entry .getValue (), interestingFieldsWithMultipleCalls ));
292
+ .forEach (entry -> processFieldData (entry .getKey (), entry .getValue (), fieldsToProcess ));
293
293
}
294
294
295
295
private void accumulateLocalVariables () {
296
- interestingLocalVariableCalls .values ().forEach (this ::processFieldData );
296
+ localVariableInvocations .values ().forEach (this ::processFieldData );
297
297
}
298
298
299
- private void processFieldData (List <BugPrototype > interestingFieldCallData ) {
300
- processFieldData (null , interestingFieldCallData , new HashSet <>());
299
+ private void processFieldData (List <BugPrototype > fieldCallData ) {
300
+ processFieldData (null , fieldCallData , new HashSet <>());
301
301
}
302
302
303
- private void processFieldData (XField field , List <BugPrototype > interestingFieldCallData , Set <XField > interestingFieldsWithMultipleCalls ) {
304
- if (!interestingFieldCallData .isEmpty ()) {
305
- BugPrototype bugPrototype = interestingFieldCallData .get (interestingFieldCallData .size () - 1 );
306
- if (interestingFieldCallData .size () > 1 || combinedAtomicFields .contains (field )) {
303
+ private void processFieldData (XField field , List <BugPrototype > fieldCallData , Set <XField > fieldsWithMultipleCalls ) {
304
+ if (!fieldCallData .isEmpty ()) {
305
+ BugPrototype bugPrototype = fieldCallData .get (fieldCallData .size () - 1 );
306
+ if (fieldCallData .size () > 1 || combinedAtomicFields .contains (field )) {
307
307
BugInstance bugInstance = bugPrototype .toBugInstance (this , "AT_COMBINED_ATOMIC_OPERATIONS_ARE_NOT_ATOMIC" );
308
308
bugAccumulator .accumulateBug (bugInstance , bugInstance .getPrimarySourceLineAnnotation ());
309
- } else if (interestingFieldsWithMultipleCalls .contains (field )) {
309
+ } else if (fieldsWithMultipleCalls .contains (field )) {
310
310
BugInstance bugInstance = bugPrototype .toBugInstance (this , "AT_ATOMIC_OPERATION_NEEDS_SYNCHRONIZATION" );
311
311
bugAccumulator .accumulateBug (bugInstance , bugInstance .getPrimarySourceLineAnnotation ());
312
312
}
313
313
}
314
314
}
315
315
316
316
private void clearProperties () {
317
- interestingFields .clear ();
317
+ fieldsForAtomicityCheck .clear ();
318
318
combinedAtomicFields .clear ();
319
- interestingFieldCalls .clear ();
320
- interestingLocalVariableCalls .clear ();
319
+ fieldAccessBugPrototypes .clear ();
320
+ localVariableInvocations .clear ();
321
321
unsynchronizedPrivateMethods .clear ();
322
322
}
323
323
}
0 commit comments