Add an /* up to */ comment to all subspan calls that may truncate. bssl::Span::subspan, unlike std::span::subspan, is defined to truncate the output length if the input is too short. In order to allow for a migration to the standard behavior later, let's already add some comments to mark the places that will need adjusting. Change-Id: I5d37c730fd6ea131f3b3bfafe7ea0fe690906a22 Bug: 453872746 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/82928 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/ssl/d1_both.cc b/ssl/d1_both.cc index 1ef97b9..a4a84b3 100644 --- a/ssl/d1_both.cc +++ b/ssl/d1_both.cc
@@ -723,7 +723,7 @@ // Pack as many handshake fragments into one record as we can. We stage the // fragments in the output buffer, to be sealed in-place. bool should_continue = false; - Span<uint8_t> fragments = out.subspan(prefix_len, max_in_len); + Span<uint8_t> fragments = out.subspan(prefix_len, /* up to */ max_in_len); CBB cbb; CBB_init_fixed(&cbb, fragments.data(), fragments.size()); DTLSSentRecord sent_record;
diff --git a/ssl/encrypted_client_hello.cc b/ssl/encrypted_client_hello.cc index cac0358..be01d9c 100644 --- a/ssl/encrypted_client_hello.cc +++ b/ssl/encrypted_client_hello.cc
@@ -285,11 +285,21 @@ // We assert with |uintptr_t| because the comparison would be UB if they // didn't alias. + // - |payload| must be contained in |extensions|. assert(reinterpret_cast<uintptr_t>(client_hello_outer->extensions) <= reinterpret_cast<uintptr_t>(payload.data())); assert(reinterpret_cast<uintptr_t>(client_hello_outer->extensions + client_hello_outer->extensions_len) >= reinterpret_cast<uintptr_t>(payload.data() + payload.size())); + // - |extensions| must be contained in |client_hello|. + assert(reinterpret_cast<uintptr_t>(client_hello_outer->client_hello) <= + reinterpret_cast<uintptr_t>(client_hello_outer->extensions)); + assert(reinterpret_cast<uintptr_t>(client_hello_outer->client_hello + + client_hello_outer->client_hello_len) >= + reinterpret_cast<uintptr_t>(client_hello_outer->extensions + + client_hello_outer->extensions_len)); + // From this then follows that |aad|, being a copy of |client_hello|, contains + // the |payload| byte range as well. Span<uint8_t> payload_aad = Span(aad).subspan( payload.data() - client_hello_outer->client_hello, payload.size()); OPENSSL_memset(payload_aad.data(), 0, payload_aad.size());
diff --git a/ssl/internal.h b/ssl/internal.h index 0bcc083..e4cc29c 100644 --- a/ssl/internal.h +++ b/ssl/internal.h
@@ -127,7 +127,7 @@ span[0] = fixed_names[i]; span = span.subspan(1); } - span = span.subspan(0, objects.size()); + span = span.subspan(0, /* up to */ objects.size()); for (size_t i = 0; i < span.size(); i++) { span[i] = objects[i].*name; }
diff --git a/ssl/s3_both.cc b/ssl/s3_both.cc index b8c156b..898b549 100644 --- a/ssl/s3_both.cc +++ b/ssl/s3_both.cc
@@ -99,7 +99,8 @@ Span<const uint8_t> rest = msg; if (!SSL_is_quic(ssl) && ssl->s3->aead_write_ctx->is_null_cipher()) { while (!rest.empty()) { - Span<const uint8_t> chunk = rest.subspan(0, ssl->max_send_fragment); + Span<const uint8_t> chunk = + rest.subspan(0, /* up to */ ssl->max_send_fragment); rest = rest.subspan(chunk.size()); if (!add_record_to_flight(ssl, SSL3_RT_HANDSHAKE, chunk)) { @@ -118,7 +119,7 @@ size_t pending_len = ssl->s3->pending_hs_data ? ssl->s3->pending_hs_data->length : 0; Span<const uint8_t> chunk = - rest.subspan(0, ssl->max_send_fragment - pending_len); + rest.subspan(0, /* up to */ ssl->max_send_fragment - pending_len); assert(!chunk.empty()); rest = rest.subspan(chunk.size());