Skip to content

Commit c9697a7

Browse files
author
thk123
committed
Convert flatten_byte_extract to use structured exceptions
Store error in string to avoid dangling pointers
1 parent 700a1f4 commit c9697a7

File tree

2 files changed

+163
-7
lines changed

2 files changed

+163
-7
lines changed
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/*******************************************************************\
2+
3+
Module: Byte flattening
4+
5+
Author: Diffblue Ltd.
6+
7+
\*******************************************************************/
8+
9+
#ifndef CPROVER_SOLVERS_FLATTENING_FLATTEN_BYTE_EXTRACT_EXCEPTIONS_H
10+
#define CPROVER_SOLVERS_FLATTENING_FLATTEN_BYTE_EXTRACT_EXCEPTIONS_H
11+
12+
#include <sstream>
13+
#include <iostream>
14+
#include <util/simplify_expr.h>
15+
#include <util/namespace.h>
16+
#include <util/byte_operators.h>
17+
#include <util/pointer_offset_size.h>
18+
#include <util/arith_tools.h>
19+
#include <util/std_expr.h>
20+
#include <util/c_types.h>
21+
22+
class flatten_byte_extract_exceptiont : public std::runtime_error
23+
{
24+
public:
25+
explicit flatten_byte_extract_exceptiont(const std::string &exception_message)
26+
: runtime_error(exception_message)
27+
{
28+
}
29+
};
30+
31+
class non_const_array_sizet : public flatten_byte_extract_exceptiont
32+
{
33+
public:
34+
non_const_array_sizet(const array_typet &array_type, const exprt &max_bytes)
35+
: flatten_byte_extract_exceptiont("cannot unpack array of non-const size"),
36+
max_bytes(max_bytes),
37+
array_type(array_type)
38+
{
39+
std::ostringstream error_message;
40+
error_message << runtime_error::what() << "\n";
41+
error_message << "array_type: " << array_type.pretty();
42+
error_message << "\nmax_bytes: " << max_bytes.pretty();
43+
computed_error_message = error_message.str();
44+
}
45+
46+
const char *what() const noexcept override
47+
{
48+
return computed_error_message.c_str();
49+
}
50+
51+
private:
52+
exprt max_bytes;
53+
array_typet array_type;
54+
55+
std::string computed_error_message;
56+
};
57+
58+
class non_byte_alignedt : public flatten_byte_extract_exceptiont
59+
{
60+
public:
61+
non_byte_alignedt(
62+
const struct_typet &struct_type,
63+
const struct_union_typet::componentt &component,
64+
const mp_integer &byte_width)
65+
: flatten_byte_extract_exceptiont(
66+
"cannot unpack struct with non-byte aligned components"),
67+
struct_type(struct_type),
68+
component(component),
69+
byte_width(byte_width)
70+
{
71+
std::ostringstream error_message;
72+
error_message << runtime_error::what() << "\n";
73+
error_message << "width: " << byte_width << "\n";
74+
error_message << "component:" << component.get_name() << "\n";
75+
error_message << "struct_type: " << struct_type.pretty();
76+
computed_error_message = error_message.str();
77+
}
78+
79+
const char *what() const noexcept override
80+
{
81+
return computed_error_message.c_str();
82+
}
83+
84+
private:
85+
const struct_typet struct_type;
86+
const struct_union_typet::componentt component;
87+
const mp_integer byte_width;
88+
89+
std::string computed_error_message;
90+
};
91+
92+
class non_constant_widtht : public flatten_byte_extract_exceptiont
93+
{
94+
public:
95+
public:
96+
non_constant_widtht(const exprt &src, const exprt &max_bytes)
97+
: flatten_byte_extract_exceptiont(
98+
"cannot unpack object of non-constant width"),
99+
src(src),
100+
max_bytes(max_bytes)
101+
{
102+
std::ostringstream error_message;
103+
error_message << runtime_error::what() << "\n";
104+
error_message << "array_type: " << src.pretty();
105+
error_message << "\nmax_bytes: " << max_bytes.pretty();
106+
computed_error_message = error_message.str();
107+
}
108+
109+
const char *what() const noexcept override
110+
{
111+
return computed_error_message.c_str();
112+
}
113+
114+
private:
115+
exprt src;
116+
exprt max_bytes;
117+
118+
std::string computed_error_message;
119+
};
120+
121+
class non_const_byte_extraction_sizet : public flatten_byte_extract_exceptiont
122+
{
123+
public:
124+
explicit non_const_byte_extraction_sizet(
125+
const byte_extract_exprt &unpack_expr)
126+
: flatten_byte_extract_exceptiont(
127+
"byte_extract flatting with non-constant size"),
128+
unpack_expr(unpack_expr)
129+
{
130+
std::ostringstream error_message;
131+
error_message << runtime_error::what() << "\n";
132+
error_message << "unpack_expr: " << unpack_expr.pretty();
133+
computed_error_message = error_message.str();
134+
}
135+
136+
const char *what() const noexcept override
137+
{
138+
return computed_error_message.c_str();
139+
}
140+
141+
private:
142+
const byte_extract_exprt unpack_expr;
143+
144+
std::string computed_error_message;
145+
};
146+
147+
#endif // CPROVER_SOLVERS_FLATTENING_FLATTEN_BYTE_EXTRACT_EXCEPTIONS_H

src/solvers/flattening/flatten_byte_operators.cpp

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,17 @@ Author: Daniel Kroening, [email protected]
1818
#include <util/simplify_expr.h>
1919

2020
#include "flatten_byte_operators.h"
21+
#include "flatten_byte_extract_exceptions.h"
2122

2223
/// rewrite an object into its individual bytes
2324
/// \par parameters: src object to unpack
2425
/// little_endian true, iff assumed endianness is little-endian
2526
/// max_bytes if not nil, use as upper bound of the number of bytes to unpack
2627
/// ns namespace for type lookups
2728
/// \return array of bytes in the sequence found in memory
29+
/// \throws flatten_byte_extract_exceptiont Raised is unable to unpack the
30+
/// object because of either non constant size, byte misalignment or
31+
/// non-constant component width.
2832
static exprt unpack_rec(
2933
const exprt &src,
3034
bool little_endian,
@@ -63,7 +67,9 @@ static exprt unpack_rec(
6367
mp_integer num_elements;
6468
if(to_integer(max_bytes, num_elements) &&
6569
to_integer(array_type.size(), num_elements))
66-
throw "cannot unpack array of non-const size:\n"+type.pretty();
70+
{
71+
throw non_const_array_sizet(array_type, max_bytes);
72+
}
6773

6874
// all array members will have the same structure; do this just
6975
// once and then replace the dummy symbol by a suitable index
@@ -97,8 +103,9 @@ static exprt unpack_rec(
97103

98104
// the next member would be misaligned, abort
99105
if(element_width<=0 || element_width%8!=0)
100-
throw "cannot unpack struct with non-byte aligned components:\n"+
101-
struct_type.pretty();
106+
{
107+
throw non_byte_alignedt(struct_type, comp, element_width);
108+
}
102109

103110
member_exprt member(src, comp.get_name(), comp.type());
104111
exprt sub=unpack_rec(member, little_endian, max_bytes, ns, true);
@@ -115,8 +122,9 @@ static exprt unpack_rec(
115122
if(bits<0)
116123
{
117124
if(to_integer(max_bytes, bits))
118-
throw "cannot unpack object of non-constant width:\n"+
119-
src.pretty();
125+
{
126+
throw non_constant_widtht(src, max_bytes);
127+
}
120128
else
121129
bits*=8;
122130
}
@@ -300,8 +308,9 @@ exprt flatten_byte_extract(
300308
{
301309
mp_integer op0_bits=pointer_offset_bits(unpacked.op().type(), ns);
302310
if(op0_bits<0)
303-
throw "byte_extract flatting with non-constant size:\n"+
304-
unpacked.pretty();
311+
{
312+
throw non_const_byte_extraction_sizet(unpacked);
313+
}
305314
else
306315
size_bits=op0_bits;
307316
}

0 commit comments

Comments
 (0)