• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 6704830136

31 Oct 2023 09:55AM UTC coverage: 91.722% (+0.001%) from 91.721%
6704830136

push

github

web-flow
Merge pull request #3752 from randombit/jack/allocator-helper

Split out allocator helpers to allocator.h

80150 of 87384 relevant lines covered (91.72%)

8593301.14 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.29
/src/lib/filters/pipe.cpp
1
/*
2
* Pipe
3
* (C) 1999-2007 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7

8
#include <botan/pipe.h>
9

10
#include <botan/mem_ops.h>
11
#include <botan/internal/fmt.h>
12
#include <botan/internal/out_buf.h>
13
#include <botan/internal/secqueue.h>
14
#include <memory>
15

16
namespace Botan {
17

18
namespace {
19

20
/*
21
* A Filter that does nothing
22
*/
23
class Null_Filter final : public Filter {
4✔
24
   public:
25
      void write(const uint8_t input[], size_t length) override { send(input, length); }
1✔
26

27
      std::string name() const override { return "Null"; }
×
28
};
29

30
}  // namespace
31

32
Pipe::Invalid_Message_Number::Invalid_Message_Number(std::string_view where, message_id msg) :
1✔
33
      Invalid_Argument(fmt("Pipe::{}: Invalid message number {}", where, msg)) {}
2✔
34

35
/*
36
* Pipe Constructor
37
*/
38
Pipe::Pipe(Filter* f1, Filter* f2, Filter* f3, Filter* f4) : Pipe({f1, f2, f3, f4}) {}
18✔
39

40
/*
41
* Pipe Constructor
42
*/
43
Pipe::Pipe(std::initializer_list<Filter*> args) {
18✔
44
   m_outputs = std::make_unique<Output_Buffers>();
18✔
45
   m_pipe = nullptr;
18✔
46
   m_default_read = 0;
18✔
47
   m_inside_msg = false;
18✔
48

49
   for(auto arg : args) {
90✔
50
      do_append(arg);
72✔
51
   }
52
}
18✔
53

54
/*
55
* Pipe Destructor
56
*/
57
Pipe::~Pipe() {
18✔
58
   destruct(m_pipe);
18✔
59
}
18✔
60

61
/*
62
* Reset the Pipe
63
*/
64
void Pipe::reset() {
6✔
65
   destruct(m_pipe);
6✔
66
   m_pipe = nullptr;
6✔
67
   m_inside_msg = false;
6✔
68
}
6✔
69

70
/*
71
* Destroy the Pipe
72
*/
73
void Pipe::destruct(Filter* to_kill) {
80✔
74
   if(!to_kill || dynamic_cast<SecureQueue*>(to_kill)) {
80✔
75
      return;
76
   }
77
   for(size_t j = 0; j != to_kill->total_ports(); ++j) {
105✔
78
      destruct(to_kill->m_next[j]);
56✔
79
   }
80
   delete to_kill;
49✔
81
}
82

83
/*
84
* Test if the Pipe has any data in it
85
*/
86
bool Pipe::end_of_data() const {
2✔
87
   return (remaining() == 0);
2✔
88
}
89

90
/*
91
* Set the default read message
92
*/
93
void Pipe::set_default_msg(message_id msg) {
3✔
94
   if(msg >= message_count()) {
3✔
95
      throw Invalid_Argument("Pipe::set_default_msg: msg number is too high");
×
96
   }
97
   m_default_read = msg;
3✔
98
}
3✔
99

100
/*
101
* Process a full message at once
102
*/
103
void Pipe::process_msg(const uint8_t input[], size_t length) {
39✔
104
   start_msg();
39✔
105
   write(input, length);
39✔
106
   end_msg();
39✔
107
}
39✔
108

109
/*
110
* Process a full message at once
111
*/
112
void Pipe::process_msg(const secure_vector<uint8_t>& input) {
2✔
113
   process_msg(input.data(), input.size());
2✔
114
}
2✔
115

116
void Pipe::process_msg(const std::vector<uint8_t>& input) {
1✔
117
   process_msg(input.data(), input.size());
1✔
118
}
1✔
119

120
/*
121
* Process a full message at once
122
*/
123
void Pipe::process_msg(std::string_view input) {
36✔
124
   process_msg(cast_char_ptr_to_uint8(input.data()), input.length());
36✔
125
}
36✔
126

127
/*
128
* Process a full message at once
129
*/
130
void Pipe::process_msg(DataSource& input) {
4✔
131
   start_msg();
4✔
132
   write(input);
4✔
133
   end_msg();
4✔
134
}
4✔
135

136
/*
137
* Start a new message
138
*/
139
void Pipe::start_msg() {
65✔
140
   if(m_inside_msg) {
65✔
141
      throw Invalid_State("Pipe::start_msg: Message was already started");
×
142
   }
143
   if(m_pipe == nullptr) {
65✔
144
      m_pipe = new Null_Filter;
2✔
145
   }
146
   find_endpoints(m_pipe);
65✔
147
   m_pipe->new_msg();
65✔
148
   m_inside_msg = true;
65✔
149
}
65✔
150

151
/*
152
* End the current message
153
*/
154
void Pipe::end_msg() {
65✔
155
   if(!m_inside_msg) {
65✔
156
      throw Invalid_State("Pipe::end_msg: Message was already ended");
×
157
   }
158
   m_pipe->finish_msg();
65✔
159
   clear_endpoints(m_pipe);
65✔
160
   if(dynamic_cast<Null_Filter*>(m_pipe)) {
65✔
161
      delete m_pipe;
2✔
162
      m_pipe = nullptr;
2✔
163
   }
164
   m_inside_msg = false;
65✔
165

166
   m_outputs->retire();
65✔
167
}
65✔
168

169
/*
170
* Find the endpoints of the Pipe
171
*/
172
void Pipe::find_endpoints(Filter* f) {
135✔
173
   for(size_t j = 0; j != f->total_ports(); ++j) {
277✔
174
      if(f->m_next[j] && !dynamic_cast<SecureQueue*>(f->m_next[j])) {
142✔
175
         find_endpoints(f->m_next[j]);
70✔
176
      } else {
177
         SecureQueue* q = new SecureQueue;
72✔
178
         f->m_next[j] = q;
72✔
179
         m_outputs->add(q);
72✔
180
      }
181
   }
182
}
135✔
183

184
/*
185
* Remove the SecureQueues attached to the Filter
186
*/
187
void Pipe::clear_endpoints(Filter* f) {
207✔
188
   if(!f) {
207✔
189
      return;
190
   }
191
   for(size_t j = 0; j != f->total_ports(); ++j) {
277✔
192
      if(f->m_next[j] && dynamic_cast<SecureQueue*>(f->m_next[j])) {
142✔
193
         f->m_next[j] = nullptr;
72✔
194
      }
195
      clear_endpoints(f->m_next[j]);
142✔
196
   }
197
}
198

199
void Pipe::append(Filter* filter) {
19✔
200
   do_append(filter);
19✔
201
}
17✔
202

203
void Pipe::append_filter(Filter* filter) {
4✔
204
   if(m_outputs->message_count() != 0) {
4✔
205
      throw Invalid_State("Cannot call Pipe::append_filter after start_msg");
2✔
206
   }
207

208
   do_append(filter);
2✔
209
}
2✔
210

211
void Pipe::prepend(Filter* filter) {
5✔
212
   do_prepend(filter);
5✔
213
}
3✔
214

215
void Pipe::prepend_filter(Filter* filter) {
4✔
216
   if(m_outputs->message_count() != 0) {
4✔
217
      throw Invalid_State("Cannot call Pipe::prepend_filter after start_msg");
2✔
218
   }
219

220
   do_prepend(filter);
2✔
221
}
2✔
222

223
/*
224
* Append a Filter to the Pipe
225
*/
226
void Pipe::do_append(Filter* filter) {
93✔
227
   if(!filter) {
93✔
228
      return;
229
   }
230
   if(dynamic_cast<SecureQueue*>(filter)) {
41✔
231
      throw Invalid_Argument("Pipe::append: SecureQueue cannot be used");
1✔
232
   }
233
   if(filter->m_owned) {
40✔
234
      throw Invalid_Argument("Filters cannot be shared among multiple Pipes");
×
235
   }
236

237
   if(m_inside_msg) {
40✔
238
      throw Invalid_State("Cannot append to a Pipe while it is processing");
1✔
239
   }
240

241
   filter->m_owned = true;
39✔
242

243
   if(!m_pipe) {
39✔
244
      m_pipe = filter;
25✔
245
   } else {
246
      m_pipe->attach(filter);
14✔
247
   }
248
}
249

250
/*
251
* Prepend a Filter to the Pipe
252
*/
253
void Pipe::do_prepend(Filter* filter) {
7✔
254
   if(m_inside_msg) {
7✔
255
      throw Invalid_State("Cannot prepend to a Pipe while it is processing");
1✔
256
   }
257
   if(!filter) {
6✔
258
      return;
259
   }
260
   if(dynamic_cast<SecureQueue*>(filter)) {
3✔
261
      throw Invalid_Argument("Pipe::prepend: SecureQueue cannot be used");
1✔
262
   }
263
   if(filter->m_owned) {
2✔
264
      throw Invalid_Argument("Filters cannot be shared among multiple Pipes");
×
265
   }
266

267
   filter->m_owned = true;
2✔
268

269
   if(m_pipe) {
2✔
270
      filter->attach(m_pipe);
×
271
   }
272
   m_pipe = filter;
2✔
273
}
274

275
/*
276
* Pop a Filter off the Pipe
277
*/
278
void Pipe::pop() {
10✔
279
   if(m_inside_msg) {
10✔
280
      throw Invalid_State("Cannot pop off a Pipe while it is processing");
1✔
281
   }
282

283
   if(!m_pipe) {
9✔
284
      return;
285
   }
286

287
   if(m_pipe->total_ports() > 1) {
7✔
288
      throw Invalid_State("Cannot pop off a Filter with multiple ports");
×
289
   }
290

291
   size_t to_remove = m_pipe->owns() + 1;
7✔
292

293
   while(to_remove--) {
16✔
294
      std::unique_ptr<Filter> to_destroy(m_pipe);
9✔
295
      m_pipe = m_pipe->m_next[0];
9✔
296
   }
9✔
297
}
298

299
/*
300
* Return the number of messages in this Pipe
301
*/
302
Pipe::message_id Pipe::message_count() const {
243✔
303
   return m_outputs->message_count();
243✔
304
}
305

306
/*
307
* Static Member Variables
308
*/
309
const Pipe::message_id Pipe::LAST_MESSAGE = static_cast<Pipe::message_id>(-2);
310

311
const Pipe::message_id Pipe::DEFAULT_MESSAGE = static_cast<Pipe::message_id>(-1);
312

313
}  // namespace Botan
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc