Skip to content

Commit 99cb995

Browse files
Strings: Add preconditions for range in CVC4 and improve error handling
1 parent e334a82 commit 99cb995

File tree

2 files changed

+32
-18
lines changed

2 files changed

+32
-18
lines changed

src/org/sosy_lab/java_smt/solvers/cvc4/CVC4StringFormulaManager.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,33 @@ protected Expr allCharImpl() {
143143
return exprManager.mkExpr(Kind.REGEXP_SIGMA, new vectorExpr());
144144
}
145145

146+
/**
147+
* Check if the String only contains printable US ASCII characters.
148+
*
149+
* <p>We use this function to check if the String contains any characters that would have to be
150+
* escaped in SMTLIB.
151+
*/
152+
private boolean isAsciiString(String str) {
153+
return str.codePoints().allMatch(c -> c >= 0x20 && c <= 0x7E);
154+
}
155+
146156
@Override
147157
protected Expr range(Expr start, Expr end) {
148-
// FIXME CVC4 will crash when start > end, even if we add an ITE with preconditions
149-
return exprManager.mkExpr(Kind.REGEXP_RANGE, start, end);
158+
Preconditions.checkArgument(
159+
start.isConst() && end.isConst(), "CVC4 does not support variables as bounds");
160+
161+
String lower = (String) formulaCreator.convertValue(start, start);
162+
String upper = (String) formulaCreator.convertValue(end, end);
163+
164+
Preconditions.checkArgument(
165+
isAsciiString(lower) && isAsciiString(upper),
166+
"CVC4 only allows printable US ASCII characters as bounds");
167+
168+
// Return the empty language if the bounds are not single character Strings, or if the upper
169+
// bound is smaller than the lower bound
170+
return lower.length() != 1 || upper.length() != 1 || upper.compareTo(lower) < 0
171+
? noneImpl()
172+
: exprManager.mkExpr(Kind.REGEXP_RANGE, start, end);
150173
}
151174

152175
@Override

src/org/sosy_lab/java_smt/test/StringFormulaManagerTest.java

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -296,28 +296,19 @@ public void testStringRange() throws SolverException, InterruptedException {
296296

297297
// Check some corner cases:
298298
// StringFormulaManager.range("b", "a") should be empty
299-
if (solver != Solvers.CVC4) {
300-
// FIXME CVC4 expects that the lower bound is smaller or equal to the upper bound
301-
assertThatFormula(smgr.in(var, smgr.range(smgr.makeString("b"), smgr.makeString("a"))))
302-
.isUnsatisfiable();
303-
assertThatFormula(smgr.in(var, smgr.range('b', 'a'))).isUnsatisfiable();
304-
}
299+
assertThatFormula(smgr.in(var, smgr.range(smgr.makeString("b"), smgr.makeString("a"))))
300+
.isUnsatisfiable();
301+
assertThatFormula(smgr.in(var, smgr.range('b', 'a'))).isUnsatisfiable();
305302

306303
// Only 'singleton' Strings (= Strings with one character) are allowed:
307304
// StringFormulaManager.range("", "a") should be empty
308-
if (solver != Solvers.CVC4) {
309-
// FIXME CVC4 expects both bounds to be single character Strings
310-
assertThatFormula(smgr.in(var, smgr.range(smgr.makeString(""), smgr.makeString("a"))))
311-
.isUnsatisfiable();
312-
}
305+
assertThatFormula(smgr.in(var, smgr.range(smgr.makeString(""), smgr.makeString("a"))))
306+
.isUnsatisfiable();
313307

314308
// Try again with two characters:
315309
// StringFormulaManager.range("aa", "ab") should be empty
316-
if (solver != Solvers.CVC4) {
317-
// FIXME CVC4 expects both bounds to be single character Strings
318-
assertThatFormula(smgr.in(var, smgr.range(smgr.makeString("aa"), smgr.makeString("ab"))))
319-
.isUnsatisfiable();
320-
}
310+
assertThatFormula(smgr.in(var, smgr.range(smgr.makeString("aa"), smgr.makeString("ab"))))
311+
.isUnsatisfiable();
321312

322313
// Now use variables for the bounds:
323314
// StringFormulaManager.range(lower, "b") should be empty iff "b" < lower

0 commit comments

Comments
 (0)