GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
// Copyright Joyent, Inc. and other Node contributors. |
||
2 |
// |
||
3 |
// Permission is hereby granted, free of charge, to any person obtaining a |
||
4 |
// copy of this software and associated documentation files (the |
||
5 |
// "Software"), to deal in the Software without restriction, including |
||
6 |
// without limitation the rights to use, copy, modify, merge, publish, |
||
7 |
// distribute, sublicense, and/or sell copies of the Software, and to permit |
||
8 |
// persons to whom the Software is furnished to do so, subject to the |
||
9 |
// following conditions: |
||
10 |
// |
||
11 |
// The above copyright notice and this permission notice shall be included |
||
12 |
// in all copies or substantial portions of the Software. |
||
13 |
// |
||
14 |
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
||
15 |
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||
16 |
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN |
||
17 |
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
||
18 |
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
||
19 |
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
||
20 |
// USE OR OTHER DEALINGS IN THE SOFTWARE. |
||
21 |
|||
22 |
#include "crypto/crypto_bio.h" |
||
23 |
#include "base_object-inl.h" |
||
24 |
#include "memory_tracker-inl.h" |
||
25 |
#include "util-inl.h" |
||
26 |
|||
27 |
#include <openssl/bio.h> |
||
28 |
|||
29 |
#include <climits> |
||
30 |
#include <cstring> |
||
31 |
|||
32 |
namespace node { |
||
33 |
namespace crypto { |
||
34 |
|||
35 |
67561 |
BIOPointer NodeBIO::New(Environment* env) { |
|
36 |
67561 |
BIOPointer bio(BIO_new(GetMethod())); |
|
37 |
✓✗✓✓ ✓✓ |
67561 |
if (bio && env != nullptr) |
38 |
24810 |
NodeBIO::FromBIO(bio.get())->env_ = env; |
|
39 |
67561 |
return bio; |
|
40 |
} |
||
41 |
|||
42 |
|||
43 |
42751 |
BIOPointer NodeBIO::NewFixed(const char* data, size_t len, Environment* env) { |
|
44 |
85502 |
BIOPointer bio = New(env); |
|
45 |
|||
46 |
✓✗ | 85502 |
if (!bio || |
47 |
42751 |
len > INT_MAX || |
|
48 |
✓✗✓✗ ✗✓✗✓ |
128253 |
BIO_write(bio.get(), data, len) != static_cast<int>(len) || |
49 |
42751 |
BIO_set_mem_eof_return(bio.get(), 0) != 1) { |
|
50 |
return BIOPointer(); |
||
51 |
} |
||
52 |
|||
53 |
42751 |
return bio; |
|
54 |
} |
||
55 |
|||
56 |
|||
57 |
67561 |
int NodeBIO::New(BIO* bio) { |
|
58 |
67561 |
BIO_set_data(bio, new NodeBIO()); |
|
59 |
67561 |
BIO_set_init(bio, 1); |
|
60 |
|||
61 |
67561 |
return 1; |
|
62 |
} |
||
63 |
|||
64 |
|||
65 |
67551 |
int NodeBIO::Free(BIO* bio) { |
|
66 |
✗✓ | 67551 |
if (bio == nullptr) |
67 |
return 0; |
||
68 |
|||
69 |
✓✗ | 67551 |
if (BIO_get_shutdown(bio)) { |
70 |
✓✗✓✗ ✓✗ |
67551 |
if (BIO_get_init(bio) && BIO_get_data(bio) != nullptr) { |
71 |
✓✗ | 67551 |
delete FromBIO(bio); |
72 |
67551 |
BIO_set_data(bio, nullptr); |
|
73 |
} |
||
74 |
} |
||
75 |
|||
76 |
67551 |
return 1; |
|
77 |
} |
||
78 |
|||
79 |
|||
80 |
37079 |
int NodeBIO::Read(BIO* bio, char* out, int len) { |
|
81 |
37079 |
BIO_clear_retry_flags(bio); |
|
82 |
|||
83 |
37079 |
NodeBIO* nbio = FromBIO(bio); |
|
84 |
37079 |
int bytes = nbio->Read(out, len); |
|
85 |
|||
86 |
✓✓ | 37079 |
if (bytes == 0) { |
87 |
7816 |
bytes = nbio->eof_return(); |
|
88 |
✓✓ | 7816 |
if (bytes != 0) { |
89 |
7814 |
BIO_set_retry_read(bio); |
|
90 |
} |
||
91 |
} |
||
92 |
|||
93 |
37079 |
return bytes; |
|
94 |
} |
||
95 |
|||
96 |
|||
97 |
20 |
char* NodeBIO::Peek(size_t* size) { |
|
98 |
20 |
*size = read_head_->write_pos_ - read_head_->read_pos_; |
|
99 |
20 |
return read_head_->data_ + read_head_->read_pos_; |
|
100 |
} |
||
101 |
|||
102 |
|||
103 |
7548 |
size_t NodeBIO::PeekMultiple(char** out, size_t* size, size_t* count) { |
|
104 |
7548 |
Buffer* pos = read_head_; |
|
105 |
7548 |
size_t max = *count; |
|
106 |
7548 |
size_t total = 0; |
|
107 |
|||
108 |
size_t i; |
||
109 |
✓✗ | 7681 |
for (i = 0; i < max; i++) { |
110 |
7681 |
size[i] = pos->write_pos_ - pos->read_pos_; |
|
111 |
7681 |
total += size[i]; |
|
112 |
7681 |
out[i] = pos->data_ + pos->read_pos_; |
|
113 |
|||
114 |
/* Don't get past write head */ |
||
115 |
✓✓ | 7681 |
if (pos == write_head_) |
116 |
7548 |
break; |
|
117 |
else |
||
118 |
133 |
pos = pos->next_; |
|
119 |
} |
||
120 |
|||
121 |
✗✓ | 7548 |
if (i == max) |
122 |
*count = i; |
||
123 |
else |
||
124 |
7548 |
*count = i + 1; |
|
125 |
|||
126 |
7548 |
return total; |
|
127 |
} |
||
128 |
|||
129 |
|||
130 |
53194 |
int NodeBIO::Write(BIO* bio, const char* data, int len) { |
|
131 |
53194 |
BIO_clear_retry_flags(bio); |
|
132 |
|||
133 |
53194 |
FromBIO(bio)->Write(data, len); |
|
134 |
|||
135 |
53194 |
return len; |
|
136 |
} |
||
137 |
|||
138 |
|||
139 |
int NodeBIO::Puts(BIO* bio, const char* str) { |
||
140 |
return Write(bio, str, strlen(str)); |
||
141 |
} |
||
142 |
|||
143 |
|||
144 |
988538 |
int NodeBIO::Gets(BIO* bio, char* out, int size) { |
|
145 |
988538 |
NodeBIO* nbio = FromBIO(bio); |
|
146 |
|||
147 |
✓✓ | 988538 |
if (nbio->Length() == 0) |
148 |
1575 |
return 0; |
|
149 |
|||
150 |
986963 |
int i = nbio->IndexOf('\n', size); |
|
151 |
|||
152 |
// Include '\n', if it's there. If not, don't read off the end. |
||
153 |
✓✗✓✗ ✓✓✓✓ |
986963 |
if (i < size && i >= 0 && static_cast<size_t>(i) < nbio->Length()) |
154 |
946776 |
i++; |
|
155 |
|||
156 |
// Shift `i` a bit to nullptr-terminate string later |
||
157 |
✗✓ | 986963 |
if (size == i) |
158 |
i--; |
||
159 |
|||
160 |
// Flush read data |
||
161 |
986963 |
nbio->Read(out, i); |
|
162 |
|||
163 |
986963 |
out[i] = 0; |
|
164 |
|||
165 |
986963 |
return i; |
|
166 |
} |
||
167 |
|||
168 |
|||
169 |
78015 |
long NodeBIO::Ctrl(BIO* bio, int cmd, long num, // NOLINT(runtime/int) |
|
170 |
void* ptr) { |
||
171 |
NodeBIO* nbio; |
||
172 |
long ret; // NOLINT(runtime/int) |
||
173 |
|||
174 |
78015 |
nbio = FromBIO(bio); |
|
175 |
78015 |
ret = 1; |
|
176 |
|||
177 |
✗✓✓✗ ✗✗✗✗ ✗✓✓✓ |
78015 |
switch (cmd) { |
178 |
case BIO_CTRL_RESET: |
||
179 |
nbio->Reset(); |
||
180 |
break; |
||
181 |
32 |
case BIO_CTRL_EOF: |
|
182 |
32 |
ret = nbio->Length() == 0; |
|
183 |
32 |
break; |
|
184 |
42751 |
case BIO_C_SET_BUF_MEM_EOF_RETURN: |
|
185 |
42751 |
nbio->set_eof_return(num); |
|
186 |
42751 |
break; |
|
187 |
case BIO_CTRL_INFO: |
||
188 |
ret = nbio->Length(); |
||
189 |
if (ptr != nullptr) |
||
190 |
*reinterpret_cast<void**>(ptr) = nullptr; |
||
191 |
break; |
||
192 |
case BIO_C_SET_BUF_MEM: |
||
193 |
CHECK(0 && "Can't use SET_BUF_MEM_PTR with NodeBIO"); |
||
194 |
break; |
||
195 |
case BIO_C_GET_BUF_MEM_PTR: |
||
196 |
CHECK(0 && "Can't use GET_BUF_MEM_PTR with NodeBIO"); |
||
197 |
ret = 0; |
||
198 |
break; |
||
199 |
case BIO_CTRL_GET_CLOSE: |
||
200 |
ret = BIO_get_shutdown(bio); |
||
201 |
break; |
||
202 |
case BIO_CTRL_SET_CLOSE: |
||
203 |
BIO_set_shutdown(bio, num); |
||
204 |
break; |
||
205 |
case BIO_CTRL_WPENDING: |
||
206 |
ret = 0; |
||
207 |
break; |
||
208 |
17036 |
case BIO_CTRL_PENDING: |
|
209 |
17036 |
ret = nbio->Length(); |
|
210 |
17036 |
break; |
|
211 |
6121 |
case BIO_CTRL_DUP: |
|
212 |
case BIO_CTRL_FLUSH: |
||
213 |
6121 |
ret = 1; |
|
214 |
6121 |
break; |
|
215 |
12075 |
case BIO_CTRL_PUSH: |
|
216 |
case BIO_CTRL_POP: |
||
217 |
default: |
||
218 |
12075 |
ret = 0; |
|
219 |
12075 |
break; |
|
220 |
} |
||
221 |
78015 |
return ret; |
|
222 |
} |
||
223 |
|||
224 |
|||
225 |
67561 |
const BIO_METHOD* NodeBIO::GetMethod() { |
|
226 |
// Static initialization ensures that this is safe to use concurrently. |
||
227 |
288 |
static const BIO_METHOD* method = [&]() { |
|
228 |
288 |
BIO_METHOD* method = BIO_meth_new(BIO_TYPE_MEM, "node.js SSL buffer"); |
|
229 |
288 |
BIO_meth_set_write(method, Write); |
|
230 |
288 |
BIO_meth_set_read(method, Read); |
|
231 |
288 |
BIO_meth_set_puts(method, Puts); |
|
232 |
288 |
BIO_meth_set_gets(method, Gets); |
|
233 |
288 |
BIO_meth_set_ctrl(method, Ctrl); |
|
234 |
288 |
BIO_meth_set_create(method, New); |
|
235 |
288 |
BIO_meth_set_destroy(method, Free); |
|
236 |
288 |
return method; |
|
237 |
✓✓✓✗ |
67561 |
}(); |
238 |
|||
239 |
67561 |
return method; |
|
240 |
} |
||
241 |
|||
242 |
|||
243 |
1080557 |
void NodeBIO::TryMoveReadHead() { |
|
244 |
// `read_pos_` and `write_pos_` means the position of the reader and writer |
||
245 |
// inside the buffer, respectively. When they're equal - its safe to reset |
||
246 |
// them, because both reader and writer will continue doing their stuff |
||
247 |
// from new (zero) positions. |
||
248 |
✓✓ | 1080557 |
while (read_head_->read_pos_ != 0 && |
249 |
✓✓ | 1023718 |
read_head_->read_pos_ == read_head_->write_pos_) { |
250 |
// Reset positions |
||
251 |
55995 |
read_head_->read_pos_ = 0; |
|
252 |
55995 |
read_head_->write_pos_ = 0; |
|
253 |
|||
254 |
// Move read_head_ forward, just in case if there're still some data to |
||
255 |
// read in the next buffer. |
||
256 |
✓✓ | 55995 |
if (read_head_ != write_head_) |
257 |
320 |
read_head_ = read_head_->next_; |
|
258 |
} |
||
259 |
1024562 |
} |
|
260 |
|||
261 |
|||
262 |
1031409 |
size_t NodeBIO::Read(char* out, size_t size) { |
|
263 |
1031409 |
size_t bytes_read = 0; |
|
264 |
✓✓ | 1031409 |
size_t expected = Length() > size ? size : Length(); |
265 |
1031409 |
size_t offset = 0; |
|
266 |
1031409 |
size_t left = size; |
|
267 |
|||
268 |
✓✓ | 2055127 |
while (bytes_read < expected) { |
269 |
✗✓ | 1023718 |
CHECK_LE(read_head_->read_pos_, read_head_->write_pos_); |
270 |
1023718 |
size_t avail = read_head_->write_pos_ - read_head_->read_pos_; |
|
271 |
✓✓ | 1023718 |
if (avail > left) |
272 |
967723 |
avail = left; |
|
273 |
|||
274 |
// Copy data |
||
275 |
✓✓ | 1023718 |
if (out != nullptr) |
276 |
1016226 |
memcpy(out + offset, read_head_->data_ + read_head_->read_pos_, avail); |
|
277 |
1023718 |
read_head_->read_pos_ += avail; |
|
278 |
|||
279 |
// Move pointers |
||
280 |
1023718 |
bytes_read += avail; |
|
281 |
1023718 |
offset += avail; |
|
282 |
1023718 |
left -= avail; |
|
283 |
|||
284 |
1023718 |
TryMoveReadHead(); |
|
285 |
} |
||
286 |
✗✓ | 1031409 |
CHECK_EQ(expected, bytes_read); |
287 |
1031409 |
length_ -= bytes_read; |
|
288 |
|||
289 |
// Free all empty buffers, but write_head's child |
||
290 |
1031409 |
FreeEmpty(); |
|
291 |
|||
292 |
1031409 |
return bytes_read; |
|
293 |
} |
||
294 |
|||
295 |
|||
296 |
1031409 |
void NodeBIO::FreeEmpty() { |
|
297 |
✓✓ | 1031409 |
if (write_head_ == nullptr) |
298 |
1031408 |
return; |
|
299 |
1029642 |
Buffer* child = write_head_->next_; |
|
300 |
✓✓✓✓ |
1029642 |
if (child == write_head_ || child == read_head_) |
301 |
1024473 |
return; |
|
302 |
5169 |
Buffer* cur = child->next_; |
|
303 |
✓✓✗✓ |
5169 |
if (cur == write_head_ || cur == read_head_) |
304 |
5168 |
return; |
|
305 |
|||
306 |
1 |
Buffer* prev = child; |
|
307 |
✓✓ | 2 |
while (cur != read_head_) { |
308 |
✗✓ | 1 |
CHECK_NE(cur, write_head_); |
309 |
✗✓ | 1 |
CHECK_EQ(cur->write_pos_, cur->read_pos_); |
310 |
|||
311 |
1 |
Buffer* next = cur->next_; |
|
312 |
✓✗ | 1 |
delete cur; |
313 |
1 |
cur = next; |
|
314 |
} |
||
315 |
1 |
prev->next_ = cur; |
|
316 |
} |
||
317 |
|||
318 |
|||
319 |
986963 |
size_t NodeBIO::IndexOf(char delim, size_t limit) { |
|
320 |
986963 |
size_t bytes_read = 0; |
|
321 |
✓✓ | 986963 |
size_t max = Length() > limit ? limit : Length(); |
322 |
986963 |
size_t left = limit; |
|
323 |
986963 |
Buffer* current = read_head_; |
|
324 |
|||
325 |
✓✓ | 1027150 |
while (bytes_read < max) { |
326 |
✗✓ | 986963 |
CHECK_LE(current->read_pos_, current->write_pos_); |
327 |
986963 |
size_t avail = current->write_pos_ - current->read_pos_; |
|
328 |
✓✓ | 986963 |
if (avail > left) |
329 |
810515 |
avail = left; |
|
330 |
|||
331 |
// Walk through data |
||
332 |
986963 |
char* tmp = current->data_ + current->read_pos_; |
|
333 |
986963 |
size_t off = 0; |
|
334 |
✓✓✓✓ |
65990222 |
while (off < avail && *tmp != delim) { |
335 |
65003259 |
off++; |
|
336 |
65003259 |
tmp++; |
|
337 |
} |
||
338 |
|||
339 |
// Move pointers |
||
340 |
986963 |
bytes_read += off; |
|
341 |
986963 |
left -= off; |
|
342 |
|||
343 |
// Found `delim` |
||
344 |
✓✓ | 986963 |
if (off != avail) { |
345 |
946776 |
return bytes_read; |
|
346 |
} |
||
347 |
|||
348 |
// Move to next buffer |
||
349 |
✓✓ | 40187 |
if (current->read_pos_ + avail == current->len_) { |
350 |
31285 |
current = current->next_; |
|
351 |
} |
||
352 |
} |
||
353 |
✗✓ | 40187 |
CHECK_EQ(max, bytes_read); |
354 |
|||
355 |
40187 |
return max; |
|
356 |
} |
||
357 |
|||
358 |
|||
359 |
53194 |
void NodeBIO::Write(const char* data, size_t size) { |
|
360 |
53194 |
size_t offset = 0; |
|
361 |
53194 |
size_t left = size; |
|
362 |
|||
363 |
// Allocate initial buffer if the ring is empty |
||
364 |
53194 |
TryAllocateForWrite(left); |
|
365 |
|||
366 |
✓✓ | 106523 |
while (left > 0) { |
367 |
53329 |
size_t to_write = left; |
|
368 |
✗✓ | 53329 |
CHECK_LE(write_head_->write_pos_, write_head_->len_); |
369 |
53329 |
size_t avail = write_head_->len_ - write_head_->write_pos_; |
|
370 |
|||
371 |
✓✓ | 53329 |
if (to_write > avail) |
372 |
135 |
to_write = avail; |
|
373 |
|||
374 |
// Copy data |
||
375 |
53329 |
memcpy(write_head_->data_ + write_head_->write_pos_, |
|
376 |
53329 |
data + offset, |
|
377 |
to_write); |
||
378 |
|||
379 |
// Move pointers |
||
380 |
53329 |
left -= to_write; |
|
381 |
53329 |
offset += to_write; |
|
382 |
53329 |
length_ += to_write; |
|
383 |
53329 |
write_head_->write_pos_ += to_write; |
|
384 |
✗✓ | 53329 |
CHECK_LE(write_head_->write_pos_, write_head_->len_); |
385 |
|||
386 |
// Go to next buffer if there still are some bytes to write |
||
387 |
✓✓ | 53329 |
if (left != 0) { |
388 |
✗✓ | 135 |
CHECK_EQ(write_head_->write_pos_, write_head_->len_); |
389 |
135 |
TryAllocateForWrite(left); |
|
390 |
135 |
write_head_ = write_head_->next_; |
|
391 |
|||
392 |
// Additionally, since we're moved to the next buffer, read head |
||
393 |
// may be moved as well. |
||
394 |
135 |
TryMoveReadHead(); |
|
395 |
} |
||
396 |
} |
||
397 |
✗✓ | 53194 |
CHECK_EQ(left, 0); |
398 |
53194 |
} |
|
399 |
|||
400 |
|||
401 |
6714 |
char* NodeBIO::PeekWritable(size_t* size) { |
|
402 |
6714 |
TryAllocateForWrite(*size); |
|
403 |
|||
404 |
6714 |
size_t available = write_head_->len_ - write_head_->write_pos_; |
|
405 |
✓✗✓✓ |
6714 |
if (*size == 0 || available <= *size) |
406 |
6671 |
*size = available; |
|
407 |
|||
408 |
6714 |
return write_head_->data_ + write_head_->write_pos_; |
|
409 |
} |
||
410 |
|||
411 |
|||
412 |
6405 |
void NodeBIO::Commit(size_t size) { |
|
413 |
6405 |
write_head_->write_pos_ += size; |
|
414 |
6405 |
length_ += size; |
|
415 |
✗✓ | 6405 |
CHECK_LE(write_head_->write_pos_, write_head_->len_); |
416 |
|||
417 |
// Allocate new buffer if write head is full, |
||
418 |
// and there're no other place to go |
||
419 |
6405 |
TryAllocateForWrite(0); |
|
420 |
✓✓ | 6405 |
if (write_head_->write_pos_ == write_head_->len_) { |
421 |
709 |
write_head_ = write_head_->next_; |
|
422 |
|||
423 |
// Additionally, since we're moved to the next buffer, read head |
||
424 |
// may be moved as well. |
||
425 |
709 |
TryMoveReadHead(); |
|
426 |
} |
||
427 |
6405 |
} |
|
428 |
|||
429 |
|||
430 |
66448 |
void NodeBIO::TryAllocateForWrite(size_t hint) { |
|
431 |
66448 |
Buffer* w = write_head_; |
|
432 |
66448 |
Buffer* r = read_head_; |
|
433 |
// If write head is full, next buffer is either read head or not empty. |
||
434 |
✓✓ | 66448 |
if (w == nullptr || |
435 |
✓✓ | 19012 |
(w->write_pos_ == w->len_ && |
436 |
✓✓✗✓ |
846 |
(w->next_ == r || w->next_->write_pos_ != 0))) { |
437 |
✓✓ | 48099 |
size_t len = w == nullptr ? initial_ : |
438 |
kThroughputBufferLength; |
||
439 |
✓✓ | 48099 |
if (len < hint) |
440 |
36823 |
len = hint; |
|
441 |
|||
442 |
// If there is a one time allocation size hint, use it. |
||
443 |
✓✓ | 48099 |
if (allocate_hint_ > len) { |
444 |
23 |
len = allocate_hint_; |
|
445 |
23 |
allocate_hint_ = 0; |
|
446 |
} |
||
447 |
|||
448 |
48099 |
Buffer* next = new Buffer(env_, len); |
|
449 |
|||
450 |
✓✓ | 48099 |
if (w == nullptr) { |
451 |
47436 |
next->next_ = next; |
|
452 |
47436 |
write_head_ = next; |
|
453 |
47436 |
read_head_ = next; |
|
454 |
} else { |
||
455 |
663 |
next->next_ = w->next_; |
|
456 |
663 |
w->next_ = next; |
|
457 |
} |
||
458 |
} |
||
459 |
66448 |
} |
|
460 |
|||
461 |
|||
462 |
void NodeBIO::Reset() { |
||
463 |
if (read_head_ == nullptr) |
||
464 |
return; |
||
465 |
|||
466 |
while (read_head_->read_pos_ != read_head_->write_pos_) { |
||
467 |
CHECK(read_head_->write_pos_ > read_head_->read_pos_); |
||
468 |
|||
469 |
length_ -= read_head_->write_pos_ - read_head_->read_pos_; |
||
470 |
read_head_->write_pos_ = 0; |
||
471 |
read_head_->read_pos_ = 0; |
||
472 |
|||
473 |
read_head_ = read_head_->next_; |
||
474 |
} |
||
475 |
write_head_ = read_head_; |
||
476 |
CHECK_EQ(length_, 0); |
||
477 |
} |
||
478 |
|||
479 |
|||
480 |
✓✓ | 270204 |
NodeBIO::~NodeBIO() { |
481 |
✓✓ | 135102 |
if (read_head_ == nullptr) |
482 |
40250 |
return; |
|
483 |
|||
484 |
94852 |
Buffer* current = read_head_; |
|
485 |
1318 |
do { |
|
486 |
96170 |
Buffer* next = current->next_; |
|
487 |
✓✗ | 96170 |
delete current; |
488 |
96170 |
current = next; |
|
489 |
✓✓ | 96170 |
} while (current != read_head_); |
490 |
|||
491 |
94852 |
read_head_ = nullptr; |
|
492 |
94852 |
write_head_ = nullptr; |
|
493 |
270204 |
} |
|
494 |
|||
495 |
|||
496 |
1291592 |
NodeBIO* NodeBIO::FromBIO(BIO* bio) { |
|
497 |
✗✓ | 1291592 |
CHECK_NOT_NULL(BIO_get_data(bio)); |
498 |
1291592 |
return static_cast<NodeBIO*>(BIO_get_data(bio)); |
|
499 |
} |
||
500 |
|||
501 |
|||
502 |
} // namespace crypto |
||
503 |
} // namespace node |
Generated by: GCOVR (Version 4.2) |