Skip to content

Commit 33b8346

Browse files
committed
C++: Do not define typeStep using TypeState columns.
Instead we: 1. first do a forward pass to first compute all the reachable type states, and then 2. define the `TypeState` type. This commit does (1). The next commit does (2).
1 parent a4ca101 commit 33b8346

1 file changed

Lines changed: 78 additions & 67 deletions

File tree

‎cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll‎

Lines changed: 78 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1329,21 +1329,12 @@ module ConstructorForwarding {
13291329
result.getBaseType() = base.getUnderlyingType()
13301330
}
13311331

1332-
private predicate arrayToPointerStep(TypeState argState, TypeState paramState) {
1333-
exists(Cpp::ArrayType array, boolean conversionUsed |
1334-
argState = MkTypeState(array, _, conversionUsed, Initial()) and
1335-
paramState =
1336-
MkTypeState(pointerType(array.getBaseType()), PRValue(), conversionUsed,
1337-
AfterTransformation())
1338-
)
1332+
private predicate arrayToPointerStep(Cpp::ArrayType array, Cpp::PointerType pointer) {
1333+
pointer = pointerType(array.getBaseType())
13391334
}
13401335

1341-
private predicate functionToPointerStep(TypeState argState, TypeState paramState) {
1342-
exists(RoutineType routine, FunctionPointerType pointer, boolean conversionUsed |
1343-
argState = MkTypeState(routine, _, conversionUsed, Initial()) and
1344-
routine = pointer.getBaseType().getUnderlyingType() and
1345-
paramState = MkTypeState(pointer, PRValue(), conversionUsed, AfterTransformation())
1346-
)
1336+
private predicate functionToPointerStep(RoutineType routine, FunctionPointerType pointer) {
1337+
routine = pointer.getBaseType().getUnderlyingType()
13471338
}
13481339

13491340
private predicate arithmeticConversion(Type t) {
@@ -1354,14 +1345,12 @@ module ConstructorForwarding {
13541345

13551346
private predicate hasNoTopLevelSpecifiers(Type type) { type = type.stripTopLevelSpecifiers() }
13561347

1357-
private predicate valueConversionStep(TypeState argState, TypeState paramState) {
1358-
exists(Type argType, Type paramType, boolean conversionUsed |
1359-
argState = MkTypeState(_, _, conversionUsed, _) and
1360-
argState.canConvertValue() and
1361-
argType = argState.getType().stripTopLevelSpecifiers() and
1348+
bindingset[type]
1349+
private predicate valueConversionStep(Type type, Type paramType) {
1350+
exists(Type argType |
1351+
argType = type.stripTopLevelSpecifiers() and
13621352
hasNoTopLevelSpecifiers(paramType) and
1363-
argType != paramType and
1364-
paramState = MkTypeState(paramType, PRValue(), conversionUsed, AfterValueConversion())
1353+
argType != paramType
13651354
|
13661355
paramType instanceof ArithmeticType and
13671356
arithmeticConversion(argType)
@@ -1388,64 +1377,82 @@ module ConstructorForwarding {
13881377
k = FunPtrKind()
13891378
}
13901379

1391-
private predicate pointerQualificationStep(TypeState argState, TypeState paramState) {
1392-
exists(Type argType, Type paramType, boolean conversionUsed, PtrKind k |
1393-
argState = MkTypeState(_, _, conversionUsed, _) and
1394-
argState.getPhase() != AfterQualification() and
1395-
argType = argState.getType().stripTopLevelSpecifiers() and
1380+
bindingset[type]
1381+
private predicate pointerQualificationStep(Type type, Type paramType) {
1382+
exists(Type argType, PtrKind k |
1383+
argType = type.stripTopLevelSpecifiers() and
13961384
hasNoTopLevelSpecifiers(paramType) and
13971385
argType != paramType and
1398-
qualificationCompatible(pointerBase(argType, k), pointerBase(paramType, k)) and
1399-
paramState = MkTypeState(paramType, PRValue(), conversionUsed, AfterQualification())
1386+
qualificationCompatible(pointerBase(argType, pragma[only_bind_into](k)),
1387+
pointerBase(paramType, pragma[only_bind_into](k)))
14001388
)
14011389
}
14021390

1403-
private predicate baseClassStep(TypeState argState, TypeState paramState) {
1404-
exists(Type arg, Type param, ValueCategory category, boolean conversionUsed |
1405-
argState = MkTypeState(arg, category, conversionUsed, _) and
1406-
argState.canConvertValue() and
1407-
baseTypeCompatible(arg, param) and
1408-
paramState = MkTypeState(param, category, conversionUsed, AfterValueConversion())
1409-
)
1391+
bindingset[argType]
1392+
private predicate baseClassStep(Type argType, Type paramType) {
1393+
baseTypeCompatible(argType, paramType)
14101394
}
14111395

1412-
private predicate convertingConstructorStep(TypeState argState, TypeState paramState) {
1396+
bindingset[argType, argCategory]
1397+
private predicate convertingConstructorStep(
1398+
Type argType, ValueCategory argCategory, Class paramType
1399+
) {
14131400
exists(ConvertingConstructor constructor |
1414-
argState.hasNotUsedConversion() and
1415-
matchesParameter(argState.getType(), argState.getCategory(),
1416-
constructor.getUnderlyingFromType()) and
1417-
paramState = MkTypeState(constructor.getDeclaringType(), PRValue(), true, Initial())
1401+
matchesParameter(argType, argCategory, constructor.getUnderlyingFromType()) and
1402+
paramType = constructor.getDeclaringType()
14181403
)
14191404
}
14201405

1421-
private predicate conversionOperatorStep(TypeState argState, TypeState paramState) {
1422-
exists(ConversionOperator conversion, ValueCategory category |
1406+
bindingset[argType]
1407+
private predicate conversionOperatorStep(Type argType, Type paramType, ValueCategory paramCategory) {
1408+
exists(ConversionOperator conversion |
14231409
not conversion.isFromUninstantiatedTemplate(_) and
14241410
not conversion.isExplicit() and
14251411
not conversion.isDeleted() and
1426-
argState.hasNotUsedConversion() and
1427-
conversion.getSourceType() =
1428-
argState.getType().stripTopLevelSpecifiers().(Class).getABaseClass*() and
1429-
paramState =
1430-
MkTypeState(getValueType(conversion.getDestType().getUnderlyingType(), category), category,
1431-
true, Initial())
1412+
conversion.getSourceType() = argType.stripTopLevelSpecifiers().(Class).getABaseClass*() and
1413+
paramType = getValueType(conversion.getDestType().getUnderlyingType(), paramCategory)
14321414
)
14331415
}
14341416

1435-
private predicate step(TypeState argState, TypeState paramState) {
1436-
arrayToPointerStep(argState, paramState)
1437-
or
1438-
functionToPointerStep(argState, paramState)
1439-
or
1440-
valueConversionStep(argState, paramState)
1441-
or
1442-
pointerQualificationStep(argState, paramState)
1443-
or
1444-
baseClassStep(argState, paramState)
1445-
or
1446-
convertingConstructorStep(argState, paramState)
1417+
bindingset[argType, argCategory, argConversionUsed, argPhase]
1418+
pragma[inline_late]
1419+
private predicate typeStep(
1420+
Type argType, ValueCategory argCategory, boolean argConversionUsed, Phase argPhase,
1421+
Type paramType, ValueCategory paramCategory, boolean paramConversionUsed, Phase paramPhase
1422+
) {
1423+
paramConversionUsed = argConversionUsed and
1424+
(
1425+
argPhase = Initial() and
1426+
paramCategory = PRValue() and
1427+
paramPhase = AfterTransformation() and
1428+
(
1429+
arrayToPointerStep(argType, paramType)
1430+
or
1431+
functionToPointerStep(argType, paramType)
1432+
)
1433+
or
1434+
(argPhase = Initial() or argPhase = AfterTransformation()) and
1435+
paramPhase = AfterValueConversion() and
1436+
(
1437+
valueConversionStep(argType, paramType) and paramCategory = PRValue()
1438+
or
1439+
baseClassStep(argType, paramType) and paramCategory = argCategory
1440+
)
1441+
or
1442+
argPhase != AfterQualification() and
1443+
pointerQualificationStep(argType, paramType) and
1444+
paramCategory = PRValue() and
1445+
paramPhase = AfterQualification()
1446+
)
14471447
or
1448-
conversionOperatorStep(argState, paramState)
1448+
argConversionUsed = false and
1449+
paramConversionUsed = true and
1450+
paramPhase = Initial() and
1451+
(
1452+
convertingConstructorStep(argType, argCategory, paramType) and paramCategory = PRValue()
1453+
or
1454+
conversionOperatorStep(argType, paramType, paramCategory)
1455+
)
14491456
}
14501457

14511458
private predicate typeFwd(TypeState state) {
@@ -1471,13 +1478,6 @@ module ConstructorForwarding {
14711478

14721479
Phase getPhase() { this = MkTypeState(_, _, _, result) }
14731480

1474-
/** Holds if this state's phase permits a value or base-class conversion. */
1475-
predicate canConvertValue() {
1476-
this.getPhase() = Initial() or this.getPhase() = AfterTransformation()
1477-
}
1478-
1479-
predicate hasNotUsedConversion() { this = MkTypeState(_, _, false, _) }
1480-
14811481
string toString() { result = this.getType().toString() }
14821482

14831483
predicate isSource(Type argType) {
@@ -1493,6 +1493,17 @@ module ConstructorForwarding {
14931493
}
14941494
}
14951495

1496+
private predicate step(TypeState argState, TypeState paramState) {
1497+
exists(
1498+
Type t1, Type t2, ValueCategory vc1, ValueCategory vc2, boolean b1, boolean b2, Phase p1,
1499+
Phase p2
1500+
|
1501+
argState = MkTypeState(t1, vc1, b1, p1) and
1502+
paramState = MkTypeState(t2, vc2, b2, p2) and
1503+
typeStep(t1, vc1, b1, p1, t2, vc2, b2, p2)
1504+
)
1505+
}
1506+
14961507
private predicate typeRev(TypeState state, Cpp::Constructor constructor) {
14971508
typeFwd(state) and
14981509
(

0 commit comments

Comments
 (0)