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 |
62995 |
BIOPointer NodeBIO::New(Environment* env) { |
|
36 |
62995 |
BIOPointer bio(BIO_new(GetMethod())); |
|
37 |
✓✗✓✓ ✓✓ |
62995 |
if (bio && env != nullptr) |
38 |
24798 |
NodeBIO::FromBIO(bio.get())->env_ = env; |
|
39 |
62995 |
return bio; |
|
40 |
} |
||
41 |
|||
42 |
|||
43 |
38197 |
BIOPointer NodeBIO::NewFixed(const char* data, size_t len, Environment* env) { |
|
44 |
76394 |
BIOPointer bio = New(env); |
|
45 |
|||
46 |
✓✗ | 76394 |
if (!bio || |
47 |
38197 |
len > INT_MAX || |
|
48 |
✓✗✓✗ ✗✓✗✓ |
114591 |
BIO_write(bio.get(), data, len) != static_cast<int>(len) || |
49 |
38197 |
BIO_set_mem_eof_return(bio.get(), 0) != 1) { |
|
50 |
return BIOPointer(); |
||
51 |
} |
||
52 |
|||
53 |
38197 |
return bio; |
|
54 |
} |
||
55 |
|||
56 |
|||
57 |
62995 |
int NodeBIO::New(BIO* bio) { |
|
58 |
62995 |
BIO_set_data(bio, new NodeBIO()); |
|
59 |
62995 |
BIO_set_init(bio, 1); |
|
60 |
|||
61 |
62995 |
return 1; |
|
62 |
} |
||
63 |
|||
64 |
|||
65 |
62985 |
int NodeBIO::Free(BIO* bio) { |
|
66 |
✗✓ | 62985 |
if (bio == nullptr) |
67 |
return 0; |
||
68 |
|||
69 |
✓✗ | 62985 |
if (BIO_get_shutdown(bio)) { |
70 |
✓✗✓✗ ✓✗ |
62985 |
if (BIO_get_init(bio) && BIO_get_data(bio) != nullptr) { |
71 |
✓✗ | 62985 |
delete FromBIO(bio); |
72 |
62985 |
BIO_set_data(bio, nullptr); |
|
73 |
} |
||
74 |
} |
||
75 |
|||
76 |
62985 |
return 1; |
|
77 |
} |
||
78 |
|||
79 |
|||
80 |
36869 |
int NodeBIO::Read(BIO* bio, char* out, int len) { |
|
81 |
36869 |
BIO_clear_retry_flags(bio); |
|
82 |
|||
83 |
36869 |
NodeBIO* nbio = FromBIO(bio); |
|
84 |
36869 |
int bytes = nbio->Read(out, len); |
|
85 |
|||
86 |
✓✓ | 36869 |
if (bytes == 0) { |
87 |
7789 |
bytes = nbio->eof_return(); |
|
88 |
✓✓ | 7789 |
if (bytes != 0) { |
89 |
7787 |
BIO_set_retry_read(bio); |
|
90 |
} |
||
91 |
} |
||
92 |
|||
93 |
36869 |
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 |
7661 |
size_t NodeBIO::PeekMultiple(char** out, size_t* size, size_t* count) { |
|
104 |
7661 |
Buffer* pos = read_head_; |
|
105 |
7661 |
size_t max = *count; |
|
106 |
7661 |
size_t total = 0; |
|
107 |
|||
108 |
size_t i; |
||
109 |
✓✗ | 7797 |
for (i = 0; i < max; i++) { |
110 |
7797 |
size[i] = pos->write_pos_ - pos->read_pos_; |
|
111 |
7797 |
total += size[i]; |
|
112 |
7797 |
out[i] = pos->data_ + pos->read_pos_; |
|
113 |
|||
114 |
/* Don't get past write head */ |
||
115 |
✓✓ | 7797 |
if (pos == write_head_) |
116 |
7661 |
break; |
|
117 |
else |
||
118 |
136 |
pos = pos->next_; |
|
119 |
} |
||
120 |
|||
121 |
✗✓ | 7661 |
if (i == max) |
122 |
*count = i; |
||
123 |
else |
||
124 |
7661 |
*count = i + 1; |
|
125 |
|||
126 |
7661 |
return total; |
|
127 |
} |
||
128 |
|||
129 |
|||
130 |
48988 |
int NodeBIO::Write(BIO* bio, const char* data, int len) { |
|
131 |
48988 |
BIO_clear_retry_flags(bio); |
|
132 |
|||
133 |
48988 |
FromBIO(bio)->Write(data, len); |
|
134 |
|||
135 |
48988 |
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 |
870850 |
int NodeBIO::Gets(BIO* bio, char* out, int size) { |
|
145 |
870850 |
NodeBIO* nbio = FromBIO(bio); |
|
146 |
|||
147 |
✓✓ | 870850 |
if (nbio->Length() == 0) |
148 |
1572 |
return 0; |
|
149 |
|||
150 |
869278 |
int i = nbio->IndexOf('\n', size); |
|
151 |
|||
152 |
// Include '\n', if it's there. If not, don't read off the end. |
||
153 |
✓✗✓✗ ✓✓✓✓ |
869278 |
if (i < size && i >= 0 && static_cast<size_t>(i) < nbio->Length()) |
154 |
833639 |
i++; |
|
155 |
|||
156 |
// Shift `i` a bit to nullptr-terminate string later |
||
157 |
✗✓ | 869278 |
if (size == i) |
158 |
i--; |
||
159 |
|||
160 |
// Flush read data |
||
161 |
869278 |
nbio->Read(out, i); |
|
162 |
|||
163 |
869278 |
out[i] = 0; |
|
164 |
|||
165 |
869278 |
return i; |
|
166 |
} |
||
167 |
|||
168 |
|||
169 |
73596 |
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 |
73596 |
nbio = FromBIO(bio); |
|
175 |
73596 |
ret = 1; |
|
176 |
|||
177 |
✗✓✓✗ ✗✗✗✗ ✗✓✓✓ |
73596 |
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 |
38197 |
case BIO_C_SET_BUF_MEM_EOF_RETURN: |
|
185 |
38197 |
nbio->set_eof_return(num); |
|
186 |
38197 |
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 |
17253 |
case BIO_CTRL_PENDING: |
|
209 |
17253 |
ret = nbio->Length(); |
|
210 |
17253 |
break; |
|
211 |
6105 |
case BIO_CTRL_DUP: |
|
212 |
case BIO_CTRL_FLUSH: |
||
213 |
6105 |
ret = 1; |
|
214 |
6105 |
break; |
|
215 |
12009 |
case BIO_CTRL_PUSH: |
|
216 |
case BIO_CTRL_POP: |
||
217 |
default: |
||
218 |
12009 |
ret = 0; |
|
219 |
12009 |
break; |
|
220 |
} |
||
221 |
73596 |
return ret; |
|
222 |
} |
||
223 |
|||
224 |
|||
225 |
68343 |
const BIO_METHOD* NodeBIO::GetMethod() { |
|
226 |
// This is called from InitCryptoOnce() to avoid race conditions during |
||
227 |
// initialization. |
||
228 |
static BIO_METHOD* method = nullptr; |
||
229 |
|||
230 |
✓✓ | 68343 |
if (method == nullptr) { |
231 |
5348 |
method = BIO_meth_new(BIO_TYPE_MEM, "node.js SSL buffer"); |
|
232 |
5348 |
BIO_meth_set_write(method, Write); |
|
233 |
5348 |
BIO_meth_set_read(method, Read); |
|
234 |
5348 |
BIO_meth_set_puts(method, Puts); |
|
235 |
5348 |
BIO_meth_set_gets(method, Gets); |
|
236 |
5348 |
BIO_meth_set_ctrl(method, Ctrl); |
|
237 |
5348 |
BIO_meth_set_create(method, New); |
|
238 |
5348 |
BIO_meth_set_destroy(method, Free); |
|
239 |
} |
||
240 |
|||
241 |
68343 |
return method; |
|
242 |
} |
||
243 |
|||
244 |
|||
245 |
958355 |
void NodeBIO::TryMoveReadHead() { |
|
246 |
// `read_pos_` and `write_pos_` means the position of the reader and writer |
||
247 |
// inside the buffer, respectively. When they're equal - its safe to reset |
||
248 |
// them, because both reader and writer will continue doing their stuff |
||
249 |
// from new (zero) positions. |
||
250 |
✓✓ | 958355 |
while (read_head_->read_pos_ != 0 && |
251 |
✓✓ | 905962 |
read_head_->read_pos_ == read_head_->write_pos_) { |
252 |
// Reset positions |
||
253 |
51535 |
read_head_->read_pos_ = 0; |
|
254 |
51535 |
read_head_->write_pos_ = 0; |
|
255 |
|||
256 |
// Move read_head_ forward, just in case if there're still some data to |
||
257 |
// read in the next buffer. |
||
258 |
✓✓ | 51535 |
if (read_head_ != write_head_) |
259 |
332 |
read_head_ = read_head_->next_; |
|
260 |
} |
||
261 |
906820 |
} |
|
262 |
|||
263 |
|||
264 |
913624 |
size_t NodeBIO::Read(char* out, size_t size) { |
|
265 |
913624 |
size_t bytes_read = 0; |
|
266 |
✓✓ | 913624 |
size_t expected = Length() > size ? size : Length(); |
267 |
913624 |
size_t offset = 0; |
|
268 |
913624 |
size_t left = size; |
|
269 |
|||
270 |
✓✓ | 1819586 |
while (bytes_read < expected) { |
271 |
✗✓ | 905962 |
CHECK_LE(read_head_->read_pos_, read_head_->write_pos_); |
272 |
905962 |
size_t avail = read_head_->write_pos_ - read_head_->read_pos_; |
|
273 |
✓✓ | 905962 |
if (avail > left) |
274 |
854427 |
avail = left; |
|
275 |
|||
276 |
// Copy data |
||
277 |
✓✓ | 905962 |
if (out != nullptr) |
278 |
898358 |
memcpy(out + offset, read_head_->data_ + read_head_->read_pos_, avail); |
|
279 |
905962 |
read_head_->read_pos_ += avail; |
|
280 |
|||
281 |
// Move pointers |
||
282 |
905962 |
bytes_read += avail; |
|
283 |
905962 |
offset += avail; |
|
284 |
905962 |
left -= avail; |
|
285 |
|||
286 |
905962 |
TryMoveReadHead(); |
|
287 |
} |
||
288 |
✗✓ | 913624 |
CHECK_EQ(expected, bytes_read); |
289 |
913624 |
length_ -= bytes_read; |
|
290 |
|||
291 |
// Free all empty buffers, but write_head's child |
||
292 |
913624 |
FreeEmpty(); |
|
293 |
|||
294 |
913624 |
return bytes_read; |
|
295 |
} |
||
296 |
|||
297 |
|||
298 |
913624 |
void NodeBIO::FreeEmpty() { |
|
299 |
✓✓ | 913624 |
if (write_head_ == nullptr) |
300 |
913623 |
return; |
|
301 |
911863 |
Buffer* child = write_head_->next_; |
|
302 |
✓✓✓✓ |
911863 |
if (child == write_head_ || child == read_head_) |
303 |
906587 |
return; |
|
304 |
5276 |
Buffer* cur = child->next_; |
|
305 |
✓✓✗✓ |
5276 |
if (cur == write_head_ || cur == read_head_) |
306 |
5275 |
return; |
|
307 |
|||
308 |
1 |
Buffer* prev = child; |
|
309 |
✓✓ | 2 |
while (cur != read_head_) { |
310 |
✗✓ | 1 |
CHECK_NE(cur, write_head_); |
311 |
✗✓ | 1 |
CHECK_EQ(cur->write_pos_, cur->read_pos_); |
312 |
|||
313 |
1 |
Buffer* next = cur->next_; |
|
314 |
✓✗ | 1 |
delete cur; |
315 |
1 |
cur = next; |
|
316 |
} |
||
317 |
1 |
prev->next_ = cur; |
|
318 |
} |
||
319 |
|||
320 |
|||
321 |
869278 |
size_t NodeBIO::IndexOf(char delim, size_t limit) { |
|
322 |
869278 |
size_t bytes_read = 0; |
|
323 |
✓✓ | 869278 |
size_t max = Length() > limit ? limit : Length(); |
324 |
869278 |
size_t left = limit; |
|
325 |
869278 |
Buffer* current = read_head_; |
|
326 |
|||
327 |
✓✓ | 904917 |
while (bytes_read < max) { |
328 |
✗✓ | 869278 |
CHECK_LE(current->read_pos_, current->write_pos_); |
329 |
869278 |
size_t avail = current->write_pos_ - current->read_pos_; |
|
330 |
✓✓ | 869278 |
if (avail > left) |
331 |
711726 |
avail = left; |
|
332 |
|||
333 |
// Walk through data |
||
334 |
869278 |
char* tmp = current->data_ + current->read_pos_; |
|
335 |
869278 |
size_t off = 0; |
|
336 |
✓✓✓✓ |
58153483 |
while (off < avail && *tmp != delim) { |
337 |
57284205 |
off++; |
|
338 |
57284205 |
tmp++; |
|
339 |
} |
||
340 |
|||
341 |
// Move pointers |
||
342 |
869278 |
bytes_read += off; |
|
343 |
869278 |
left -= off; |
|
344 |
|||
345 |
// Found `delim` |
||
346 |
✓✓ | 869278 |
if (off != avail) { |
347 |
833639 |
return bytes_read; |
|
348 |
} |
||
349 |
|||
350 |
// Move to next buffer |
||
351 |
✓✓ | 35639 |
if (current->read_pos_ + avail == current->len_) { |
352 |
28834 |
current = current->next_; |
|
353 |
} |
||
354 |
} |
||
355 |
✗✓ | 35639 |
CHECK_EQ(max, bytes_read); |
356 |
|||
357 |
35639 |
return max; |
|
358 |
} |
||
359 |
|||
360 |
|||
361 |
48988 |
void NodeBIO::Write(const char* data, size_t size) { |
|
362 |
48988 |
size_t offset = 0; |
|
363 |
48988 |
size_t left = size; |
|
364 |
|||
365 |
// Allocate initial buffer if the ring is empty |
||
366 |
48988 |
TryAllocateForWrite(left); |
|
367 |
|||
368 |
✓✓ | 98114 |
while (left > 0) { |
369 |
49126 |
size_t to_write = left; |
|
370 |
✗✓ | 49126 |
CHECK_LE(write_head_->write_pos_, write_head_->len_); |
371 |
49126 |
size_t avail = write_head_->len_ - write_head_->write_pos_; |
|
372 |
|||
373 |
✓✓ | 49126 |
if (to_write > avail) |
374 |
138 |
to_write = avail; |
|
375 |
|||
376 |
// Copy data |
||
377 |
49126 |
memcpy(write_head_->data_ + write_head_->write_pos_, |
|
378 |
49126 |
data + offset, |
|
379 |
to_write); |
||
380 |
|||
381 |
// Move pointers |
||
382 |
49126 |
left -= to_write; |
|
383 |
49126 |
offset += to_write; |
|
384 |
49126 |
length_ += to_write; |
|
385 |
49126 |
write_head_->write_pos_ += to_write; |
|
386 |
✗✓ | 49126 |
CHECK_LE(write_head_->write_pos_, write_head_->len_); |
387 |
|||
388 |
// Go to next buffer if there still are some bytes to write |
||
389 |
✓✓ | 49126 |
if (left != 0) { |
390 |
✗✓ | 138 |
CHECK_EQ(write_head_->write_pos_, write_head_->len_); |
391 |
138 |
TryAllocateForWrite(left); |
|
392 |
138 |
write_head_ = write_head_->next_; |
|
393 |
|||
394 |
// Additionally, since we're moved to the next buffer, read head |
||
395 |
// may be moved as well. |
||
396 |
138 |
TryMoveReadHead(); |
|
397 |
} |
||
398 |
} |
||
399 |
✗✓ | 48988 |
CHECK_EQ(left, 0); |
400 |
48988 |
} |
|
401 |
|||
402 |
|||
403 |
7212 |
char* NodeBIO::PeekWritable(size_t* size) { |
|
404 |
7212 |
TryAllocateForWrite(*size); |
|
405 |
|||
406 |
7212 |
size_t available = write_head_->len_ - write_head_->write_pos_; |
|
407 |
✓✗✓✓ |
7212 |
if (*size == 0 || available <= *size) |
408 |
7169 |
*size = available; |
|
409 |
|||
410 |
7212 |
return write_head_->data_ + write_head_->write_pos_; |
|
411 |
} |
||
412 |
|||
413 |
|||
414 |
6382 |
void NodeBIO::Commit(size_t size) { |
|
415 |
6382 |
write_head_->write_pos_ += size; |
|
416 |
6382 |
length_ += size; |
|
417 |
✗✓ | 6382 |
CHECK_LE(write_head_->write_pos_, write_head_->len_); |
418 |
|||
419 |
// Allocate new buffer if write head is full, |
||
420 |
// and there're no other place to go |
||
421 |
6382 |
TryAllocateForWrite(0); |
|
422 |
✓✓ | 6382 |
if (write_head_->write_pos_ == write_head_->len_) { |
423 |
720 |
write_head_ = write_head_->next_; |
|
424 |
|||
425 |
// Additionally, since we're moved to the next buffer, read head |
||
426 |
// may be moved as well. |
||
427 |
720 |
TryMoveReadHead(); |
|
428 |
} |
||
429 |
6382 |
} |
|
430 |
|||
431 |
|||
432 |
62720 |
void NodeBIO::TryAllocateForWrite(size_t hint) { |
|
433 |
62720 |
Buffer* w = write_head_; |
|
434 |
62720 |
Buffer* r = read_head_; |
|
435 |
// If write head is full, next buffer is either read head or not empty. |
||
436 |
✓✓ | 62720 |
if (w == nullptr || |
437 |
✓✓ | 19846 |
(w->write_pos_ == w->len_ && |
438 |
✓✓✗✓ |
860 |
(w->next_ == r || w->next_->write_pos_ != 0))) { |
439 |
✓✓ | 43541 |
size_t len = w == nullptr ? initial_ : |
440 |
kThroughputBufferLength; |
||
441 |
✓✓ | 43541 |
if (len < hint) |
442 |
33347 |
len = hint; |
|
443 |
|||
444 |
// If there is a one time allocation size hint, use it. |
||
445 |
✓✓ | 43541 |
if (allocate_hint_ > len) { |
446 |
23 |
len = allocate_hint_; |
|
447 |
23 |
allocate_hint_ = 0; |
|
448 |
} |
||
449 |
|||
450 |
43541 |
Buffer* next = new Buffer(env_, len); |
|
451 |
|||
452 |
✓✓ | 43541 |
if (w == nullptr) { |
453 |
42874 |
next->next_ = next; |
|
454 |
42874 |
write_head_ = next; |
|
455 |
42874 |
read_head_ = next; |
|
456 |
} else { |
||
457 |
667 |
next->next_ = w->next_; |
|
458 |
667 |
w->next_ = next; |
|
459 |
} |
||
460 |
} |
||
461 |
62720 |
} |
|
462 |
|||
463 |
|||
464 |
void NodeBIO::Reset() { |
||
465 |
if (read_head_ == nullptr) |
||
466 |
return; |
||
467 |
|||
468 |
while (read_head_->read_pos_ != read_head_->write_pos_) { |
||
469 |
CHECK(read_head_->write_pos_ > read_head_->read_pos_); |
||
470 |
|||
471 |
length_ -= read_head_->write_pos_ - read_head_->read_pos_; |
||
472 |
read_head_->write_pos_ = 0; |
||
473 |
read_head_->read_pos_ = 0; |
||
474 |
|||
475 |
read_head_ = read_head_->next_; |
||
476 |
} |
||
477 |
write_head_ = read_head_; |
||
478 |
CHECK_EQ(length_, 0); |
||
479 |
} |
||
480 |
|||
481 |
|||
482 |
✓✓ | 251940 |
NodeBIO::~NodeBIO() { |
483 |
✓✓ | 125970 |
if (read_head_ == nullptr) |
484 |
40242 |
return; |
|
485 |
|||
486 |
85728 |
Buffer* current = read_head_; |
|
487 |
1326 |
do { |
|
488 |
87054 |
Buffer* next = current->next_; |
|
489 |
✓✗ | 87054 |
delete current; |
490 |
87054 |
current = next; |
|
491 |
✓✓ | 87054 |
} while (current != read_head_); |
492 |
|||
493 |
85728 |
read_head_ = nullptr; |
|
494 |
85728 |
write_head_ = nullptr; |
|
495 |
251940 |
} |
|
496 |
|||
497 |
|||
498 |
1161305 |
NodeBIO* NodeBIO::FromBIO(BIO* bio) { |
|
499 |
✗✓ | 1161305 |
CHECK_NOT_NULL(BIO_get_data(bio)); |
500 |
1161305 |
return static_cast<NodeBIO*>(BIO_get_data(bio)); |
|
501 |
} |
||
502 |
|||
503 |
|||
504 |
} // namespace crypto |
||
505 |
} // namespace node |
Generated by: GCOVR (Version 4.2) |