Skip to content

Commit 78cd286

Browse files
committed
Fix messaget's copy-constructor and operator=
These were broken, leaving an mstreamt whose back-pointer pointed into a different messaget than the one it enclosed, which could then have its message_handlert changed with unexpected side-effects, or be deleted causing a probable segfault on next log message. The added unit tests verify that this no longer happens.
1 parent 0681219 commit 78cd286

File tree

5 files changed

+80
-5
lines changed

5 files changed

+80
-5
lines changed

scripts/cpplint.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -4876,7 +4876,9 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
48764876
CheckCommaSpacing(filename, clean_lines, linenum, error)
48774877
CheckBracesSpacing(filename, clean_lines, linenum, nesting_state, error)
48784878
CheckSpacingForFunctionCall(filename, clean_lines, linenum, error)
4879-
CheckCheck(filename, clean_lines, linenum, error)
4879+
# Disabled because whatever CHECK macro this was looking for, it isn't the
4880+
# CHECK macro used in Catch, but was complaining about it anyway.
4881+
#CheckCheck(filename, clean_lines, linenum, error)
48804882
CheckAltTokens(filename, clean_lines, linenum, error)
48814883
CheckAssert(filename, clean_lines, linenum, error)
48824884
classinfo = nesting_state.InnermostClass()

src/solvers/refinement/string_refinement.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ string_refinementt::string_refinementt(const infot &info):
145145

146146
/// display the current index set, for debugging
147147
static void display_index_set(
148-
messaget::mstreamt stream,
148+
messaget::mstreamt &stream,
149149
const namespacet &ns,
150150
const index_set_pairt &index_set)
151151
{

src/util/message.h

+24-3
Original file line numberDiff line numberDiff line change
@@ -154,10 +154,17 @@ class messaget
154154

155155
messaget(const messaget &other):
156156
message_handler(other.message_handler),
157-
mstream(other.mstream)
157+
mstream(other.mstream, *this)
158158
{
159159
}
160160

161+
messaget &operator=(const messaget &other)
162+
{
163+
message_handler=other.message_handler;
164+
mstream.assign_from(other.mstream);
165+
return *this;
166+
}
167+
161168
explicit messaget(message_handlert &_message_handler):
162169
message_handler(&_message_handler),
163170
mstream(M_DEBUG, *this)
@@ -177,13 +184,17 @@ class messaget
177184
{
178185
}
179186

180-
mstreamt(const mstreamt &other):
187+
mstreamt(const mstreamt &other)=delete;
188+
189+
mstreamt(const mstreamt &other, messaget &_message):
181190
message_level(other.message_level),
182-
message(other.message),
191+
message(_message),
183192
source_location(other.source_location)
184193
{
185194
}
186195

196+
mstreamt &operator=(const mstreamt &other)=delete;
197+
187198
unsigned message_level;
188199
messaget &message;
189200
source_locationt source_location;
@@ -220,6 +231,16 @@ class messaget
220231
{
221232
return func(*this);
222233
}
234+
235+
private:
236+
void assign_from(const mstreamt &other)
237+
{
238+
message_level=other.message_level;
239+
source_location=other.source_location;
240+
// message, the pointer to my enclosing messaget, remains unaltered.
241+
}
242+
243+
friend class messaget;
223244
};
224245

225246
// Feeding 'eom' into the stream triggers

unit/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ SRC += unit_tests.cpp \
2727
solvers/refinement/string_refinement/substitute_array_list.cpp \
2828
util/expr_cast/expr_cast.cpp \
2929
util/expr_iterator.cpp \
30+
util/message.cpp \
3031
util/simplify_expr.cpp \
3132
catch_example.cpp \
3233
# Empty last line

unit/util/message.cpp

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*******************************************************************\
2+
3+
Module: Messaget tests
4+
5+
Author: Diffblue Limited. All rights reserved.
6+
7+
\*******************************************************************/
8+
9+
#include <testing-utils/catch.hpp>
10+
#include <util/message.h>
11+
#include <sstream>
12+
#include <string.h>
13+
14+
TEST_CASE("Copy a messaget")
15+
{
16+
std::ostringstream sstream1, sstream2;
17+
stream_message_handlert handler1(sstream1), handler2(sstream2);
18+
19+
messaget msg1(handler1);
20+
21+
// Copy messaget:
22+
messaget msg2(msg1);
23+
24+
// Change its handler:
25+
msg2.set_message_handler(handler2);
26+
27+
msg2.status() << "Test" << messaget::eom;
28+
29+
CHECK(sstream1.str()=="");
30+
CHECK(sstream2.str()=="Test\n");
31+
}
32+
33+
TEST_CASE("Assign a messaget")
34+
{
35+
std::ostringstream sstream1, sstream2;
36+
stream_message_handlert handler1(sstream1), handler2(sstream2);
37+
38+
messaget msg1(handler1);
39+
40+
// Assign messaget:
41+
messaget msg2;
42+
msg2=msg1;
43+
44+
// Change its handler:
45+
msg2.set_message_handler(handler2);
46+
47+
msg2.status() << "Test" << messaget::eom;
48+
49+
CHECK(sstream1.str()=="");
50+
CHECK(sstream2.str()=="Test\n");
51+
}

0 commit comments

Comments
 (0)