From f1344aea0dbac73e3dab5d351c9aee830a293d44 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Fri, 15 Mar 2024 12:21:20 -0700 Subject: [PATCH 1/4] Try fix interop issues --- CMakeLists.txt | 1 + UnitTest1/unittest1.cpp | 6 + picohttp/h3zero_common.c | 11 +- picohttp/wt_baton.c | 4 +- picohttp_t/picohttp_t.c | 1 + picoquictest/h3zero_stream_test.c | 155 ++++++++++++++++++++++ picoquictest/picoquictest.h | 1 + picoquictest/picoquictest.vcxproj | 1 + picoquictest/picoquictest.vcxproj.filters | 3 + 9 files changed, 175 insertions(+), 8 deletions(-) create mode 100644 picoquictest/h3zero_stream_test.c diff --git a/CMakeLists.txt b/CMakeLists.txt index fab61cfb6..9b76cb1dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -199,6 +199,7 @@ set(PICOHTTP_HEADERS set(PICOHTTP_TEST_LIBRARY_FILES picoquictest/h3zerotest.c + picoquictest/h3zero_stream_test.c picoquictest/h3zero_uri_test.c picoquictest/webtransport_test.c) diff --git a/UnitTest1/unittest1.cpp b/UnitTest1/unittest1.cpp index a38612684..9c076e69c 100644 --- a/UnitTest1/unittest1.cpp +++ b/UnitTest1/unittest1.cpp @@ -2722,6 +2722,12 @@ namespace UnitTest1 Assert::AreEqual(ret, 0); } + TEST_METHOD(h3zero_varint_stream) { + int ret = h3zero_varint_stream_test(); + + Assert::AreEqual(ret, 0); + } + TEST_METHOD(qpack_huffman) { int ret = qpack_huffman_test(); diff --git a/picohttp/h3zero_common.c b/picohttp/h3zero_common.c index 5f7ddd9a9..cfa79e7e2 100644 --- a/picohttp/h3zero_common.c +++ b/picohttp/h3zero_common.c @@ -476,13 +476,12 @@ uint8_t* h3zero_parse_control_stream_id( uint8_t* bytes, uint8_t* bytes_max, h3zero_data_stream_state_t* stream_state, h3zero_stream_ctx_t* stream_ctx, - h3zero_callback_ctx_t* ctx, - uint64_t * error_found) + h3zero_callback_ctx_t* ctx) { if (stream_state->control_stream_id == UINT64_MAX) { bytes = h3zero_varint_from_stream(bytes, bytes_max, &stream_state->control_stream_id, stream_state->frame_header, &stream_state->frame_header_read); - if (stream_state->current_frame_type == UINT64_MAX) { - /* frame type was not updated */ + if (stream_state->control_stream_id == UINT64_MAX) { + /* Control stream ID not updated */ return bytes; } /* Just found the control stream ID */ @@ -523,7 +522,7 @@ uint8_t* h3zero_parse_remote_bidir_stream( } } if (stream_state->stream_type == h3zero_frame_webtransport_stream) { - bytes = h3zero_parse_control_stream_id(bytes, bytes_max, stream_state, stream_ctx, ctx, error_found); + bytes = h3zero_parse_control_stream_id(bytes, bytes_max, stream_state, stream_ctx, ctx); } else { /* Not and expected stream */ @@ -565,7 +564,7 @@ uint8_t* h3zero_parse_remote_unidir_stream( bytes = bytes_max; break; case h3zero_stream_type_webtransport: /* unidir stream is used as specified in web transport */ - bytes = h3zero_parse_control_stream_id(bytes, bytes_max, stream_state, stream_ctx, ctx, error_found); + bytes = h3zero_parse_control_stream_id(bytes, bytes_max, stream_state, stream_ctx, ctx); break; default: /* Per section 6.2 of RFC 9114, unknown stream types are just ignored */ diff --git a/picohttp/wt_baton.c b/picohttp/wt_baton.c index eb60deef8..5b79817ee 100644 --- a/picohttp/wt_baton.c +++ b/picohttp/wt_baton.c @@ -915,8 +915,8 @@ int wt_baton_process_remote_stream(picoquic_cnx_t* cnx, picoquic_log_app_message(cnx, "Cannot parse incoming stream: %"PRIu64, stream_id); ret = -1; } - else { - ret = h3zero_post_data_or_fin(cnx, bytes, length, fin_or_event, stream_ctx); + else if (bytes < bytes_max) { + ret = h3zero_post_data_or_fin(cnx, bytes, bytes_max - bytes, fin_or_event, stream_ctx); } } return ret; diff --git a/picohttp_t/picohttp_t.c b/picohttp_t/picohttp_t.c index 9d92446a9..2d3ec9edc 100644 --- a/picohttp_t/picohttp_t.c +++ b/picohttp_t/picohttp_t.c @@ -46,6 +46,7 @@ typedef enum { static const picoquic_test_def_t test_table[] = { { "h3zero_integer", h3zero_integer_test }, + { "h3zero_varint_stream", h3zero_varint_stream_test }, { "qpack_huffman", qpack_huffman_test }, { "qpack_huffman_base", qpack_huffman_base_test}, { "h3zero_parse_qpack", h3zero_parse_qpack_test }, diff --git a/picoquictest/h3zero_stream_test.c b/picoquictest/h3zero_stream_test.c new file mode 100644 index 000000000..877ae78ac --- /dev/null +++ b/picoquictest/h3zero_stream_test.c @@ -0,0 +1,155 @@ +/* +* Author: Christian Huitema +* Copyright (c) 2024, Private Octopus, Inc. +* All rights reserved. +* +* Permission to use, copy, modify, and distribute this software for any +* purpose with or without fee is hereby granted, provided that the above +* copyright notice and this permission notice appear in all copies. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL Private Octopus, Inc. BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include +#include "picoquic_internal.h" +#include "picoquic_utils.h" +#include "picoquictest_internal.h" +#include "tls_api.h" +#include "h3zero.h" +#include "h3zero_common.h" +#include "democlient.h" +#include "demoserver.h" +#ifdef _WINDOWS +#include "wincompat.h" +#include +#else +#include +#include +#endif +#if 0 +/* Include picotls.h in order to support tests of ESNI */ +#include "picotls.h" +#include "tls_api.h" +#endif +#include "autoqlog.h" +#include "picoquic_binlog.h" + +/* testing: + * uint8_t * h3zero_varint_from_stream(uint8_t* bytes, uint8_t* bytes_max, uint64_t * result, uint8_t * buffer, size_t* buffer_length) + * + * start with a stream encoding, made of a set of bytes, encoding a number of varint puls some extra bytes. + * the state is captured in a decoded varint vector of size N. + * the vector is initialized to UINT64_MAX. + * the logic: + * get the encoded buffer that contains the encoded value of the varints, as a string of bytes + * feed that buffer to the decoder in multiple ways: + * - all bytes at once, + * - one byte at a time, + * - two bytes at a time. + * The decoder itself will try to decode the next varint in the record, and consume bytes. + * if the varint value is not UINT64_MAX, go to the next one, etc. + */ + +typedef struct st_h3zero_varint_stream_test_t { + uint64_t v_int[4]; + uint64_t targets[4]; + size_t nb_targets; + uint8_t buffer[16]; + size_t buffer_length; + uint8_t bytes[64]; + size_t nb_bytes; + size_t nb_processed; +} h3zero_varint_stream_test_t; + +static int h3zero_varint_stream_test_init(h3zero_varint_stream_test_t * hvst, uint64_t * targets, size_t nb_targets) +{ + int ret = 0; + uint8_t * bytes = hvst->bytes; + uint8_t * bytes_max = bytes + sizeof(hvst->bytes); + + memset(hvst, 0, sizeof(h3zero_varint_stream_test_t)); + if (nb_targets >= 4) { + ret = -1; + } + else { + hvst->nb_targets = nb_targets; + for (size_t i = 0; i < nb_targets && i < 4; i++) { + hvst->targets[i] = targets[i]; + hvst->v_int[i] = UINT64_MAX; + bytes = picoquic_frames_varint_encode(bytes, bytes_max, targets[i]); + if (bytes == NULL) { + ret = -1; + break; + } + } + if (ret == 0) { + hvst->nb_bytes = bytes - hvst->bytes; + } + } + return ret; +} + +int h3zero_varint_stream_chunk_test(uint64_t * targets, size_t nb_targets, size_t chunk_bytes) +{ + h3zero_varint_stream_test_t hvst; + int ret = h3zero_varint_stream_test_init(&hvst, targets, nb_targets); + size_t nb_not_64max = 0; + uint8_t* bytes = hvst.bytes; + uint8_t* bytes_max = hvst.bytes + hvst.nb_bytes; + + while (ret == 0) { + nb_not_64max = 0; + for (size_t i = 0; i < nb_targets; i++) { + if (hvst.v_int[i] != UINT64_MAX) { + nb_not_64max++; + } + } + if (nb_not_64max >= nb_targets) { + break; + } + uint8_t* bytes_max = hvst.bytes + hvst.nb_bytes; + if (bytes >= bytes_max) { + /* nothing more to feed */ + break; + } + if (bytes_max > bytes + chunk_bytes) { + bytes_max = bytes + chunk_bytes; + } + bytes = h3zero_varint_from_stream(bytes, bytes_max, &hvst.v_int[nb_not_64max], hvst.buffer, &hvst.buffer_length); + } + if (nb_not_64max < nb_targets) { + ret = -1; + } + for (size_t i = 0; ret == 0 && i < nb_targets; i++) { + if (hvst.v_int[i] != targets[i]) { + ret = -1; + break; + } + } + return ret; +} + +int h3zero_varint_stream_test() +{ + int ret = 0; + uint64_t targets[4] = { 132, 4, 0x10001, 0x10000001 }; + + for (size_t nb_targets = 1; ret = 0 && nb_targets <= 4; nb_targets++) { + for (size_t j = 0; ret == 0 && j < 4; j++) { + size_t chunk_bytes = (size_t)(1 << j); + ret = h3zero_varint_stream_chunk_test(targets, nb_targets, chunk_bytes); + } + } + return ret; +} \ No newline at end of file diff --git a/picoquictest/picoquictest.h b/picoquictest/picoquictest.h index 9578e0446..e7a64f9fa 100644 --- a/picoquictest/picoquictest.h +++ b/picoquictest/picoquictest.h @@ -280,6 +280,7 @@ int high_latency_probeRTT_test(); int cid_length_test(); int initial_server_close_test(); int h3zero_integer_test(); +int h3zero_varint_stream_test(); int qpack_huffman_test(); int qpack_huffman_base_test(); int h3zero_parse_qpack_test(); diff --git a/picoquictest/picoquictest.vcxproj b/picoquictest/picoquictest.vcxproj index 09e8874fa..7b37d04fd 100644 --- a/picoquictest/picoquictest.vcxproj +++ b/picoquictest/picoquictest.vcxproj @@ -161,6 +161,7 @@ + diff --git a/picoquictest/picoquictest.vcxproj.filters b/picoquictest/picoquictest.vcxproj.filters index 028301996..4c52f6acb 100644 --- a/picoquictest/picoquictest.vcxproj.filters +++ b/picoquictest/picoquictest.vcxproj.filters @@ -159,6 +159,9 @@ Source Files + + Source Files + From 0a1de0cf1697f66290813bd1d564b74a4184341f Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Fri, 15 Mar 2024 20:36:32 -0700 Subject: [PATCH 2/4] Debuf Stream Varint parsing --- UnitTest1/unittest1.cpp | 6 ++ picohttp/h3zero.c | 2 + picohttp/h3zero_common.c | 4 +- picohttp_t/picohttp_t.c | 1 + picoquictest/h3zero_stream_test.c | 154 ++++++++++++++++++++++++++---- picoquictest/picoquictest.h | 1 + 6 files changed, 148 insertions(+), 20 deletions(-) diff --git a/UnitTest1/unittest1.cpp b/UnitTest1/unittest1.cpp index 9c076e69c..65fb025ed 100644 --- a/UnitTest1/unittest1.cpp +++ b/UnitTest1/unittest1.cpp @@ -2728,6 +2728,12 @@ namespace UnitTest1 Assert::AreEqual(ret, 0); } + TEST_METHOD(h3zero_incoming_unidir) { + int ret = h3zero_incoming_unidir_test(); + + Assert::AreEqual(ret, 0); + } + TEST_METHOD(qpack_huffman) { int ret = qpack_huffman_test(); diff --git a/picohttp/h3zero.c b/picohttp/h3zero.c index ded42456e..eb4fd63da 100644 --- a/picohttp/h3zero.c +++ b/picohttp/h3zero.c @@ -1014,11 +1014,13 @@ uint8_t * h3zero_varint_from_stream(uint8_t* bytes, uint8_t* bytes_max, uint64_t } if (bp == buffer) { *bp++ = *bytes++; + *buffer_length += 1; } be = buffer + h3zero_varint_skip(buffer); while (bytes < bytes_max && bp < be) { *bp++ = *bytes++; + *buffer_length += 1; } if (bp >= be) { diff --git a/picohttp/h3zero_common.c b/picohttp/h3zero_common.c index cfa79e7e2..a5bd5ab32 100644 --- a/picohttp/h3zero_common.c +++ b/picohttp/h3zero_common.c @@ -541,8 +541,8 @@ uint8_t* h3zero_parse_remote_unidir_stream( if (stream_state->stream_type == UINT64_MAX) { bytes = h3zero_varint_from_stream(bytes, bytes_max, &stream_state->stream_type, stream_state->frame_header, &stream_state->frame_header_read); - if (stream_state->current_frame_type == UINT64_MAX) { - /* frame type was not updated */ + if (stream_state->stream_type == UINT64_MAX) { + /* stream type was not updated */ return bytes; } if (stream_state->stream_type == h3zero_stream_type_control) { diff --git a/picohttp_t/picohttp_t.c b/picohttp_t/picohttp_t.c index 2d3ec9edc..e4daf31f5 100644 --- a/picohttp_t/picohttp_t.c +++ b/picohttp_t/picohttp_t.c @@ -47,6 +47,7 @@ typedef enum { static const picoquic_test_def_t test_table[] = { { "h3zero_integer", h3zero_integer_test }, { "h3zero_varint_stream", h3zero_varint_stream_test }, + { "h3zero_incoming_unidir", h3zero_incoming_unidir_test }, { "qpack_huffman", qpack_huffman_test }, { "qpack_huffman_base", qpack_huffman_base_test}, { "h3zero_parse_qpack", h3zero_parse_qpack_test }, diff --git a/picoquictest/h3zero_stream_test.c b/picoquictest/h3zero_stream_test.c index 877ae78ac..fe01f9a9d 100644 --- a/picoquictest/h3zero_stream_test.c +++ b/picoquictest/h3zero_stream_test.c @@ -44,6 +44,7 @@ #endif #include "autoqlog.h" #include "picoquic_binlog.h" +#include "pico_webtransport.h" /* testing: * uint8_t * h3zero_varint_from_stream(uint8_t* bytes, uint8_t* bytes_max, uint64_t * result, uint8_t * buffer, size_t* buffer_length) @@ -79,7 +80,7 @@ static int h3zero_varint_stream_test_init(h3zero_varint_stream_test_t * hvst, ui uint8_t * bytes_max = bytes + sizeof(hvst->bytes); memset(hvst, 0, sizeof(h3zero_varint_stream_test_t)); - if (nb_targets >= 4) { + if (nb_targets > 4) { ret = -1; } else { @@ -105,36 +106,47 @@ int h3zero_varint_stream_chunk_test(uint64_t * targets, size_t nb_targets, size_ h3zero_varint_stream_test_t hvst; int ret = h3zero_varint_stream_test_init(&hvst, targets, nb_targets); size_t nb_not_64max = 0; + size_t nb_chunks = 0; uint8_t* bytes = hvst.bytes; uint8_t* bytes_max = hvst.bytes + hvst.nb_bytes; + uint8_t* chunk_start; + uint8_t* chunk_end; while (ret == 0) { - nb_not_64max = 0; - for (size_t i = 0; i < nb_targets; i++) { - if (hvst.v_int[i] != UINT64_MAX) { + chunk_start = hvst.bytes + chunk_bytes * nb_chunks; + chunk_end = chunk_start + chunk_bytes; + if (chunk_start >= bytes_max) { + /* nothing more to feed */ + break; + } + else if (chunk_end >= bytes_max) { + chunk_end = bytes_max; + } + nb_chunks++; + bytes = chunk_start; + while (bytes != NULL && bytes < chunk_end) { + bytes = h3zero_varint_from_stream(bytes, chunk_end, &hvst.v_int[nb_not_64max], hvst.buffer, &hvst.buffer_length); + if (hvst.v_int[nb_not_64max] != UINT64_MAX) { nb_not_64max++; + if (nb_not_64max >= nb_targets) { + break; + } + continue; } } if (nb_not_64max >= nb_targets) { break; } - uint8_t* bytes_max = hvst.bytes + hvst.nb_bytes; - if (bytes >= bytes_max) { - /* nothing more to feed */ - break; - } - if (bytes_max > bytes + chunk_bytes) { - bytes_max = bytes + chunk_bytes; - } - bytes = h3zero_varint_from_stream(bytes, bytes_max, &hvst.v_int[nb_not_64max], hvst.buffer, &hvst.buffer_length); } if (nb_not_64max < nb_targets) { ret = -1; } - for (size_t i = 0; ret == 0 && i < nb_targets; i++) { - if (hvst.v_int[i] != targets[i]) { - ret = -1; - break; + else { + for (size_t i = 0; ret == 0 && i < nb_targets; i++) { + if (hvst.v_int[i] != targets[i]) { + ret = -1; + break; + } } } return ret; @@ -145,11 +157,117 @@ int h3zero_varint_stream_test() int ret = 0; uint64_t targets[4] = { 132, 4, 0x10001, 0x10000001 }; - for (size_t nb_targets = 1; ret = 0 && nb_targets <= 4; nb_targets++) { + for (size_t nb_targets = 1; ret == 0 && nb_targets <= 4; nb_targets++) { for (size_t j = 0; ret == 0 && j < 4; j++) { size_t chunk_bytes = (size_t)(1 << j); ret = h3zero_varint_stream_chunk_test(targets, nb_targets, chunk_bytes); + if (ret == -1) { + DBG_PRINTF("varint_stream test fails for chunks size= %zu, nb_target=%zu", chunk_bytes, nb_targets); + } + } + } + return ret; +} + +/* + * Test of + * uint8_t* h3zero_parse_remote_unidir_stream( + * uint8_t* bytes, uint8_t* bytes_max, + * h3zero_stream_ctx_t* stream_ctx, + * h3zero_callback_ctx_t* ctx, + * uint64_t * error_found) + * + * uint8_t* h3zero_parse_incoming_remote_stream( + * uint8_t* bytes, uint8_t* bytes_max, + * h3zero_stream_ctx_t* stream_ctx, + * h3zero_callback_ctx_t* ctx) + * + * The test requires that a valid context is defined: + * + * h3zero_stream_ctx_t: incoming stream context. + * + */ + +int incoming_unidir_test_fn(picoquic_cnx_t* cnx, + uint8_t* bytes, size_t length, + picohttp_call_back_event_t fin_or_event, + struct st_h3zero_stream_ctx_t* stream_ctx, + void* path_app_ctx) +{ + return 0; +} + +int h3zero_incoming_unidir_test() +{ + picoquic_quic_t* quic = NULL; + picoquic_cnx_t* cnx = NULL; + int ret = picoquic_test_set_minimal_cnx(&quic, &cnx); + uint64_t stream_id = 3; + h3zero_stream_ctx_t* control_stream_ctx; + h3zero_stream_ctx_t* stream_ctx = NULL; + h3zero_callback_ctx_t* h3_ctx = NULL; + uint8_t unidir_input[] = { 0x40, 0x54, 0x04, 0xf0 }; + size_t chunk = 2; + + + if (ret == 0) { + h3_ctx = h3zero_callback_create_context(NULL); + if (h3_ctx == NULL) { + ret = -1; + } + else { + picoquic_set_callback(cnx, h3zero_callback, h3_ctx); + } + } + + if (ret == 0) { + control_stream_ctx = picowt_set_control_stream(cnx, h3_ctx); + if (control_stream_ctx == NULL) { + ret = -1; + } + else { + unidir_input[2] = (uint8_t)control_stream_ctx->stream_id; + /* Need to program a stream prefix that matches the connection */ + ret = h3zero_declare_stream_prefix(h3_ctx, control_stream_ctx->stream_id, incoming_unidir_test_fn, NULL); } } + + if (ret == 0) { + stream_ctx = h3zero_find_or_create_stream(cnx, stream_id, h3_ctx, 1, 1); + if (stream_ctx == NULL) { + ret = -1; + } + } + + picoquic_set_app_stream_ctx(cnx, stream_id, stream_ctx); + + if (ret == 0) { + int success = 0; + + for (size_t i = 0; ret == 0 && i < 4; i++) { + uint8_t * bytes = &unidir_input[i]; + uint8_t * bytes_max = bytes + 1; + bytes = h3zero_parse_incoming_remote_stream(bytes, bytes_max, stream_ctx, h3_ctx); + if (bytes == bytes_max) { + continue; + } + else if (bytes == NULL) { + ret = -1; + } + else if (bytes != &unidir_input[3]) { + ret = -1; + } + else { + success = 1; + } + } + if (!success) { + ret = -1; + } + } + + h3zero_callback_delete_context(cnx, h3_ctx); + picoquic_test_delete_minimal_cnx(&quic, &cnx); + return ret; } \ No newline at end of file diff --git a/picoquictest/picoquictest.h b/picoquictest/picoquictest.h index e7a64f9fa..39729d663 100644 --- a/picoquictest/picoquictest.h +++ b/picoquictest/picoquictest.h @@ -281,6 +281,7 @@ int cid_length_test(); int initial_server_close_test(); int h3zero_integer_test(); int h3zero_varint_stream_test(); +int h3zero_incoming_unidir_test(); int qpack_huffman_test(); int qpack_huffman_base_test(); int h3zero_parse_qpack_test(); From d3dcabd46f7be755dfd78bc0cf9bff865d2f7b69 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Fri, 15 Mar 2024 20:46:33 -0700 Subject: [PATCH 3/4] Fix use callback after free --- picohttp/h3zero_common.c | 1 + 1 file changed, 1 insertion(+) diff --git a/picohttp/h3zero_common.c b/picohttp/h3zero_common.c index a5bd5ab32..2653280f3 100644 --- a/picohttp/h3zero_common.c +++ b/picohttp/h3zero_common.c @@ -805,6 +805,7 @@ void h3zero_callback_delete_context(picoquic_cnx_t* cnx, h3zero_callback_ctx_t* { h3zero_delete_all_stream_prefixes(cnx, ctx); picosplay_empty_tree(&ctx->h3_stream_tree); + picoquic_set_callback(cnx, NULL, NULL); free(ctx); } From ba10749c41c87d95e7a0b3e5982d09952112a1b5 Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Fri, 15 Mar 2024 21:08:46 -0700 Subject: [PATCH 4/4] Better fix of memroy issue. --- picohttp/h3zero_common.c | 1 - picoquictest/h3zero_stream_test.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/picohttp/h3zero_common.c b/picohttp/h3zero_common.c index 2653280f3..a5bd5ab32 100644 --- a/picohttp/h3zero_common.c +++ b/picohttp/h3zero_common.c @@ -805,7 +805,6 @@ void h3zero_callback_delete_context(picoquic_cnx_t* cnx, h3zero_callback_ctx_t* { h3zero_delete_all_stream_prefixes(cnx, ctx); picosplay_empty_tree(&ctx->h3_stream_tree); - picoquic_set_callback(cnx, NULL, NULL); free(ctx); } diff --git a/picoquictest/h3zero_stream_test.c b/picoquictest/h3zero_stream_test.c index fe01f9a9d..3e5d93b17 100644 --- a/picoquictest/h3zero_stream_test.c +++ b/picoquictest/h3zero_stream_test.c @@ -265,7 +265,7 @@ int h3zero_incoming_unidir_test() ret = -1; } } - + picoquic_set_callback(cnx, NULL, NULL); h3zero_callback_delete_context(cnx, h3_ctx); picoquic_test_delete_minimal_cnx(&quic, &cnx);