Skip to content

Commit 9bd5222

Browse files
author
thk123
committed
Convert flatten_byte_extract to use structured exceptions
Store error in string to avoid dangling pointers
1 parent 3207291 commit 9bd5222

File tree

2 files changed

+160
-7
lines changed

2 files changed

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

20+
#include "flatten_byte_extract_exceptions.h"
2021
#include "flatten_byte_operators.h"
2122

2223
/// rewrite an object into its individual bytes
@@ -25,6 +26,9 @@ Author: Daniel Kroening, [email protected]
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)