Skip to content

Commit f872937

Browse files
authored
Merge pull request #7444 from diffblue/pointer-to-bit
prohibit pointers to bit-vectors that are not byte-aligned
2 parents 5b56469 + 0aba4e8 commit f872937

File tree

11 files changed

+105
-12
lines changed

11 files changed

+105
-12
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
__CPROVER_bool x;
2+
3+
int main()
4+
{
5+
void *p = &x; // should error
6+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
pointer-to-bool.c
3+
4+
cannot take address of a proper Boolean$
5+
^EXIT=(1|64)$
6+
^SIGNAL=0$
7+
--
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
__CPROVER_bitvector[123] z[10];
2+
3+
int main()
4+
{
5+
void *p = z; // should error
6+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
pointer-to-bv-array1.c
3+
4+
bitvector must have width that is a multiple of CHAR_BIT$
5+
^EXIT=(1|64)$
6+
^SIGNAL=0$
7+
--
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
__CPROVER_bitvector[123] z[10];
2+
3+
int main()
4+
{
5+
void *p = (int *)z; // should error
6+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
pointer-to-bv-array2.c
3+
4+
bitvector must have width that is a multiple of CHAR_BIT$
5+
^EXIT=(1|64)$
6+
^SIGNAL=0$
7+
--
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
__CPROVER_bitvector[15] y;
2+
3+
int main()
4+
{
5+
void *p = &y; // should error
6+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
pointer-to-bv.c
3+
4+
bitvector must have width that is a multiple of CHAR_BIT$
5+
^EXIT=(1|64)$
6+
^SIGNAL=0$
7+
--

src/ansi-c/c_typecast.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,15 @@ void c_typecastt::do_typecast(exprt &expr, const typet &dest_type)
739739

740740
if(src_type.id()==ID_array)
741741
{
742+
// This is the promotion from an array
743+
// to a pointer to the first element.
744+
auto error_opt = check_address_can_be_taken(expr.type());
745+
if(error_opt.has_value())
746+
{
747+
errors.push_back(error_opt.value());
748+
return;
749+
}
750+
742751
index_exprt index(expr, from_integer(0, c_index_type()));
743752
expr = typecast_exprt::conditional_cast(address_of_exprt(index), dest_type);
744753
return;
@@ -765,3 +774,31 @@ void c_typecastt::do_typecast(exprt &expr, const typet &dest_type)
765774
}
766775
}
767776
}
777+
778+
optionalt<std::string>
779+
c_typecastt::check_address_can_be_taken(const typet &type)
780+
{
781+
if(type.id() == ID_c_bit_field)
782+
return std::string("cannot take address of a bit field");
783+
784+
if(type.id() == ID_bool)
785+
return std::string("cannot take address of a proper Boolean");
786+
787+
if(can_cast_type<bitvector_typet>(type))
788+
{
789+
// The width of the bitvector must be a multiple of CHAR_BIT.
790+
auto width = to_bitvector_type(type).get_width();
791+
if(width % config.ansi_c.char_width != 0)
792+
{
793+
return std::string(
794+
"bitvector must have width that is a multiple of CHAR_BIT");
795+
}
796+
else
797+
return {};
798+
}
799+
800+
if(type.id() == ID_array)
801+
return check_address_can_be_taken(to_array_type(type).element_type());
802+
803+
return {}; // ok
804+
}

src/ansi-c/c_typecast.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ Author: Daniel Kroening, [email protected]
1010
#ifndef CPROVER_ANSI_C_C_TYPECAST_H
1111
#define CPROVER_ANSI_C_C_TYPECAST_H
1212

13+
#include <util/optional.h>
14+
1315
#include <list>
1416
#include <string>
1517

@@ -65,6 +67,10 @@ class c_typecastt
6567
std::list<std::string> errors;
6668
std::list<std::string> warnings;
6769

70+
/// \return empty when address can be taken,
71+
/// error message otherwise
72+
static optionalt<std::string> check_address_can_be_taken(const typet &);
73+
6874
protected:
6975
const namespacet &ns;
7076

0 commit comments

Comments
 (0)