diff --git a/include/picotls.h b/include/picotls.h index e0c390811..3542c3a40 100644 --- a/include/picotls.h +++ b/include/picotls.h @@ -248,6 +248,7 @@ extern "C" { #define PTLS_ERROR_REJECT_EARLY_DATA (PTLS_ERROR_CLASS_INTERNAL + 9) #define PTLS_ERROR_DELEGATE (PTLS_ERROR_CLASS_INTERNAL + 10) #define PTLS_ERROR_ASYNC_OPERATION (PTLS_ERROR_CLASS_INTERNAL + 11) +#define PTLS_ERROR_BLOCK_OVERFLOW (PTLS_ERROR_CLASS_INTERNAL + 12) #define PTLS_ERROR_INCORRECT_BASE64 (PTLS_ERROR_CLASS_INTERNAL + 50) #define PTLS_ERROR_PEM_LABEL_NOT_FOUND (PTLS_ERROR_CLASS_INTERNAL + 51) @@ -1203,6 +1204,10 @@ static uint8_t *ptls_encode_quicint(uint8_t *p, uint64_t v); } while (0); \ size_t body_size = (buf)->off - body_start; \ if (capacity != -1) { \ + if (capacity < sizeof(size_t) && body_size >= (size_t)1 << (capacity * 8)) { \ + ret = PTLS_ERROR_BLOCK_OVERFLOW; \ + goto Exit; \ + } \ for (; capacity != 0; --capacity) \ (buf)->base[body_start - capacity] = (uint8_t)(body_size >> (8 * (capacity - 1))); \ } else { \ diff --git a/t/picotls.c b/t/picotls.c index c82cc414a..8bc5ab444 100644 --- a/t/picotls.c +++ b/t/picotls.c @@ -1901,6 +1901,60 @@ static void test_all_handshakes(void) ctx->sign_certificate = second_sc_orig; } +static void do_test_tlsblock(size_t len_encoded, size_t max_bytes) +{ + ptls_buffer_t buf; + const uint8_t *src, *end; + int expect_overflow = 0, ret; + + /* block that fits in */ + ptls_buffer_init(&buf, "", 0); + ptls_buffer_push_block(&buf, len_encoded, { + for (size_t i = 0; i < max_bytes; ++i) + ptls_buffer_push(&buf, (uint8_t)i); + }); + src = buf.base; + end = buf.base + buf.off; + ptls_decode_block(src, end, len_encoded, { + ok(end - src == max_bytes); + int bytes_eq = 1; + for (size_t i = 0; i < max_bytes; ++i) { + if (src[i] != (uint8_t)i) + bytes_eq = 0; + } + ok(bytes_eq); + src = end; + }); + + /* block that does not fit in */ + ptls_buffer_push_block(&buf, len_encoded, { + for (size_t i = 0; i < max_bytes + 1; i++) + ptls_buffer_push(&buf, 1); + expect_overflow = 1; + }); + ok(!"fail"); + +Exit: + if (ret != 0) { + if (expect_overflow) { + ok(ret == PTLS_ERROR_BLOCK_OVERFLOW); + } else { + ok(!"fail"); + } + } + ptls_buffer_dispose(&buf); +} + +static void test_tlsblock8(void) +{ + do_test_tlsblock(1, 255); +} + +static void test_tlsblock16(void) +{ + do_test_tlsblock(2, 65535); +} + static void test_quicint(void) { #define CHECK_PATTERN(output, ...) \ @@ -2161,6 +2215,8 @@ void test_picotls(void) subtest("chacha20", test_chacha20); subtest("ffx", test_ffx); subtest("base64-decode", test_base64_decode); + subtest("tls-block8", test_tlsblock8); + subtest("tls-block16", test_tlsblock16); subtest("ech", test_ech); subtest("fragmented-message", test_fragmented_message); subtest("handshake", test_all_handshakes);