@@ -224,7 +224,7 @@ signature predicate interestedInEquality(Type a, Type b);
224
224
* Note that `equalTypes(a, b)` only holds if `interestedIn(a, b)` holds. A type is always
225
225
* considered to be equal to itself, and this module does not support configurations that declare
226
226
* otherwise.
227
- *
227
+ *
228
228
* Further, `interestedInEquality(a, a)` is treated differently from `interestedInEquality(a, b)`,
229
229
* assuming that `a` and `b` are not identical. This is so that we can construct a set of types
230
230
* that are not identical, but still may be equivalent by the specified configuration. We also must
@@ -233,45 +233,75 @@ signature predicate interestedInEquality(Type a, Type b);
233
233
* only a few are not.
234
234
*/
235
235
module TypeEquivalence< TypeEquivalenceSig Config, interestedInEquality / 2 interestedIn> {
236
+
236
237
/**
237
- * Check whether two types are equivalent, as defined by the `TypeEquivalenceSig` module.
238
- *
239
- * This only holds if the specified predicate `interestedIn` holds for the types, and always
240
- * holds if `t1` and `t2` are identical.
238
+ * Performance related predicate to force top down rather than bottom up evaluation of type
239
+ * equivalence.
241
240
*/
242
- predicate equalTypes ( Type t1 , Type t2 ) {
243
- interestedInUnordered ( t1 , t2 ) and
244
- (
245
- // If the types are identical, they are trivially equal.
246
- t1 = t2
241
+ predicate compares ( Type t1 , Type t2 ) {
242
+ interestedIn ( t1 , t2 )
243
+ or
244
+ exists ( DerivedType t1Derived , DerivedType t2Derived |
245
+ not t1Derived instanceof SpecifiedType and
246
+ not t2Derived instanceof SpecifiedType and
247
+ compares ( pragma [ only_bind_into ] ( t1Derived ) , pragma [ only_bind_into ] ( t2Derived ) ) and
248
+ t1 = t1Derived .getBaseType ( ) and
249
+ t2 = t2Derived .getBaseType ( )
250
+ )
251
+ or
252
+ exists ( SpecifiedType t1Spec , SpecifiedType t2Spec |
253
+ compares ( pragma [ only_bind_into ] ( t1Spec ) , pragma [ only_bind_into ] ( t2Spec ) ) and
254
+ (
255
+ t1 = unspecify ( t1Spec ) and
256
+ t2 = unspecify ( t2Spec )
257
+ )
258
+ )
259
+ or
260
+ exists ( FunctionType t1Func , FunctionType t2Func |
261
+ compares ( pragma [ only_bind_into ] ( t1Func ) , pragma [ only_bind_into ] ( t2Func ) ) and
262
+ (
263
+ t1 = t1Func .getReturnType ( ) and
264
+ t2 = t2Func .getReturnType ( )
265
+ or
266
+ exists ( int i |
267
+ t1 = t1Func .getParameterType ( pragma [ only_bind_out ] ( i ) ) and
268
+ t2 = t2Func .getParameterType ( i )
269
+ )
270
+ )
271
+ )
272
+ or
273
+ Config:: resolveTypedefs ( ) and
274
+ exists ( TypedefType tdtype |
275
+ tdtype .getBaseType ( ) = t1 and
276
+ compares ( pragma [ only_bind_into ] ( tdtype ) , t2 )
247
277
or
248
- not t1 = t2 and
249
- equalTypesImpl ( t1 , t2 )
278
+ tdtype . getBaseType ( ) = t2 and
279
+ compares ( t1 , pragma [ only_bind_into ] ( tdtype ) )
250
280
)
251
281
}
252
282
253
283
/**
254
- * This implementation handles only the slow and complex cases of type equivalence, where the
255
- * types are not identical.
284
+ * Check whether two types are equivalent, as defined by the `TypeEquivalenceSig` module.
256
285
*
257
- * Assuming that types a, b must be compared where `a` and `b` are not identical, we wish to
258
- * search only the smallest set of possible relevant types. See `RelevantType` for more .
286
+ * This only holds if the specified predicate `interestedIn` holds for the types, and always
287
+ * holds if `t1` and `t2` are identical .
259
288
*/
260
- private predicate equalTypesImpl ( RelevantType t1 , RelevantType t2 ) {
289
+ private predicate equalTypes ( Type t1 , Type t2 ) {
290
+ compares ( pragma [ only_bind_into ] ( t1 ) , pragma [ only_bind_into ] ( t2 ) ) and
261
291
if Config:: overrideTypeComparison ( t1 , t2 , _)
262
292
then Config:: overrideTypeComparison ( t1 , t2 , true )
263
293
else
264
294
if t1 instanceof TypedefType and Config:: resolveTypedefs ( )
265
- then equalTypesImpl ( t1 .( TypedefType ) .getBaseType ( ) , t2 )
295
+ then equalTypes ( t1 .( TypedefType ) .getBaseType ( ) , t2 )
266
296
else
267
297
if t2 instanceof TypedefType and Config:: resolveTypedefs ( )
268
- then equalTypesImpl ( t1 , t2 .( TypedefType ) .getBaseType ( ) )
298
+ then equalTypes ( t1 , t2 .( TypedefType ) .getBaseType ( ) )
269
299
else (
270
300
not t1 instanceof DerivedType and
271
301
not t2 instanceof DerivedType and
272
302
not t1 instanceof TypedefType and
273
303
not t2 instanceof TypedefType and
274
- LeafEquiv :: getEquivalenceClass ( t1 ) = LeafEquiv :: getEquivalenceClass ( t2 )
304
+ equalLeafRelation ( t1 , t2 )
275
305
or
276
306
equalDerivedTypes ( t1 , t2 )
277
307
or
@@ -284,56 +314,14 @@ module TypeEquivalence<TypeEquivalenceSig Config, interestedInEquality/2 interes
284
314
/** Whether two types will be compared, regardless of order (a, b) or (b, a). */
285
315
private predicate interestedInUnordered ( Type t1 , Type t2 ) {
286
316
interestedIn ( t1 , t2 ) or
287
- interestedIn ( t2 , t1 ) }
288
-
289
- final private class FinalType = Type ;
290
-
291
- /**
292
- * A type that is compared to another type that is not identical. This is the set of types that
293
- * form the roots of our more expensive type equivalence analysis.
294
- */
295
- private class InterestingType extends FinalType {
296
- InterestingType ( ) {
297
- exists ( Type inexactCompare |
298
- interestedInUnordered ( this , _) and
299
- not inexactCompare = this
300
- )
301
- }
302
- }
303
-
304
- /**
305
- * A type that is reachable from an `InterestingType` (a type that is compared to a non-identical
306
- * type).
307
- *
308
- * Since type equivalence is recursive, CodeQL will consider the equality of these types in a
309
- * bottom-up evaluation, with leaf nodes first. Therefore, this set must be as small as possible
310
- * in order to be efficient.
311
- */
312
- private class RelevantType extends FinalType {
313
- RelevantType ( ) { exists ( InterestingType t | typeGraph * ( t , this ) ) }
317
+ interestedIn ( t2 , t1 )
314
318
}
315
319
316
- private class RelevantDerivedType extends RelevantType instanceof DerivedType {
317
- RelevantType getBaseType ( ) { result = this .( DerivedType ) .getBaseType ( ) }
318
- }
319
-
320
- private class RelevantFunctionType extends RelevantType instanceof FunctionType {
321
- RelevantType getReturnType ( ) { result = this .( FunctionType ) .getReturnType ( ) }
322
-
323
- RelevantType getParameterType ( int i ) { result = this .( FunctionType ) .getParameterType ( i ) }
324
- }
325
-
326
- private class RelevantTypedefType extends RelevantType instanceof TypedefType {
327
- RelevantType getBaseType ( ) { result = this .( TypedefType ) .getBaseType ( ) }
328
- }
329
-
330
- private module LeafEquiv = QlBuiltins:: EquivalenceRelation< RelevantType , equalLeafRelation / 2 > ;
331
-
332
- private predicate equalLeafRelation ( RelevantType t1 , RelevantType t2 ) {
333
- Config:: equalLeafTypes ( t1 , t2 )
334
- }
320
+ bindingset [ t1, t2]
321
+ private predicate equalLeafRelation ( Type t1 , Type t2 ) { Config:: equalLeafTypes ( t1 , t2 ) }
335
322
336
- private RelevantType unspecify ( SpecifiedType t ) {
323
+ bindingset [ t]
324
+ private Type unspecify ( SpecifiedType t ) {
337
325
// This subtly and importantly handles the complicated cases of typedefs. Under most scenarios,
338
326
// if we see a typedef in `equalTypes()` we can simply get the base type and continue. However,
339
327
// there is an exception if we have a specified type that points to a typedef that points to
@@ -347,9 +335,9 @@ module TypeEquivalence<TypeEquivalenceSig Config, interestedInEquality/2 interes
347
335
}
348
336
349
337
bindingset [ t1, t2]
350
- private predicate equalDerivedTypes ( RelevantDerivedType t1 , RelevantDerivedType t2 ) {
338
+ private predicate equalDerivedTypes ( DerivedType t1 , DerivedType t2 ) {
351
339
exists ( Boolean baseTypesEqual |
352
- ( baseTypesEqual = true implies equalTypesImpl ( t1 .getBaseType ( ) , t2 .getBaseType ( ) ) ) and
340
+ ( baseTypesEqual = true implies equalTypes ( t1 .getBaseType ( ) , t2 .getBaseType ( ) ) ) and
353
341
(
354
342
Config:: equalPointerTypes ( t1 , t2 , baseTypesEqual )
355
343
or
@@ -363,20 +351,20 @@ module TypeEquivalence<TypeEquivalenceSig Config, interestedInEquality/2 interes
363
351
// Note that this case is different from the above, in that we don't merely get the base
364
352
// type (as that could be a TypedefType that points to another SpecifiedType). We need to
365
353
// unspecify the type to see if the base types are equal.
366
- ( unspecifiedTypesEqual = true implies equalTypesImpl ( unspecify ( t1 ) , unspecify ( t2 ) ) ) and
354
+ ( unspecifiedTypesEqual = true implies equalTypes ( unspecify ( t1 ) , unspecify ( t2 ) ) ) and
367
355
Config:: equalSpecifiedTypes ( t1 , t2 , unspecifiedTypesEqual )
368
356
)
369
357
}
370
358
371
359
bindingset [ t1, t2]
372
- private predicate equalFunctionTypes ( RelevantFunctionType t1 , RelevantFunctionType t2 ) {
360
+ private predicate equalFunctionTypes ( FunctionType t1 , FunctionType t2 ) {
373
361
exists ( Boolean returnTypeEqual , Boolean parameterTypesEqual |
374
- ( returnTypeEqual = true implies equalTypesImpl ( t1 .getReturnType ( ) , t2 .getReturnType ( ) ) ) and
362
+ ( returnTypeEqual = true implies equalTypes ( t1 .getReturnType ( ) , t2 .getReturnType ( ) ) ) and
375
363
(
376
364
parameterTypesEqual = true
377
365
implies
378
366
forall ( int i | exists ( [ t1 , t2 ] .getParameterType ( i ) ) |
379
- equalTypesImpl ( t1 .getParameterType ( i ) , t2 .getParameterType ( i ) )
367
+ equalTypes ( t1 .getParameterType ( i ) , t2 .getParameterType ( i ) )
380
368
)
381
369
) and
382
370
(
@@ -388,9 +376,9 @@ module TypeEquivalence<TypeEquivalenceSig Config, interestedInEquality/2 interes
388
376
}
389
377
390
378
bindingset [ t1, t2]
391
- private predicate equalTypedefTypes ( RelevantTypedefType t1 , RelevantTypedefType t2 ) {
379
+ private predicate equalTypedefTypes ( TypedefType t1 , TypedefType t2 ) {
392
380
exists ( Boolean baseTypesEqual |
393
- ( baseTypesEqual = true implies equalTypesImpl ( t1 .getBaseType ( ) , t2 .getBaseType ( ) ) ) and
381
+ ( baseTypesEqual = true implies equalTypes ( t1 .getBaseType ( ) , t2 .getBaseType ( ) ) ) and
394
382
Config:: equalTypedefTypes ( t1 , t2 , baseTypesEqual )
395
383
)
396
384
}
0 commit comments