Skip to content

Commit e4a80aa

Browse files
romainbrenguiertautschnig
authored andcommitted
Adding overflow checks in the parsing of integer (#172)
This fixes diffblue/test-gen#172. Clarifying number format check and correcting overflow checks. This solves some issues related to the sign characters in string representing numbers.
1 parent 8977bcd commit e4a80aa

File tree

1 file changed

+41
-12
lines changed

1 file changed

+41
-12
lines changed

src/solvers/refinement/string_constraint_generator_valueof.cpp

+41-12
Original file line numberDiff line numberDiff line change
@@ -511,25 +511,35 @@ exprt string_constraint_generatort::add_axioms_for_correct_number_format(
511511
binary_relation_exprt(chr, ID_ge, zero_char),
512512
binary_relation_exprt(chr, ID_le, nine_char));
513513

514+
// TODO: we should have implications in the other direction for correct
515+
// correct => |str| > 0
516+
exprt non_empty=str.axiom_for_is_longer_than(from_integer(1, index_type));
517+
axioms.push_back(implies_exprt(correct, non_empty));
518+
519+
// correct => (str[0] = '+' or '-' || '0' <= str[0] <= '9')
514520
or_exprt correct_first(
515521
or_exprt(starts_with_minus, starts_with_plus), starts_with_digit);
516-
exprt has_first=str.axiom_for_is_longer_than(from_integer(1, index_type));
517-
implies_exprt a1(correct, and_exprt(has_first, correct_first));
518-
axioms.push_back(a1);
522+
axioms.push_back(implies_exprt(correct, correct_first));
519523

520-
exprt not_too_long=str.axiom_for_is_shorter_than(max_size);
521-
axioms.push_back(not_too_long);
524+
// correct => str[0]='+' or '-' ==> |str| > 1
525+
implies_exprt contains_digit(
526+
or_exprt(starts_with_minus, starts_with_plus),
527+
str.axiom_for_is_longer_than(from_integer(2, index_type)));
528+
axioms.push_back(implies_exprt(correct, contains_digit));
522529

523-
symbol_exprt qvar=fresh_univ_index("number_format", index_type);
530+
// correct => |str| < max_size
531+
axioms.push_back(
532+
implies_exprt(correct, str.axiom_for_is_shorter_than(max_size)));
524533

534+
// forall 1 <= qvar < |str| . correct => '0'<= str[qvar] <= '9'
535+
symbol_exprt qvar=fresh_univ_index("number_format", index_type);
525536
and_exprt is_digit(
526537
binary_relation_exprt(str[qvar], ID_ge, zero_char),
527538
binary_relation_exprt(str[qvar], ID_le, nine_char));
528-
529-
string_constraintt a2(
539+
string_constraintt all_digits(
530540
qvar, from_integer(1, index_type), str.length(), correct, is_digit);
541+
axioms.push_back(all_digits);
531542

532-
axioms.push_back(a2);
533543
return correct;
534544
}
535545

@@ -575,10 +585,29 @@ exprt string_constraint_generatort::add_axioms_for_parse_int(
575585

576586
for(unsigned j=1; j<size; j++)
577587
{
578-
sum=plus_exprt(
579-
mult_exprt(sum, ten),
588+
mult_exprt ten_sum(sum, ten);
589+
if(j>=9)
590+
{
591+
// We have to be careful about overflows
592+
div_exprt div(sum, ten);
593+
equal_exprt no_overflow(div, sum);
594+
axioms.push_back(no_overflow);
595+
}
596+
597+
sum=plus_exprt_with_overflow_check(
598+
ten_sum,
580599
typecast_exprt(minus_exprt(str[j], zero_char), type));
581-
first_value=mult_exprt(first_value, ten);
600+
601+
mult_exprt first(first_value, ten);
602+
if(j>=9)
603+
{
604+
// We have to be careful about overflows
605+
div_exprt div_first(first, ten);
606+
implies_exprt no_overflow_first(
607+
starts_with_digit, equal_exprt(div_first, first_value));
608+
axioms.push_back(no_overflow_first);
609+
}
610+
first_value=first;
582611
}
583612

584613
// If the length is `size`, we add axioms:

0 commit comments

Comments
 (0)