2 * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
11 #include <openssl/configuration.h>
12 #include <openssl/bio.h>
13 #include "quictestlib.h"
14 #include "ssltestlib.h"
15 #include "../testutil.h"
16 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
17 # include "../threadstest.h"
19 #include "internal/quic_wire_pkt.h"
20 #include "internal/quic_record_tx.h"
21 #include "internal/quic_error.h"
22 #include "internal/packet.h"
24 #define GROWTH_ALLOWANCE 1024
29 /* Plain packet mutations */
30 /* Header for the plaintext packet */
31 QUIC_PKT_HDR pplainhdr
;
32 /* iovec for the plaintext packet data buffer */
33 OSSL_QTX_IOVEC pplainio
;
34 /* Allocated size of the plaintext packet data buffer */
35 size_t pplainbuf_alloc
;
36 qtest_fault_on_packet_plain_cb pplaincb
;
39 /* Handshake message mutations */
40 /* Handshake message buffer */
41 unsigned char *handbuf
;
42 /* Allocated size of the handshake message buffer */
44 /* Actual length of the handshake message */
46 qtest_fault_on_handshake_cb handshakecb
;
48 qtest_fault_on_enc_ext_cb encextcb
;
51 /* Cipher packet mutations */
52 qtest_fault_on_packet_cipher_cb pciphercb
;
55 /* Datagram mutations */
56 qtest_fault_on_datagram_cb datagramcb
;
58 /* The currently processed message */
60 /* Allocated size of msg data buffer */
64 static void packet_plain_finish(void *arg
);
65 static void handshake_finish(void *arg
);
67 static OSSL_TIME fake_now
;
69 static OSSL_TIME
fake_now_cb(void *arg
)
74 int qtest_create_quic_objects(OSSL_LIB_CTX
*libctx
, SSL_CTX
*clientctx
,
75 char *certfile
, char *keyfile
,
76 int flags
, QUIC_TSERVER
**qtserv
, SSL
**cssl
,
79 /* ALPN value as recognised by QUIC_TSERVER */
80 unsigned char alpn
[] = { 8, 'o', 's', 's', 'l', 't', 'e', 's', 't' };
81 QUIC_TSERVER_ARGS tserver_args
= {0};
82 BIO
*cbio
= NULL
, *sbio
= NULL
, *fisbio
= NULL
;
83 BIO_ADDR
*peeraddr
= NULL
;
84 struct in_addr ina
= {0};
91 *cssl
= SSL_new(clientctx
);
96 /* SSL_set_alpn_protos returns 0 for success! */
97 if (!TEST_false(SSL_set_alpn_protos(*cssl
, alpn
, sizeof(alpn
))))
100 if (!TEST_ptr(peeraddr
= BIO_ADDR_new()))
103 if ((flags
& QTEST_FLAG_BLOCK
) != 0) {
104 #if !defined(OPENSSL_NO_POSIX_IO)
108 * For blocking mode we need to create actual sockets rather than doing
109 * everything in memory
111 if (!TEST_true(create_test_sockets(&cfd
, &sfd
, SOCK_DGRAM
, peeraddr
)))
113 cbio
= BIO_new_dgram(cfd
, 1);
114 if (!TEST_ptr(cbio
)) {
119 sbio
= BIO_new_dgram(sfd
, 1);
120 if (!TEST_ptr(sbio
)) {
128 if (!TEST_true(BIO_new_bio_dgram_pair(&cbio
, 0, &sbio
, 0)))
131 if (!TEST_true(BIO_dgram_set_caps(cbio
, BIO_DGRAM_CAP_HANDLES_DST_ADDR
))
132 || !TEST_true(BIO_dgram_set_caps(sbio
, BIO_DGRAM_CAP_HANDLES_DST_ADDR
)))
135 /* Dummy server address */
136 if (!TEST_true(BIO_ADDR_rawmake(peeraddr
, AF_INET
, &ina
, sizeof(ina
),
141 SSL_set_bio(*cssl
, cbio
, cbio
);
143 if (!TEST_true(SSL_set_blocking_mode(*cssl
,
144 (flags
& QTEST_FLAG_BLOCK
) != 0 ? 1 : 0)))
147 if (!TEST_true(SSL_set_initial_peer_addr(*cssl
, peeraddr
)))
151 *fault
= OPENSSL_zalloc(sizeof(**fault
));
156 fisbio
= BIO_new(qtest_get_bio_method());
157 if (!TEST_ptr(fisbio
))
160 BIO_set_data(fisbio
, fault
== NULL
? NULL
: *fault
);
162 if (!TEST_ptr(BIO_push(fisbio
, sbio
)))
165 tserver_args
.libctx
= libctx
;
166 tserver_args
.net_rbio
= sbio
;
167 tserver_args
.net_wbio
= fisbio
;
168 tserver_args
.alpn
= NULL
;
169 if ((flags
& QTEST_FLAG_FAKE_TIME
) != 0) {
170 fake_now
= ossl_time_zero();
171 tserver_args
.now_cb
= fake_now_cb
;
174 if (!TEST_ptr(*qtserv
= ossl_quic_tserver_new(&tserver_args
, certfile
,
178 /* Ownership of fisbio and sbio is now held by *qtserv */
183 (*fault
)->qtserv
= *qtserv
;
185 BIO_ADDR_free(peeraddr
);
189 BIO_ADDR_free(peeraddr
);
195 ossl_quic_tserver_free(*qtserv
);
197 OPENSSL_free(*fault
);
202 void qtest_add_time(uint64_t millis
)
204 fake_now
= ossl_time_add(fake_now
, ossl_ms2time(millis
));
207 QTEST_FAULT
*qtest_create_injector(QUIC_TSERVER
*ts
)
211 f
= OPENSSL_zalloc(sizeof(*f
));
220 int qtest_supports_blocking(void)
222 #if !defined(OPENSSL_NO_POSIX_IO) && defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
229 #define MAXLOOPS 1000
231 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
232 static int globserverret
= 0;
233 static QUIC_TSERVER
*globtserv
;
234 static const thread_t thread_zero
;
236 static void run_server_thread(void)
239 * This will operate in a busy loop because the server does not block,
240 * but should be acceptable because it is local and we expect this to be
243 globserverret
= qtest_create_quic_connection(globtserv
, NULL
);
247 int qtest_create_quic_connection(QUIC_TSERVER
*qtserv
, SSL
*clientssl
)
249 int retc
= -1, rets
= 0, err
, abortctr
= 0, ret
= 0;
250 int clienterr
= 0, servererr
= 0;
251 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
253 * Pointless initialisation to avoid bogus compiler warnings about using
256 thread_t t
= thread_zero
;
259 if (!TEST_ptr(qtserv
)) {
261 } else if (clientssl
== NULL
) {
263 } else if (SSL_get_blocking_mode(clientssl
) > 0) {
264 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
266 * clientssl is blocking. We will need a thread to complete the
270 if (!TEST_true(run_thread(&t
, run_server_thread
)))
276 TEST_error("No thread support in this build");
282 err
= SSL_ERROR_WANT_WRITE
;
283 while (!clienterr
&& retc
<= 0 && err
== SSL_ERROR_WANT_WRITE
) {
284 retc
= SSL_connect(clientssl
);
286 err
= SSL_get_error(clientssl
, retc
);
289 if (!clienterr
&& retc
<= 0 && err
!= SSL_ERROR_WANT_READ
) {
290 TEST_info("SSL_connect() failed %d, %d", retc
, err
);
291 TEST_openssl_errors();
296 * We're cheating. We don't take any notice of SSL_get_tick_timeout()
297 * and tick every time around the loop anyway. This is inefficient. We
298 * can get away with it in test code because we control both ends of
299 * the communications and don't expect network delays. This shouldn't
300 * be done in a real application.
302 if (!clienterr
&& retc
<= 0)
303 SSL_handle_events(clientssl
);
304 if (!servererr
&& rets
<= 0) {
306 ossl_quic_tserver_tick(qtserv
);
307 servererr
= ossl_quic_tserver_is_term_any(qtserv
);
309 rets
= ossl_quic_tserver_is_handshake_confirmed(qtserv
);
312 if (clienterr
&& servererr
)
315 if (clientssl
!= NULL
&& ++abortctr
== MAXLOOPS
) {
316 TEST_info("No progress made");
319 } while ((retc
<= 0 && !clienterr
) || (rets
<= 0 && !servererr
));
321 if (qtserv
== NULL
&& rets
> 0) {
322 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
323 if (!TEST_true(wait_for_thread(t
)) || !TEST_true(globserverret
))
326 TEST_error("Should not happen");
331 if (!clienterr
&& !servererr
)
337 int qtest_shutdown(QUIC_TSERVER
*qtserv
, SSL
*clientssl
)
339 /* Busy loop in non-blocking mode. It should be quick because its local */
341 int rc
= SSL_shutdown(clientssl
);
349 ossl_quic_tserver_tick(qtserv
);
355 int qtest_check_server_transport_err(QUIC_TSERVER
*qtserv
, uint64_t code
)
357 const QUIC_TERMINATE_CAUSE
*cause
;
359 ossl_quic_tserver_tick(qtserv
);
362 * Check that the server has closed with the specified code from the client
364 if (!TEST_true(ossl_quic_tserver_is_term_any(qtserv
)))
367 cause
= ossl_quic_tserver_get_terminate_cause(qtserv
);
369 || !TEST_true(cause
->remote
)
370 || !TEST_false(cause
->app
)
371 || !TEST_uint64_t_eq(cause
->error_code
, code
))
377 int qtest_check_server_protocol_err(QUIC_TSERVER
*qtserv
)
379 return qtest_check_server_transport_err(qtserv
, QUIC_ERR_PROTOCOL_VIOLATION
);
382 int qtest_check_server_frame_encoding_err(QUIC_TSERVER
*qtserv
)
384 return qtest_check_server_transport_err(qtserv
, QUIC_ERR_FRAME_ENCODING_ERROR
);
387 void qtest_fault_free(QTEST_FAULT
*fault
)
392 packet_plain_finish(fault
);
393 handshake_finish(fault
);
398 static int packet_plain_mutate(const QUIC_PKT_HDR
*hdrin
,
399 const OSSL_QTX_IOVEC
*iovecin
, size_t numin
,
400 QUIC_PKT_HDR
**hdrout
,
401 const OSSL_QTX_IOVEC
**iovecout
,
405 QTEST_FAULT
*fault
= arg
;
409 /* Coalesce our data into a single buffer */
411 /* First calculate required buffer size */
412 for (i
= 0; i
< numin
; i
++)
413 bufsz
+= iovecin
[i
].buf_len
;
415 fault
->pplainio
.buf_len
= bufsz
;
417 /* Add an allowance for possible growth */
418 bufsz
+= GROWTH_ALLOWANCE
;
420 fault
->pplainio
.buf
= cur
= OPENSSL_malloc(bufsz
);
422 fault
->pplainio
.buf_len
= 0;
426 fault
->pplainbuf_alloc
= bufsz
;
428 /* Copy in the data from the input buffers */
429 for (i
= 0; i
< numin
; i
++) {
430 memcpy(cur
, iovecin
[i
].buf
, iovecin
[i
].buf_len
);
431 cur
+= iovecin
[i
].buf_len
;
434 fault
->pplainhdr
= *hdrin
;
436 /* Cast below is safe because we allocated the buffer */
437 if (fault
->pplaincb
!= NULL
438 && !fault
->pplaincb(fault
, &fault
->pplainhdr
,
439 (unsigned char *)fault
->pplainio
.buf
,
440 fault
->pplainio
.buf_len
, fault
->pplaincbarg
))
443 *hdrout
= &fault
->pplainhdr
;
444 *iovecout
= &fault
->pplainio
;
450 static void packet_plain_finish(void *arg
)
452 QTEST_FAULT
*fault
= arg
;
454 /* Cast below is safe because we allocated the buffer */
455 OPENSSL_free((unsigned char *)fault
->pplainio
.buf
);
456 fault
->pplainio
.buf_len
= 0;
457 fault
->pplainbuf_alloc
= 0;
458 fault
->pplainio
.buf
= NULL
;
461 int qtest_fault_set_packet_plain_listener(QTEST_FAULT
*fault
,
462 qtest_fault_on_packet_plain_cb pplaincb
,
465 fault
->pplaincb
= pplaincb
;
466 fault
->pplaincbarg
= pplaincbarg
;
468 return ossl_quic_tserver_set_plain_packet_mutator(fault
->qtserv
,
474 /* To be called from a packet_plain_listener callback */
475 int qtest_fault_resize_plain_packet(QTEST_FAULT
*fault
, size_t newlen
)
478 size_t oldlen
= fault
->pplainio
.buf_len
;
481 * Alloc'd size should always be non-zero, so if this fails we've been
484 if (fault
->pplainbuf_alloc
== 0)
487 if (newlen
> fault
->pplainbuf_alloc
) {
488 /* This exceeds our growth allowance. Fail */
492 /* Cast below is safe because we allocated the buffer */
493 buf
= (unsigned char *)fault
->pplainio
.buf
;
495 if (newlen
> oldlen
) {
496 /* Extend packet with 0 bytes */
497 memset(buf
+ oldlen
, 0, newlen
- oldlen
);
498 } /* else we're truncating or staying the same */
500 fault
->pplainio
.buf_len
= newlen
;
501 fault
->pplainhdr
.len
= newlen
;
507 * Prepend frame data into a packet. To be called from a packet_plain_listener
510 int qtest_fault_prepend_frame(QTEST_FAULT
*fault
, const unsigned char *frame
,
517 * Alloc'd size should always be non-zero, so if this fails we've been
520 if (fault
->pplainbuf_alloc
== 0)
523 /* Cast below is safe because we allocated the buffer */
524 buf
= (unsigned char *)fault
->pplainio
.buf
;
525 old_len
= fault
->pplainio
.buf_len
;
527 /* Extend the size of the packet by the size of the new frame */
528 if (!TEST_true(qtest_fault_resize_plain_packet(fault
,
529 old_len
+ frame_len
)))
532 memmove(buf
+ frame_len
, buf
, old_len
);
533 memcpy(buf
, frame
, frame_len
);
538 static int handshake_mutate(const unsigned char *msgin
, size_t msginlen
,
539 unsigned char **msgout
, size_t *msgoutlen
,
542 QTEST_FAULT
*fault
= arg
;
544 unsigned long payloadlen
;
545 unsigned int msgtype
;
548 buf
= OPENSSL_malloc(msginlen
+ GROWTH_ALLOWANCE
);
552 fault
->handbuf
= buf
;
553 fault
->handbuflen
= msginlen
;
554 fault
->handbufalloc
= msginlen
+ GROWTH_ALLOWANCE
;
555 memcpy(buf
, msgin
, msginlen
);
557 if (!PACKET_buf_init(&pkt
, buf
, msginlen
)
558 || !PACKET_get_1(&pkt
, &msgtype
)
559 || !PACKET_get_net_3(&pkt
, &payloadlen
)
560 || PACKET_remaining(&pkt
) != payloadlen
)
563 /* Parse specific message types */
565 case SSL3_MT_ENCRYPTED_EXTENSIONS
:
567 QTEST_ENCRYPTED_EXTENSIONS ee
;
569 if (fault
->encextcb
== NULL
)
573 * The EncryptedExtensions message is very simple. It just has an
574 * extensions block in it and nothing else.
576 ee
.extensions
= (unsigned char *)PACKET_data(&pkt
);
577 ee
.extensionslen
= payloadlen
;
578 if (!fault
->encextcb(fault
, &ee
, payloadlen
, fault
->encextcbarg
))
583 /* No specific handlers for these message types yet */
587 if (fault
->handshakecb
!= NULL
588 && !fault
->handshakecb(fault
, buf
, fault
->handbuflen
,
589 fault
->handshakecbarg
))
593 *msgoutlen
= fault
->handbuflen
;
598 static void handshake_finish(void *arg
)
600 QTEST_FAULT
*fault
= arg
;
602 OPENSSL_free(fault
->handbuf
);
603 fault
->handbuf
= NULL
;
606 int qtest_fault_set_handshake_listener(QTEST_FAULT
*fault
,
607 qtest_fault_on_handshake_cb handshakecb
,
608 void *handshakecbarg
)
610 fault
->handshakecb
= handshakecb
;
611 fault
->handshakecbarg
= handshakecbarg
;
613 return ossl_quic_tserver_set_handshake_mutator(fault
->qtserv
,
619 int qtest_fault_set_hand_enc_ext_listener(QTEST_FAULT
*fault
,
620 qtest_fault_on_enc_ext_cb encextcb
,
623 fault
->encextcb
= encextcb
;
624 fault
->encextcbarg
= encextcbarg
;
626 return ossl_quic_tserver_set_handshake_mutator(fault
->qtserv
,
632 /* To be called from a handshake_listener callback */
633 int qtest_fault_resize_handshake(QTEST_FAULT
*fault
, size_t newlen
)
636 size_t oldlen
= fault
->handbuflen
;
639 * Alloc'd size should always be non-zero, so if this fails we've been
642 if (fault
->handbufalloc
== 0)
645 if (newlen
> fault
->handbufalloc
) {
646 /* This exceeds our growth allowance. Fail */
650 buf
= (unsigned char *)fault
->handbuf
;
652 if (newlen
> oldlen
) {
653 /* Extend packet with 0 bytes */
654 memset(buf
+ oldlen
, 0, newlen
- oldlen
);
655 } /* else we're truncating or staying the same */
657 fault
->handbuflen
= newlen
;
661 /* To be called from message specific listener callbacks */
662 int qtest_fault_resize_message(QTEST_FAULT
*fault
, size_t newlen
)
664 /* First resize the underlying message */
665 if (!qtest_fault_resize_handshake(fault
, newlen
+ SSL3_HM_HEADER_LENGTH
))
668 /* Fixup the handshake message header */
669 fault
->handbuf
[1] = (unsigned char)((newlen
>> 16) & 0xff);
670 fault
->handbuf
[2] = (unsigned char)((newlen
>> 8) & 0xff);
671 fault
->handbuf
[3] = (unsigned char)((newlen
) & 0xff);
676 int qtest_fault_delete_extension(QTEST_FAULT
*fault
,
677 unsigned int exttype
, unsigned char *ext
,
680 PACKET pkt
, sub
, subext
;
682 const unsigned char *start
, *end
;
684 size_t msglen
= fault
->handbuflen
;
686 if (!PACKET_buf_init(&pkt
, ext
, *extlen
))
689 /* Extension block starts with 2 bytes for extension block length */
690 if (!PACKET_as_length_prefixed_2(&pkt
, &sub
))
694 start
= PACKET_data(&sub
);
695 if (!PACKET_get_net_2(&sub
, &type
)
696 || !PACKET_get_length_prefixed_2(&sub
, &subext
))
698 } while (type
!= exttype
);
701 end
= PACKET_data(&sub
);
704 * If we're not the last extension we need to move the rest earlier. The
705 * cast below is safe because we own the underlying buffer and we're no
706 * longer making PACKET calls.
708 if (end
< ext
+ *extlen
)
709 memmove((unsigned char *)start
, end
, end
- start
);
712 * Calculate new extensions payload length =
714 * - 2 extension block length bytes
715 * - length of removed extension
717 newlen
= *extlen
- 2 - (end
- start
);
719 /* Fixup the length bytes for the extension block */
720 ext
[0] = (unsigned char)((newlen
>> 8) & 0xff);
721 ext
[1] = (unsigned char)((newlen
) & 0xff);
724 * Length of the whole extension block is the new payload length plus the
725 * 2 bytes for the length
727 *extlen
= newlen
+ 2;
729 /* We can now resize the message */
730 if ((size_t)(end
- start
) + SSL3_HM_HEADER_LENGTH
> msglen
)
731 return 0; /* Should not happen */
732 msglen
-= (end
- start
) + SSL3_HM_HEADER_LENGTH
;
733 if (!qtest_fault_resize_message(fault
, msglen
))
739 #define BIO_TYPE_CIPHER_PACKET_FILTER (0x80 | BIO_TYPE_FILTER)
741 static BIO_METHOD
*pcipherbiometh
= NULL
;
743 # define BIO_MSG_N(array, stride, n) (*(BIO_MSG *)((char *)(array) + (n)*(stride)))
745 static int pcipher_sendmmsg(BIO
*b
, BIO_MSG
*msg
, size_t stride
,
746 size_t num_msg
, uint64_t flags
,
747 size_t *num_processed
)
750 BIO
*next
= BIO_next(b
);
751 ossl_ssize_t ret
= 0;
752 size_t i
= 0, tmpnump
;
755 unsigned char *tmpdata
;
760 fault
= BIO_get_data(b
);
762 || (fault
->pciphercb
== NULL
&& fault
->datagramcb
== NULL
))
763 return BIO_sendmmsg(next
, msg
, stride
, num_msg
, flags
, num_processed
);
770 for (i
= 0; i
< num_msg
; ++i
) {
771 fault
->msg
= BIO_MSG_N(msg
, stride
, i
);
773 /* Take a copy of the data so that callbacks can modify it */
774 tmpdata
= OPENSSL_malloc(fault
->msg
.data_len
+ GROWTH_ALLOWANCE
);
777 memcpy(tmpdata
, fault
->msg
.data
, fault
->msg
.data_len
);
778 fault
->msg
.data
= tmpdata
;
779 fault
->msgalloc
= fault
->msg
.data_len
+ GROWTH_ALLOWANCE
;
781 if (fault
->pciphercb
!= NULL
) {
782 if (!PACKET_buf_init(&pkt
, fault
->msg
.data
, fault
->msg
.data_len
))
786 if (!ossl_quic_wire_decode_pkt_hdr(&pkt
,
787 0 /* TODO(QUIC): Not sure how this should be set*/, 1,
792 * hdr.data is const - but its our buffer so casting away the
795 if (!fault
->pciphercb(fault
, &hdr
, (unsigned char *)hdr
.data
,
796 hdr
.len
, fault
->pciphercbarg
))
800 * TODO(QUIC): At the moment modifications to hdr by the callback
801 * are ignored. We might need to rewrite the QUIC header to
802 * enable tests to change this. We also don't yet have a
803 * mechanism for the callback to change the encrypted data
804 * length. It's not clear if that's needed or not.
806 } while (PACKET_remaining(&pkt
) > 0);
809 if (fault
->datagramcb
!= NULL
810 && !fault
->datagramcb(fault
, &fault
->msg
, stride
,
811 fault
->datagramcbarg
))
814 if (!BIO_sendmmsg(next
, &fault
->msg
, stride
, 1, flags
, &tmpnump
)) {
819 OPENSSL_free(fault
->msg
.data
);
820 fault
->msg
.data
= NULL
;
827 OPENSSL_free(fault
->msg
.data
);
828 fault
->msg
.data
= NULL
;
832 static long pcipher_ctrl(BIO
*b
, int cmd
, long larg
, void *parg
)
834 BIO
*next
= BIO_next(b
);
839 return BIO_ctrl(next
, cmd
, larg
, parg
);
842 BIO_METHOD
*qtest_get_bio_method(void)
846 if (pcipherbiometh
!= NULL
)
847 return pcipherbiometh
;
849 tmp
= BIO_meth_new(BIO_TYPE_CIPHER_PACKET_FILTER
, "Cipher Packet Filter");
854 if (!TEST_true(BIO_meth_set_sendmmsg(tmp
, pcipher_sendmmsg
))
855 || !TEST_true(BIO_meth_set_ctrl(tmp
, pcipher_ctrl
)))
858 pcipherbiometh
= tmp
;
862 return pcipherbiometh
;
865 int qtest_fault_set_packet_cipher_listener(QTEST_FAULT
*fault
,
866 qtest_fault_on_packet_cipher_cb pciphercb
,
869 fault
->pciphercb
= pciphercb
;
870 fault
->pciphercbarg
= pciphercbarg
;
875 int qtest_fault_set_datagram_listener(QTEST_FAULT
*fault
,
876 qtest_fault_on_datagram_cb datagramcb
,
879 fault
->datagramcb
= datagramcb
;
880 fault
->datagramcbarg
= datagramcbarg
;
885 /* To be called from a datagram_listener callback */
886 int qtest_fault_resize_datagram(QTEST_FAULT
*fault
, size_t newlen
)
888 if (newlen
> fault
->msgalloc
)
891 if (newlen
> fault
->msg
.data_len
)
892 memset((unsigned char *)fault
->msg
.data
+ fault
->msg
.data_len
, 0,
893 newlen
- fault
->msg
.data_len
);
895 fault
->msg
.data_len
= newlen
;