Skip to content

Commit 02f8697

Browse files
romainbrenguierJoel Allred
authored and
Joel Allred
committed
Adding overflow checks in the parsing of integer (diffblue#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 e05353e commit 02f8697

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
@@ -642,25 +642,35 @@ exprt string_constraint_generatort::add_axioms_for_correct_number_format(
642642
binary_relation_exprt(chr, ID_ge, zero_char),
643643
binary_relation_exprt(chr, ID_le, nine_char));
644644

645+
// TODO: we should have implications in the other direction for correct
646+
// correct => |str| > 0
647+
exprt non_empty=str.axiom_for_is_longer_than(from_integer(1, index_type));
648+
axioms.push_back(implies_exprt(correct, non_empty));
649+
650+
// correct => (str[0] = '+' or '-' || '0' <= str[0] <= '9')
645651
or_exprt correct_first(
646652
or_exprt(starts_with_minus, starts_with_plus), starts_with_digit);
647-
exprt has_first=str.axiom_for_is_longer_than(from_integer(1, index_type));
648-
implies_exprt a1(correct, and_exprt(has_first, correct_first));
649-
axioms.push_back(a1);
653+
axioms.push_back(implies_exprt(correct, correct_first));
650654

651-
exprt not_too_long=str.axiom_for_is_shorter_than(max_size);
652-
axioms.push_back(not_too_long);
655+
// correct => str[0]='+' or '-' ==> |str| > 1
656+
implies_exprt contains_digit(
657+
or_exprt(starts_with_minus, starts_with_plus),
658+
str.axiom_for_is_longer_than(from_integer(2, index_type)));
659+
axioms.push_back(implies_exprt(correct, contains_digit));
653660

654-
symbol_exprt qvar=fresh_univ_index("number_format", index_type);
661+
// correct => |str| < max_size
662+
axioms.push_back(
663+
implies_exprt(correct, str.axiom_for_is_shorter_than(max_size)));
655664

665+
// forall 1 <= qvar < |str| . correct => '0'<= str[qvar] <= '9'
666+
symbol_exprt qvar=fresh_univ_index("number_format", index_type);
656667
and_exprt is_digit(
657668
binary_relation_exprt(str[qvar], ID_ge, zero_char),
658669
binary_relation_exprt(str[qvar], ID_le, nine_char));
659-
660-
string_constraintt a2(
670+
string_constraintt all_digits(
661671
qvar, from_integer(1, index_type), str.length(), correct, is_digit);
672+
axioms.push_back(all_digits);
662673

663-
axioms.push_back(a2);
664674
return correct;
665675
}
666676

@@ -706,10 +716,29 @@ exprt string_constraint_generatort::add_axioms_for_parse_int(
706716

707717
for(unsigned j=1; j<size; j++)
708718
{
709-
sum=plus_exprt(
710-
mult_exprt(sum, ten),
719+
mult_exprt ten_sum(sum, ten);
720+
if(j>=9)
721+
{
722+
// We have to be careful about overflows
723+
div_exprt div(sum, ten);
724+
equal_exprt no_overflow(div, sum);
725+
axioms.push_back(no_overflow);
726+
}
727+
728+
sum=plus_exprt_with_overflow_check(
729+
ten_sum,
711730
typecast_exprt(minus_exprt(str[j], zero_char), type));
712-
first_value=mult_exprt(first_value, ten);
731+
732+
mult_exprt first(first_value, ten);
733+
if(j>=9)
734+
{
735+
// We have to be careful about overflows
736+
div_exprt div_first(first, ten);
737+
implies_exprt no_overflow_first(
738+
starts_with_digit, equal_exprt(div_first, first_value));
739+
axioms.push_back(no_overflow_first);
740+
}
741+
first_value=first;
713742
}
714743

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

0 commit comments

Comments
 (0)