Skip to content

Commit ce572d6

Browse files
davidbenBoringssl LUCI CQ
authored andcommitted
Standardize on Init vs InitForOverwrite for value vs default initialization
C++ is fun and has two notions of "default" initialization, `new T` and `new T()`. These are default initialization and value initialization, respectively. They are identical except that POD types are uninit when default-initialized and zero when value-initialized. InplaceVector picked the safer option by default and called the other one FooMaybeUninit. Array is older and uses the less safe one (it's almost always the one we want; we usually allocate an array to immediately fill it). While MaybeUninit does capture what you do with it, it is slightly ambiguous, as seen in Array's internal implementation: uninitialized could also mean we haven't gotten around to initialize it at all. I.e. we need to use a function like std::uninitialized_value_construct_n instead of normal functions in <algorithm>. C++20 has std::make_unique and std::make_unique_for_overwrite to capture the two. This seems as fine a naming convention as any, so switch to it. Along the way, make the internal bssl::Array default to the safer one. This lets us remove a couple of memset(0)'s. Change-Id: I32cede231da051a854e6251e10b87f8e4dd06ee6 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/72268 Reviewed-by: Nick Harper <[email protected]> Commit-Queue: David Benjamin <[email protected]>
1 parent 4f76523 commit ce572d6

16 files changed

+74
-58
lines changed

ssl/d1_both.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -785,7 +785,7 @@ static int send_flight(SSL *ssl) {
785785
dtls1_update_mtu(ssl);
786786

787787
Array<uint8_t> packet;
788-
if (!packet.Init(ssl->d1->mtu)) {
788+
if (!packet.InitForOverwrite(ssl->d1->mtu)) {
789789
return -1;
790790
}
791791

ssl/encrypted_client_hello.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ bool ssl_client_hello_decrypt(SSL_HANDSHAKE *hs, uint8_t *out_alert,
303303
return false;
304304
}
305305
#else
306-
if (!encoded.Init(payload.size())) {
306+
if (!encoded.InitForOverwrite(payload.size())) {
307307
*out_alert = SSL_AD_INTERNAL_ERROR;
308308
return false;
309309
}

ssl/extensions.cc

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ static bool tls1_check_duplicate_extensions(const CBS *cbs) {
175175
}
176176

177177
Array<uint16_t> extension_types;
178-
if (!extension_types.Init(num_extensions)) {
178+
if (!extension_types.InitForOverwrite(num_extensions)) {
179179
return false;
180180
}
181181

@@ -2526,7 +2526,7 @@ static bool parse_u16_array(const CBS *cbs, Array<uint16_t> *out) {
25262526
}
25272527

25282528
Array<uint16_t> ret;
2529-
if (!ret.Init(CBS_len(&copy) / 2)) {
2529+
if (!ret.InitForOverwrite(CBS_len(&copy) / 2)) {
25302530
return false;
25312531
}
25322532
for (size_t i = 0; i < ret.size(); i++) {
@@ -2878,7 +2878,7 @@ static bool cert_compression_parse_clienthello(SSL_HANDSHAKE *hs,
28782878

28792879
const size_t num_given_alg_ids = CBS_len(&alg_ids) / 2;
28802880
Array<uint16_t> given_alg_ids;
2881-
if (!given_alg_ids.Init(num_given_alg_ids)) {
2881+
if (!given_alg_ids.InitForOverwrite(num_given_alg_ids)) {
28822882
return false;
28832883
}
28842884

@@ -3352,7 +3352,7 @@ bool ssl_setup_extension_permutation(SSL_HANDSHAKE *hs) {
33523352
uint32_t seeds[kNumExtensions - 1];
33533353
Array<uint8_t> permutation;
33543354
if (!RAND_bytes(reinterpret_cast<uint8_t *>(seeds), sizeof(seeds)) ||
3355-
!permutation.Init(kNumExtensions)) {
3355+
!permutation.InitForOverwrite(kNumExtensions)) {
33563356
return false;
33573357
}
33583358
for (size_t i = 0; i < kNumExtensions; i++) {
@@ -3918,7 +3918,7 @@ static enum ssl_ticket_aead_result_t decrypt_ticket_with_cipher_ctx(
39183918
if (ciphertext.size() >= INT_MAX) {
39193919
return ssl_ticket_aead_ignore_ticket;
39203920
}
3921-
if (!plaintext.Init(ciphertext.size())) {
3921+
if (!plaintext.InitForOverwrite(ciphertext.size())) {
39223922
return ssl_ticket_aead_error;
39233923
}
39243924
int len1, len2;
@@ -4006,7 +4006,7 @@ static enum ssl_ticket_aead_result_t ssl_decrypt_ticket_with_method(
40064006
SSL_HANDSHAKE *hs, Array<uint8_t> *out, bool *out_renew_ticket,
40074007
Span<const uint8_t> ticket) {
40084008
Array<uint8_t> plaintext;
4009-
if (!plaintext.Init(ticket.size())) {
4009+
if (!plaintext.InitForOverwrite(ticket.size())) {
40104010
return ssl_ticket_aead_error;
40114011
}
40124012

@@ -4115,7 +4115,7 @@ enum ssl_ticket_aead_result_t ssl_process_ticket(
41154115
// Envoy's tests expect the session to have a session ID that matches the
41164116
// placeholder used by the client. It's unclear whether this is a good idea,
41174117
// but we maintain it for now.
4118-
session->session_id.ResizeMaybeUninit(SHA256_DIGEST_LENGTH);
4118+
session->session_id.ResizeForOverwrite(SHA256_DIGEST_LENGTH);
41194119
SHA256(ticket.data(), ticket.size(), session->session_id.data());
41204120

41214121
*out_session = std::move(session);
@@ -4356,7 +4356,7 @@ bool tls1_record_handshake_hashes_for_channel_id(SSL_HANDSHAKE *hs) {
43564356
}
43574357

43584358
size_t digest_len;
4359-
hs->new_session->original_handshake_hash.ResizeMaybeUninit(
4359+
hs->new_session->original_handshake_hash.ResizeForOverwrite(
43604360
hs->transcript.DigestLen());
43614361
if (!hs->transcript.GetHash(hs->new_session->original_handshake_hash.data(),
43624362
&digest_len)) {

ssl/handoff.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ static bool apply_remote_features(SSL *ssl, CBS *in) {
176176
return false;
177177
}
178178
Array<uint16_t> supported_groups;
179-
if (!supported_groups.Init(CBS_len(&groups) / 2)) {
179+
if (!supported_groups.InitForOverwrite(CBS_len(&groups) / 2)) {
180180
return false;
181181
}
182182
size_t idx = 0;
@@ -190,7 +190,7 @@ static bool apply_remote_features(SSL *ssl, CBS *in) {
190190
Span<const uint16_t> configured_groups =
191191
tls1_get_grouplist(ssl->s3->hs.get());
192192
Array<uint16_t> new_configured_groups;
193-
if (!new_configured_groups.Init(configured_groups.size())) {
193+
if (!new_configured_groups.InitForOverwrite(configured_groups.size())) {
194194
return false;
195195
}
196196
idx = 0;

ssl/handshake_client.cc

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,7 @@ static enum ssl_hs_wait_t do_start_connect(SSL_HANDSHAKE *hs) {
542542
if (has_id_session) {
543543
hs->session_id = ssl->session->session_id;
544544
} else if (ticket_session_requires_random_id || enable_compatibility_mode) {
545-
hs->session_id.ResizeMaybeUninit(SSL_MAX_SSL_SESSION_ID_LENGTH);
545+
hs->session_id.ResizeForOverwrite(SSL_MAX_SSL_SESSION_ID_LENGTH);
546546
if (!RAND_bytes(hs->session_id.data(), hs->session_id.size())) {
547547
return ssl_hs_error;
548548
}
@@ -1528,16 +1528,15 @@ static enum ssl_hs_wait_t do_send_client_key_exchange(SSL_HANDSHAKE *hs) {
15281528

15291529
// Depending on the key exchange method, compute |pms|.
15301530
if (alg_k & SSL_kRSA) {
1531-
if (!pms.Init(SSL_MAX_MASTER_KEY_LENGTH)) {
1532-
return ssl_hs_error;
1533-
}
1534-
15351531
RSA *rsa = EVP_PKEY_get0_RSA(hs->peer_pubkey.get());
15361532
if (rsa == NULL) {
15371533
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
15381534
return ssl_hs_error;
15391535
}
15401536

1537+
if (!pms.InitForOverwrite(SSL_MAX_MASTER_KEY_LENGTH)) {
1538+
return ssl_hs_error;
1539+
}
15411540
pms[0] = hs->client_version >> 8;
15421541
pms[1] = hs->client_version & 0xff;
15431542
if (!RAND_bytes(&pms[2], SSL_MAX_MASTER_KEY_LENGTH - 2)) {
@@ -1581,7 +1580,6 @@ static enum ssl_hs_wait_t do_send_client_key_exchange(SSL_HANDSHAKE *hs) {
15811580
if (!pms.Init(psk_len)) {
15821581
return ssl_hs_error;
15831582
}
1584-
OPENSSL_memset(pms.data(), 0, pms.size());
15851583
} else {
15861584
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
15871585
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
@@ -1609,7 +1607,7 @@ static enum ssl_hs_wait_t do_send_client_key_exchange(SSL_HANDSHAKE *hs) {
16091607
return ssl_hs_error;
16101608
}
16111609

1612-
hs->new_session->secret.ResizeMaybeUninit(SSL3_MASTER_SECRET_SIZE);
1610+
hs->new_session->secret.ResizeForOverwrite(SSL3_MASTER_SECRET_SIZE);
16131611
if (!tls1_generate_master_secret(hs, MakeSpan(hs->new_session->secret),
16141612
pms)) {
16151613
return ssl_hs_error;
@@ -1850,7 +1848,7 @@ static enum ssl_hs_wait_t do_read_session_ticket(SSL_HANDSHAKE *hs) {
18501848

18511849
// Historically, OpenSSL filled in fake session IDs for ticket-based sessions.
18521850
// TODO(davidben): Are external callers relying on this? Try removing this.
1853-
hs->new_session->session_id.ResizeMaybeUninit(SHA256_DIGEST_LENGTH);
1851+
hs->new_session->session_id.ResizeForOverwrite(SHA256_DIGEST_LENGTH);
18541852
SHA256(CBS_data(&ticket), CBS_len(&ticket),
18551853
hs->new_session->session_id.data());
18561854

ssl/handshake_server.cc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -941,7 +941,7 @@ static enum ssl_hs_wait_t do_select_parameters(SSL_HANDSHAKE *hs) {
941941
// Assign a session ID if not using session tickets.
942942
if (!hs->ticket_expected &&
943943
(ssl->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER)) {
944-
hs->new_session->session_id.ResizeMaybeUninit(SSL3_SSL_SESSION_ID_LENGTH);
944+
hs->new_session->session_id.ResizeForOverwrite(SSL3_SSL_SESSION_ID_LENGTH);
945945
RAND_bytes(hs->new_session->session_id.data(),
946946
hs->new_session->session_id.size());
947947
}
@@ -1464,7 +1464,8 @@ static enum ssl_hs_wait_t do_read_client_key_exchange(SSL_HANDSHAKE *hs) {
14641464

14651465
// Allocate a buffer large enough for an RSA decryption.
14661466
Array<uint8_t> decrypt_buf;
1467-
if (!decrypt_buf.Init(EVP_PKEY_size(hs->credential->pubkey.get()))) {
1467+
if (!decrypt_buf.InitForOverwrite(
1468+
EVP_PKEY_size(hs->credential->pubkey.get()))) {
14681469
return ssl_hs_error;
14691470
}
14701471

@@ -1492,7 +1493,7 @@ static enum ssl_hs_wait_t do_read_client_key_exchange(SSL_HANDSHAKE *hs) {
14921493

14931494
// Prepare a random premaster, to be used on invalid padding. See RFC 5246,
14941495
// section 7.4.7.1.
1495-
if (!premaster_secret.Init(SSL_MAX_MASTER_KEY_LENGTH) ||
1496+
if (!premaster_secret.InitForOverwrite(SSL_MAX_MASTER_KEY_LENGTH) ||
14961497
!RAND_bytes(premaster_secret.data(), premaster_secret.size())) {
14971498
return ssl_hs_error;
14981499
}
@@ -1583,7 +1584,6 @@ static enum ssl_hs_wait_t do_read_client_key_exchange(SSL_HANDSHAKE *hs) {
15831584
if (!premaster_secret.Init(psk_len)) {
15841585
return ssl_hs_error;
15851586
}
1586-
OPENSSL_memset(premaster_secret.data(), 0, premaster_secret.size());
15871587
}
15881588

15891589
ScopedCBB new_premaster;
@@ -1605,7 +1605,7 @@ static enum ssl_hs_wait_t do_read_client_key_exchange(SSL_HANDSHAKE *hs) {
16051605
}
16061606

16071607
// Compute the master secret.
1608-
hs->new_session->secret.ResizeMaybeUninit(SSL3_MASTER_SECRET_SIZE);
1608+
hs->new_session->secret.ResizeForOverwrite(SSL3_MASTER_SECRET_SIZE);
16091609
if (!tls1_generate_master_secret(hs, MakeSpan(hs->new_session->secret),
16101610
premaster_secret)) {
16111611
return ssl_hs_error;

ssl/internal.h

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -334,11 +334,21 @@ class Array {
334334
}
335335

336336
// Init replaces the array with a newly-allocated array of |new_size|
337-
// default-constructed copies of |T|. It returns true on success and false on
338-
// error.
339-
//
340-
// Note that if |T| is a primitive type like |uint8_t|, it is uninitialized.
337+
// value-constructed copies of |T|. It returns true on success and false on
338+
// error. If |T| is a primitive type like |uint8_t|, value-construction means
339+
// it will be zero-initialized.
341340
bool Init(size_t new_size) {
341+
if (!InitUninitialized(new_size)) {
342+
return false;
343+
}
344+
cxx17_uninitialized_value_construct_n(data_, size_);
345+
return true;
346+
}
347+
348+
// InitForOverwrite behaves like |Init| but it default-constructs each element
349+
// instead. This means that, if |T| is a primitive type, the array will be
350+
// uninitialized and thus must be filled in by the caller.
351+
bool InitForOverwrite(size_t new_size) {
342352
if (!InitUninitialized(new_size)) {
343353
return false;
344354
}
@@ -585,10 +595,10 @@ class InplaceVector {
585595
return true;
586596
}
587597

588-
// TryResizeMaybeUninit behaves like |TryResize|, but newly-added elements are
589-
// default-initialized, so POD types may contain uninitialized values that the
590-
// caller is responsible for filling in.
591-
bool TryResizeMaybeUninit(size_t new_size) {
598+
// TryResizeForOverwrite behaves like |TryResize|, but newly-added elements
599+
// are default-initialized, so POD types may contain uninitialized values that
600+
// the caller is responsible for filling in.
601+
bool TryResizeForOverwrite(size_t new_size) {
592602
if (new_size <= size_) {
593603
Shrink(new_size);
594604
return true;
@@ -628,8 +638,8 @@ class InplaceVector {
628638
// The following methods behave like their |Try*| counterparts, but abort the
629639
// program on failure.
630640
void Resize(size_t size) { BSSL_CHECK(TryResize(size)); }
631-
void ResizeMaybeUninit(size_t size) {
632-
BSSL_CHECK(TryResizeMaybeUninit(size));
641+
void ResizeForOverwrite(size_t size) {
642+
BSSL_CHECK(TryResizeForOverwrite(size));
633643
}
634644
void CopyFrom(Span<const T> in) { BSSL_CHECK(TryCopyFrom(in)); }
635645
T &PushBack(T val) {

ssl/ssl_cipher.cc

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -919,7 +919,6 @@ static bool ssl_cipher_strength_sort(CIPHER_ORDER **head_p,
919919
if (!number_uses.Init(max_strength_bits + 1)) {
920920
return false;
921921
}
922-
OPENSSL_memset(number_uses.data(), 0, (max_strength_bits + 1) * sizeof(int));
923922

924923
// Now find the strength_bits values actually used.
925924
curr = *head_p;
@@ -1231,7 +1230,7 @@ bool ssl_create_cipher_list(UniquePtr<SSLCipherPreferenceList> *out_cipher_list,
12311230
UniquePtr<STACK_OF(SSL_CIPHER)> cipherstack(sk_SSL_CIPHER_new_null());
12321231
Array<bool> in_group_flags;
12331232
if (cipherstack == nullptr ||
1234-
!in_group_flags.Init(OPENSSL_ARRAY_SIZE(kCiphers))) {
1233+
!in_group_flags.InitForOverwrite(OPENSSL_ARRAY_SIZE(kCiphers))) {
12351234
return false;
12361235
}
12371236

@@ -1246,13 +1245,11 @@ bool ssl_create_cipher_list(UniquePtr<SSLCipherPreferenceList> *out_cipher_list,
12461245
in_group_flags[num_in_group_flags++] = curr->in_group;
12471246
}
12481247
}
1248+
in_group_flags.Shrink(num_in_group_flags);
12491249

12501250
UniquePtr<SSLCipherPreferenceList> pref_list =
12511251
MakeUnique<SSLCipherPreferenceList>();
1252-
if (!pref_list ||
1253-
!pref_list->Init(
1254-
std::move(cipherstack),
1255-
MakeConstSpan(in_group_flags).subspan(0, num_in_group_flags))) {
1252+
if (!pref_list || !pref_list->Init(std::move(cipherstack), in_group_flags)) {
12561253
return false;
12571254
}
12581255

ssl/ssl_credential.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ bool ssl_get_credential_list(SSL_HANDSHAKE *hs, Array<SSL_CREDENTIAL *> *out) {
4848
num_creds++;
4949
}
5050

51-
if (!out->Init(num_creds)) {
51+
if (!out->InitForOverwrite(num_creds)) {
5252
return false;
5353
}
5454

ssl/ssl_internal_test.cc

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,15 @@
2323
BSSL_NAMESPACE_BEGIN
2424
namespace {
2525

26+
TEST(ArrayTest, InitValueConstructs) {
27+
Array<uint8_t> array;
28+
ASSERT_TRUE(array.Init(10));
29+
EXPECT_EQ(array.size(), 10u);
30+
for (size_t i = 0; i < 10u; i++) {
31+
EXPECT_EQ(0u, array[i]);
32+
}
33+
}
34+
2635
TEST(ArrayDeathTest, BoundsChecks) {
2736
Array<int> array;
2837
const int v[] = {1, 2, 3, 4};
@@ -345,7 +354,7 @@ TEST(InplaceVectorDeathTest, BoundsChecks) {
345354
EXPECT_DEATH_IF_SUPPORTED(vec[1000], "");
346355
// The vector cannot be resized past the capacity.
347356
EXPECT_DEATH_IF_SUPPORTED(vec.Resize(5), "");
348-
EXPECT_DEATH_IF_SUPPORTED(vec.ResizeMaybeUninit(5), "");
357+
EXPECT_DEATH_IF_SUPPORTED(vec.ResizeForOverwrite(5), "");
349358
int too_much_data[] = {1, 2, 3, 4, 5};
350359
EXPECT_DEATH_IF_SUPPORTED(vec.CopyFrom(too_much_data), "");
351360
vec.Resize(4);

ssl/ssl_key_share.cc

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ class ECKeyShare : public SSLKeyShare {
108108

109109
// Encode the x-coordinate left-padded with zeros.
110110
Array<uint8_t> secret;
111-
if (!secret.Init((EC_GROUP_get_degree(group_) + 7) / 8) ||
111+
if (!secret.InitForOverwrite((EC_GROUP_get_degree(group_) + 7) / 8) ||
112112
!BN_bn2bin_padded(secret.data(), secret.size(), x.get())) {
113113
return false;
114114
}
@@ -162,7 +162,7 @@ class X25519KeyShare : public SSLKeyShare {
162162
*out_alert = SSL_AD_INTERNAL_ERROR;
163163

164164
Array<uint8_t> secret;
165-
if (!secret.Init(32)) {
165+
if (!secret.InitForOverwrite(32)) {
166166
return false;
167167
}
168168

@@ -220,7 +220,7 @@ class X25519Kyber768KeyShare : public SSLKeyShare {
220220
bool Encap(CBB *out_ciphertext, Array<uint8_t> *out_secret,
221221
uint8_t *out_alert, Span<const uint8_t> peer_key) override {
222222
Array<uint8_t> secret;
223-
if (!secret.Init(32 + KYBER_SHARED_SECRET_BYTES)) {
223+
if (!secret.InitForOverwrite(32 + KYBER_SHARED_SECRET_BYTES)) {
224224
return false;
225225
}
226226

@@ -260,7 +260,7 @@ class X25519Kyber768KeyShare : public SSLKeyShare {
260260
*out_alert = SSL_AD_INTERNAL_ERROR;
261261

262262
Array<uint8_t> secret;
263-
if (!secret.Init(32 + KYBER_SHARED_SECRET_BYTES)) {
263+
if (!secret.InitForOverwrite(32 + KYBER_SHARED_SECRET_BYTES)) {
264264
return false;
265265
}
266266

@@ -308,7 +308,8 @@ class X25519MLKEM768KeyShare : public SSLKeyShare {
308308
bool Encap(CBB *out_ciphertext, Array<uint8_t> *out_secret,
309309
uint8_t *out_alert, Span<const uint8_t> peer_key) override {
310310
Array<uint8_t> secret;
311-
if (!secret.Init(MLKEM_SHARED_SECRET_BYTES + X25519_SHARED_KEY_LEN)) {
311+
if (!secret.InitForOverwrite(MLKEM_SHARED_SECRET_BYTES +
312+
X25519_SHARED_KEY_LEN)) {
312313
return false;
313314
}
314315

@@ -349,7 +350,8 @@ class X25519MLKEM768KeyShare : public SSLKeyShare {
349350
*out_alert = SSL_AD_INTERNAL_ERROR;
350351

351352
Array<uint8_t> secret;
352-
if (!secret.Init(MLKEM_SHARED_SECRET_BYTES + X25519_SHARED_KEY_LEN)) {
353+
if (!secret.InitForOverwrite(MLKEM_SHARED_SECRET_BYTES +
354+
X25519_SHARED_KEY_LEN)) {
353355
return false;
354356
}
355357

0 commit comments

Comments
 (0)