26
26
package de.fraunhofer.aisec.cpg.analysis
27
27
28
28
import de.fraunhofer.aisec.cpg.graph.AccessValues
29
+ import de.fraunhofer.aisec.cpg.graph.HasInitializer
29
30
import de.fraunhofer.aisec.cpg.graph.HasOperatorCode
30
31
import de.fraunhofer.aisec.cpg.graph.Node
31
32
import de.fraunhofer.aisec.cpg.graph.declarations.VariableDeclaration
@@ -74,7 +75,7 @@ open class ValueEvaluator(
74
75
open fun evaluate (node : Any? ): Any? {
75
76
if (node !is Node ) return node
76
77
77
- return evaluateInternal(node as ? Node , 0 )
78
+ return evaluateInternal(node, 0 )
78
79
}
79
80
80
81
fun clearPath () {
@@ -87,11 +88,11 @@ open class ValueEvaluator(
87
88
node?.let { this .path + = it }
88
89
89
90
when (node) {
90
- is NewArrayExpression -> return evaluateInternal (node.initializer , depth)
91
- is VariableDeclaration -> return handleVariableDeclaration (node, depth)
91
+ is NewArrayExpression -> return handleHasInitializer (node, depth)
92
+ is VariableDeclaration -> return handleHasInitializer (node, depth)
92
93
// For a literal, we can just take its value, and we are finished
93
94
is Literal <* > -> return node.value
94
- is Reference -> return handleReference (node, depth)
95
+ is Reference -> return handlePrevDFG (node, depth)
95
96
is UnaryOperator -> return handleUnaryOp(node, depth)
96
97
is BinaryOperator -> return handleBinaryOperator(node, depth)
97
98
// Casts are just a wrapper in this case, we are interested in the inner expression
@@ -108,10 +109,17 @@ open class ValueEvaluator(
108
109
return cannotEvaluate(node, this )
109
110
}
110
111
111
- protected fun handleVariableDeclaration (node : VariableDeclaration , depth : Int ): Any? {
112
- // If we have an initializer, we can use it. However, we actually should just use the DFG
113
- // instead and do something similar to handleReference
114
- return evaluateInternal(node.initializer, depth + 1 )
112
+ /* *
113
+ * If a node declaration implements [HasInitializer], we can use the initializer to evaluate
114
+ * their value. If not, we can try to use [handlePrevDFG].
115
+ */
116
+ protected fun handleHasInitializer (node : HasInitializer , depth : Int ): Any? {
117
+ // If we have an initializer, we can use it. Otherwise, we can fall back to the prevDFG
118
+ return if (node.initializer != null ) {
119
+ evaluateInternal(node.initializer, depth + 1 )
120
+ } else {
121
+ handlePrevDFG(node as Node , depth)
122
+ }
115
123
}
116
124
117
125
/* * Under certain circumstances, an assignment can also be used as an expression. */
@@ -259,51 +267,63 @@ open class ValueEvaluator(
259
267
}
260
268
}
261
269
262
- private fun handleGreater (lhsValue : Any? , rhsValue : Any? , expr : Expression ? ): Any? {
270
+ protected open fun handleGreater (lhsValue : Any? , rhsValue : Any? , expr : Expression ? ): Any? {
263
271
return if (lhsValue is Number && rhsValue is Number ) {
264
272
lhsValue.compareTo(rhsValue) > 0
265
273
} else {
266
274
cannotEvaluate(expr, this )
267
275
}
268
276
}
269
277
270
- private fun handleGEq (lhsValue : Any? , rhsValue : Any? , expr : Expression ? ): Any? {
278
+ protected open fun handleGEq (lhsValue : Any? , rhsValue : Any? , expr : Expression ? ): Any? {
271
279
return if (lhsValue is Number && rhsValue is Number ) {
272
280
lhsValue.compareTo(rhsValue) >= 0
273
281
} else {
274
282
cannotEvaluate(expr, this )
275
283
}
276
284
}
277
285
278
- private fun handleLess (lhsValue : Any? , rhsValue : Any? , expr : Expression ? ): Any? {
286
+ protected open fun handleLess (lhsValue : Any? , rhsValue : Any? , expr : Expression ? ): Any? {
279
287
return if (lhsValue is Number && rhsValue is Number ) {
280
288
lhsValue.compareTo(rhsValue) < 0
281
289
} else {
282
290
cannotEvaluate(expr, this )
283
291
}
284
292
}
285
293
286
- private fun handleLEq (lhsValue : Any? , rhsValue : Any? , expr : Expression ? ): Any? {
294
+ protected open fun handleLEq (lhsValue : Any? , rhsValue : Any? , expr : Expression ? ): Any? {
287
295
return if (lhsValue is Number && rhsValue is Number ) {
288
296
lhsValue.compareTo(rhsValue) <= 0
289
297
} else {
290
298
cannotEvaluate(expr, this )
291
299
}
292
300
}
293
301
294
- private fun handleEq (lhsValue : Any? , rhsValue : Any? , expr : Expression ? ): Any? {
295
- return if (lhsValue is Number && rhsValue is Number ) {
296
- lhsValue.compareTo(rhsValue) == 0
297
- } else {
298
- cannotEvaluate(expr, this )
302
+ protected open fun handleEq (lhsValue : Any? , rhsValue : Any? , expr : Expression ? ): Any? {
303
+ return when {
304
+ lhsValue is Number && rhsValue is Number -> {
305
+ lhsValue.compareTo(rhsValue) == 0
306
+ }
307
+ lhsValue is String && rhsValue is String -> {
308
+ lhsValue == rhsValue
309
+ }
310
+ else -> {
311
+ cannotEvaluate(expr, this )
312
+ }
299
313
}
300
314
}
301
315
302
- private fun handleNEq (lhsValue : Any? , rhsValue : Any? , expr : Expression ? ): Any? {
303
- return if (lhsValue is Number && rhsValue is Number ) {
304
- lhsValue.compareTo(rhsValue) != 0
305
- } else {
306
- cannotEvaluate(expr, this )
316
+ protected open fun handleNEq (lhsValue : Any? , rhsValue : Any? , expr : Expression ? ): Any? {
317
+ return when {
318
+ lhsValue is Number && rhsValue is Number -> {
319
+ lhsValue.compareTo(rhsValue) != 0
320
+ }
321
+ lhsValue is String && rhsValue is String -> {
322
+ lhsValue != rhsValue
323
+ }
324
+ else -> {
325
+ cannotEvaluate(expr, this )
326
+ }
307
327
}
308
328
}
309
329
@@ -390,15 +410,17 @@ open class ValueEvaluator(
390
410
return cannotEvaluate(expr, this )
391
411
}
392
412
393
- /* *
394
- * Tries to compute the constant value of a reference. It therefore checks the incoming data
395
- * flow edges.
396
- */
397
- protected open fun handleReference (expr : Reference , depth : Int ): Any? {
413
+ /* * Tries to compute the constant value of a node based on its [Node.prevDFG]. */
414
+ protected open fun handlePrevDFG (node : Node , depth : Int ): Any? {
398
415
// For a reference, we are interested into its last assignment into the reference
399
416
// denoted by the previous DFG edge. We need to filter out any self-references for READWRITE
400
417
// references.
401
- val prevDFG = filterSelfReferences(expr, expr.prevDFG.toList())
418
+ val prevDFG =
419
+ if (node is Reference ) {
420
+ filterSelfReferences(node, node.prevDFG.toList())
421
+ } else {
422
+ node.prevDFG
423
+ }
402
424
403
425
return if (prevDFG.size == 1 ) {
404
426
// There's only one incoming DFG edge, so we follow this one.
@@ -407,13 +429,13 @@ open class ValueEvaluator(
407
429
// We cannot have more than ONE valid solution, so we need to abort
408
430
log.warn(
409
431
" We cannot evaluate {}: It has more than 1 previous DFG edges, meaning that the value is probably affected by a branch." ,
410
- expr ,
432
+ node ,
411
433
)
412
- cannotEvaluate(expr , this )
434
+ cannotEvaluate(node , this )
413
435
} else {
414
436
// No previous DFG node
415
- log.warn(" We cannot evaluate {}: It has no previous DFG edges." , expr )
416
- cannotEvaluate(expr , this )
437
+ log.warn(" We cannot evaluate {}: It has no previous DFG edges." , node )
438
+ cannotEvaluate(node , this )
417
439
}
418
440
}
419
441
0 commit comments