Skip to content

Commit 927d359

Browse files
authored
Merge pull request github#18310 from MathiasVP/fix-recursion-through-forex-in-sign-analysis
C++: Fix `forex` recursion in sign analysis
2 parents 87b9e60 + 4ffe70d commit 927d359

File tree

1 file changed

+81
-3
lines changed

1 file changed

+81
-3
lines changed

cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/SignAnalysisCommon.qll

Lines changed: 81 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -437,20 +437,98 @@ module SignAnalysis<DeltaSig D> {
437437
not hasGuard(v, pos, result)
438438
}
439439

440+
private SemExpr posBoundGetElement(int i, SemSsaVariable v, SsaReadPosition pos) {
441+
result =
442+
rank[i + 1](SemExpr bound, SemBasicBlock b, int blockOrder, int indexOrder |
443+
posBound(bound, v, pos) and
444+
b = bound.getBasicBlock() and
445+
blockOrder = b.getUniqueId() and
446+
bound = b.getInstruction(indexOrder)
447+
|
448+
bound order by blockOrder, indexOrder
449+
)
450+
}
451+
452+
private predicate posBoundOkFromIndex(int i, SemSsaVariable v, SsaReadPosition pos) {
453+
i = 0 and
454+
posBoundOk(posBoundGetElement(i, v, pos), v, pos)
455+
or
456+
posBoundOkFromIndex(i - 1, v, pos) and
457+
posBoundOk(posBoundGetElement(i, v, pos), v, pos)
458+
}
459+
460+
private predicate posBoundGuardedSsaSignOk(SemSsaVariable v, SsaReadPosition pos) {
461+
posBoundOkFromIndex(max(int i | exists(posBoundGetElement(i, v, pos))), v, pos)
462+
}
463+
464+
private SemExpr negBoundGetElement(int i, SemSsaVariable v, SsaReadPosition pos) {
465+
result =
466+
rank[i + 1](SemExpr bound, SemBasicBlock b, int blockOrder, int indexOrder |
467+
negBound(bound, v, pos) and
468+
b = bound.getBasicBlock() and
469+
blockOrder = b.getUniqueId() and
470+
bound = b.getInstruction(indexOrder)
471+
|
472+
bound order by blockOrder, indexOrder
473+
)
474+
}
475+
476+
private predicate negBoundOkFromIndex(int i, SemSsaVariable v, SsaReadPosition pos) {
477+
i = 0 and
478+
negBoundOk(negBoundGetElement(i, v, pos), v, pos)
479+
or
480+
negBoundOkFromIndex(i - 1, v, pos) and
481+
negBoundOk(negBoundGetElement(i, v, pos), v, pos)
482+
}
483+
484+
private predicate negBoundGuardedSsaSignOk(SemSsaVariable v, SsaReadPosition pos) {
485+
negBoundOkFromIndex(max(int i | exists(negBoundGetElement(i, v, pos))), v, pos)
486+
}
487+
488+
private SemExpr zeroBoundGetElement(int i, SemSsaVariable v, SsaReadPosition pos) {
489+
result =
490+
rank[i + 1](SemExpr bound, SemBasicBlock b, int blockOrder, int indexOrder |
491+
zeroBound(bound, v, pos) and
492+
b = bound.getBasicBlock() and
493+
blockOrder = b.getUniqueId() and
494+
bound = b.getInstruction(indexOrder)
495+
|
496+
bound order by blockOrder, indexOrder
497+
)
498+
}
499+
500+
private predicate zeroBoundOkFromIndex(int i, SemSsaVariable v, SsaReadPosition pos) {
501+
i = 0 and
502+
zeroBoundOk(zeroBoundGetElement(i, v, pos), v, pos)
503+
or
504+
zeroBoundOkFromIndex(i - 1, v, pos) and
505+
zeroBoundOk(zeroBoundGetElement(i, v, pos), v, pos)
506+
}
507+
508+
private predicate zeroBoundGuardedSsaSignOk(SemSsaVariable v, SsaReadPosition pos) {
509+
zeroBoundOkFromIndex(max(int i | exists(zeroBoundGetElement(i, v, pos))), v, pos)
510+
}
511+
440512
/**
441513
* Gets a possible sign of `v` at read position `pos`, where a guard could have
442514
* ruled out the sign but does not.
443515
* This does not check that the definition of `v` also allows the sign.
444516
*/
445517
private Sign guardedSsaSignOk(SemSsaVariable v, SsaReadPosition pos) {
446518
result = TPos() and
447-
forex(SemExpr bound | posBound(bound, v, pos) | posBoundOk(bound, v, pos))
519+
// optimised version of
520+
// `forex(SemExpr bound | posBound(bound, v, pos) | posBoundOk(bound, v, pos))`
521+
posBoundGuardedSsaSignOk(v, pos)
448522
or
449523
result = TNeg() and
450-
forex(SemExpr bound | negBound(bound, v, pos) | negBoundOk(bound, v, pos))
524+
// optimised version of
525+
// `forex(SemExpr bound | negBound(bound, v, pos) | negBoundOk(bound, v, pos))`
526+
negBoundGuardedSsaSignOk(v, pos)
451527
or
452528
result = TZero() and
453-
forex(SemExpr bound | zeroBound(bound, v, pos) | zeroBoundOk(bound, v, pos))
529+
// optimised version of
530+
// `forex(SemExpr bound | zeroBound(bound, v, pos) | zeroBoundOk(bound, v, pos))`
531+
zeroBoundGuardedSsaSignOk(v, pos)
454532
}
455533

456534
/** Gets a possible sign for `v` at `pos`. */

0 commit comments

Comments
 (0)