Skip to content

Commit 5593f45

Browse files
authored
[analyzer] Fix crash in Z3 SMTConv when negating a boolean expression (#165779) (#168034)
Refer to #158276 for previous hotfix. In Z3, boolean expressions are incompatible with bitvec operators. However, C expressions like `-(5 && a)` will generate such symbolic expressions, which will be further used as an integer. To be compatible with such usages, this fix converts such expressions to integer using the existing `fromCast`.
1 parent 85db928 commit 5593f45

File tree

2 files changed

+17
-11
lines changed

2 files changed

+17
-11
lines changed

clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -456,17 +456,15 @@ class SMTConv {
456456
llvm::SMTExprRef OperandExp =
457457
getSymExpr(Solver, Ctx, USE->getOperand(), &OperandTy, hasComparison);
458458

459-
if (const BinarySymExpr *BSE =
460-
dyn_cast<BinarySymExpr>(USE->getOperand())) {
461-
if (USE->getOpcode() == UO_Minus &&
462-
BinaryOperator::isComparisonOp(BSE->getOpcode()))
463-
// The comparison operator yields a boolean value in the Z3
464-
// language and applying the unary minus operator on a boolean
465-
// crashes Z3. However, the unary minus does nothing in this
466-
// context (a number is truthy if and only if its negative is
467-
// truthy), so let's just ignore the unary minus.
468-
// TODO: Replace this with a more general solution.
469-
return OperandExp;
459+
// When the operand is a bool expr, but the operator is an integeral
460+
// operator, casting the bool expr to the integer before creating the
461+
// unary operator.
462+
// E.g. -(5 && a)
463+
if (OperandTy == Ctx.BoolTy && OperandTy != *RetTy &&
464+
(*RetTy)->isIntegerType()) {
465+
OperandExp = fromCast(Solver, OperandExp, (*RetTy),
466+
Ctx.getTypeSize(*RetTy), OperandTy, 1);
467+
OperandTy = (*RetTy);
470468
}
471469

472470
llvm::SMTExprRef UnaryExp =

clang/test/Analysis/z3-unarysymexpr.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,11 @@ int z3_crash2(int a) {
4747
return *d; // expected-warning{{Dereference of undefined pointer value}}
4848
return 0;
4949
}
50+
51+
// Refer to issue 165779
52+
void z3_crash3(long a) {
53+
if (~-(5 && a)) {
54+
long *c;
55+
*c; // expected-warning{{Dereference of undefined pointer value (loaded from variable 'c')}}
56+
}
57+
}

0 commit comments

Comments
 (0)