Skip to content

Commit 9b41819

Browse files
Simplify AutoCommissioner::SetCommissioningParameters (project-chip#36896)
Unconditionally clear members that point to buffers, and handle them via the explicit code that copies the pointed-to data. The logic to work out whether any pointers need to be cleared was quite complicated. Use memmove() instead of memcpy() since src and dst may overlap / be identical. Always assign mNeedIcdRegistration when the kReadCommissioningInfo step finishes, instead of relying on SetCommissioningParameters to clear it.
1 parent aac3e3f commit 9b41819

File tree

2 files changed

+22
-71
lines changed

2 files changed

+22
-71
lines changed

src/controller/AutoCommissioner.cpp

+16-68
Original file line numberDiff line numberDiff line change
@@ -49,25 +49,6 @@ void AutoCommissioner::SetOperationalCredentialsDelegate(OperationalCredentialsD
4949
mOperationalCredentialsDelegate = operationalCredentialsDelegate;
5050
}
5151

52-
// Returns true if maybeUnsafeSpan is pointing to a buffer that we're not sure
53-
// will live for long enough. knownSafeSpan, if it has a value, points to a
54-
// buffer that we _are_ sure will live for long enough.
55-
template <typename SpanType>
56-
static bool IsUnsafeSpan(const Optional<SpanType> & maybeUnsafeSpan, const Optional<SpanType> & knownSafeSpan)
57-
{
58-
if (!maybeUnsafeSpan.HasValue())
59-
{
60-
return false;
61-
}
62-
63-
if (!knownSafeSpan.HasValue())
64-
{
65-
return true;
66-
}
67-
68-
return maybeUnsafeSpan.Value().data() != knownSafeSpan.Value().data();
69-
}
70-
7152
CHIP_ERROR AutoCommissioner::VerifyICDRegistrationInfo(const CommissioningParameters & params)
7253
{
7354
ChipLogProgress(Controller, "Checking ICD registration parameters");
@@ -101,56 +82,26 @@ CHIP_ERROR AutoCommissioner::VerifyICDRegistrationInfo(const CommissioningParame
10182

10283
CHIP_ERROR AutoCommissioner::SetCommissioningParameters(const CommissioningParameters & params)
10384
{
104-
// Make sure any members that point to buffers that we are not pointing to
105-
// our own buffers are not going to dangle. We can skip this step if all
106-
// the buffers pointers that we don't plan to re-point to our own buffers
107-
// below are already pointing to the same things as our own buffer pointers
108-
// (so that we know they have to be safe somehow).
109-
//
110-
// The checks are a bit painful, because Span does not have a usable
111-
// operator==, and in any case, we want to compare for pointer equality, not
112-
// data equality.
113-
bool haveMaybeDanglingBufferPointers =
114-
((params.GetNOCChainGenerationParameters().HasValue() &&
115-
(!mParams.GetNOCChainGenerationParameters().HasValue() ||
116-
params.GetNOCChainGenerationParameters().Value().nocsrElements.data() !=
117-
mParams.GetNOCChainGenerationParameters().Value().nocsrElements.data() ||
118-
params.GetNOCChainGenerationParameters().Value().signature.data() !=
119-
mParams.GetNOCChainGenerationParameters().Value().signature.data())) ||
120-
IsUnsafeSpan(params.GetRootCert(), mParams.GetRootCert()) || IsUnsafeSpan(params.GetNoc(), mParams.GetNoc()) ||
121-
IsUnsafeSpan(params.GetIcac(), mParams.GetIcac()) || IsUnsafeSpan(params.GetIpk(), mParams.GetIpk()) ||
122-
IsUnsafeSpan(params.GetAttestationElements(), mParams.GetAttestationElements()) ||
123-
IsUnsafeSpan(params.GetAttestationSignature(), mParams.GetAttestationSignature()) ||
124-
IsUnsafeSpan(params.GetPAI(), mParams.GetPAI()) || IsUnsafeSpan(params.GetDAC(), mParams.GetDAC()) ||
125-
IsUnsafeSpan(params.GetTimeZone(), mParams.GetTimeZone()) ||
126-
IsUnsafeSpan(params.GetDSTOffsets(), mParams.GetDSTOffsets()) ||
127-
IsUnsafeSpan(params.GetICDSymmetricKey(), mParams.GetICDSymmetricKey()) ||
128-
(params.GetDefaultNTP().HasValue() && !params.GetDefaultNTP().Value().IsNull() &&
129-
params.GetDefaultNTP().Value().Value().data() != mDefaultNtp));
130-
85+
// Our logic below assumes that we can modify mParams without affecting params.
86+
VerifyOrReturnError(&params != &mParams, CHIP_NO_ERROR);
87+
88+
// Copy the whole struct (scalars and pointers), but clear any members that might point to
89+
// external buffers. For those members we have to copy the data over into our own buffers below.
90+
// Note that all of the copy operations use memmove() instead of memcpy(), because the caller
91+
// may be passing a modified shallow copy of our CommissioningParmeters, i.e. where various spans
92+
// already point into the buffers we're copying into, and memcpy() with overlapping buffers is UB.
13193
mParams = params;
132-
133-
mNeedIcdRegistration = false;
134-
135-
if (haveMaybeDanglingBufferPointers)
136-
{
137-
mParams.ClearExternalBufferDependentValues();
138-
}
139-
140-
// For members of params that point to some sort of buffer, we have to copy
141-
// the data over into our own buffers.
94+
mParams.ClearExternalBufferDependentValues();
14295

14396
if (params.GetThreadOperationalDataset().HasValue())
14497
{
14598
ByteSpan dataset = params.GetThreadOperationalDataset().Value();
14699
if (dataset.size() > CommissioningParameters::kMaxThreadDatasetLen)
147100
{
148101
ChipLogError(Controller, "Thread operational data set is too large");
149-
// Make sure our buffer pointers don't dangle.
150-
mParams.ClearExternalBufferDependentValues();
151102
return CHIP_ERROR_INVALID_ARGUMENT;
152103
}
153-
memcpy(mThreadOperationalDataset, dataset.data(), dataset.size());
104+
memmove(mThreadOperationalDataset, dataset.data(), dataset.size());
154105
ChipLogProgress(Controller, "Setting thread operational dataset from parameters");
155106
mParams.SetThreadOperationalDataset(ByteSpan(mThreadOperationalDataset, dataset.size()));
156107
}
@@ -162,12 +113,10 @@ CHIP_ERROR AutoCommissioner::SetCommissioningParameters(const CommissioningParam
162113
creds.credentials.size() > CommissioningParameters::kMaxCredentialsLen)
163114
{
164115
ChipLogError(Controller, "Wifi credentials are too large");
165-
// Make sure our buffer pointers don't dangle.
166-
mParams.ClearExternalBufferDependentValues();
167116
return CHIP_ERROR_INVALID_ARGUMENT;
168117
}
169-
memcpy(mSsid, creds.ssid.data(), creds.ssid.size());
170-
memcpy(mCredentials, creds.credentials.data(), creds.credentials.size());
118+
memmove(mSsid, creds.ssid.data(), creds.ssid.size());
119+
memmove(mCredentials, creds.credentials.data(), creds.credentials.size());
171120
ChipLogProgress(Controller, "Setting wifi credentials from parameters");
172121
mParams.SetWiFiCredentials(
173122
WiFiCredentials(ByteSpan(mSsid, creds.ssid.size()), ByteSpan(mCredentials, creds.credentials.size())));
@@ -184,8 +133,6 @@ CHIP_ERROR AutoCommissioner::SetCommissioningParameters(const CommissioningParam
184133
else
185134
{
186135
ChipLogError(Controller, "Country code is too large: %u", static_cast<unsigned>(code.size()));
187-
// Make sure our buffer pointers don't dangle.
188-
mParams.ClearExternalBufferDependentValues();
189136
return CHIP_ERROR_INVALID_ARGUMENT;
190137
}
191138
}
@@ -195,7 +142,7 @@ CHIP_ERROR AutoCommissioner::SetCommissioningParameters(const CommissioningParam
195142
{
196143
ChipLogProgress(Controller, "Setting attestation nonce from parameters");
197144
VerifyOrReturnError(params.GetAttestationNonce().Value().size() == sizeof(mAttestationNonce), CHIP_ERROR_INVALID_ARGUMENT);
198-
memcpy(mAttestationNonce, params.GetAttestationNonce().Value().data(), params.GetAttestationNonce().Value().size());
145+
memmove(mAttestationNonce, params.GetAttestationNonce().Value().data(), params.GetAttestationNonce().Value().size());
199146
}
200147
else
201148
{
@@ -208,7 +155,7 @@ CHIP_ERROR AutoCommissioner::SetCommissioningParameters(const CommissioningParam
208155
{
209156
ChipLogProgress(Controller, "Setting CSR nonce from parameters");
210157
VerifyOrReturnError(params.GetCSRNonce().Value().size() == sizeof(mCSRNonce), CHIP_ERROR_INVALID_ARGUMENT);
211-
memcpy(mCSRNonce, params.GetCSRNonce().Value().data(), params.GetCSRNonce().Value().size());
158+
memmove(mCSRNonce, params.GetCSRNonce().Value().data(), params.GetCSRNonce().Value().size());
212159
}
213160
else
214161
{
@@ -271,7 +218,7 @@ CHIP_ERROR AutoCommissioner::SetCommissioningParameters(const CommissioningParam
271218
ReturnErrorOnFailure(VerifyICDRegistrationInfo(params));
272219

273220
// The values must be valid now.
274-
memcpy(mICDSymmetricKey, params.GetICDSymmetricKey().Value().data(), params.GetICDSymmetricKey().Value().size());
221+
memmove(mICDSymmetricKey, params.GetICDSymmetricKey().Value().data(), params.GetICDSymmetricKey().Value().size());
275222
mParams.SetICDSymmetricKey(ByteSpan(mICDSymmetricKey));
276223
mParams.SetICDCheckInNodeId(params.GetICDCheckInNodeId().Value());
277224
mParams.SetICDMonitoredSubject(params.GetICDMonitoredSubject().Value());
@@ -787,6 +734,7 @@ CHIP_ERROR AutoCommissioner::CommissioningStepFinished(CHIP_ERROR err, Commissio
787734
}
788735
}
789736

737+
mNeedIcdRegistration = false;
790738
if (mParams.GetICDRegistrationStrategy() != ICDRegistrationStrategy::kIgnore)
791739
{
792740
if (mDeviceCommissioningInfo.icd.isLIT && mDeviceCommissioningInfo.icd.checkInProtocolSupport)

src/lib/support/Span.h

+6-3
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,8 @@ inline CHIP_ERROR CopySpanToMutableSpan(ByteSpan span_to_copy, MutableByteSpan &
374374
{
375375
VerifyOrReturnError(out_buf.size() >= span_to_copy.size(), CHIP_ERROR_BUFFER_TOO_SMALL);
376376

377-
memcpy(out_buf.data(), span_to_copy.data(), span_to_copy.size());
377+
// There is no guarantee that span_to_copy and out_buf don't overlap, so use memmove()
378+
memmove(out_buf.data(), span_to_copy.data(), span_to_copy.size());
378379
out_buf.reduce_size(span_to_copy.size());
379380

380381
return CHIP_NO_ERROR;
@@ -384,7 +385,8 @@ inline CHIP_ERROR CopyCharSpanToMutableCharSpan(CharSpan cspan_to_copy, MutableC
384385
{
385386
VerifyOrReturnError(out_buf.size() >= cspan_to_copy.size(), CHIP_ERROR_BUFFER_TOO_SMALL);
386387

387-
memcpy(out_buf.data(), cspan_to_copy.data(), cspan_to_copy.size());
388+
// There is no guarantee that cspan_to_copy and out_buf don't overlap, so use memmove()
389+
memmove(out_buf.data(), cspan_to_copy.data(), cspan_to_copy.size());
388390
out_buf.reduce_size(cspan_to_copy.size());
389391

390392
return CHIP_NO_ERROR;
@@ -400,7 +402,8 @@ inline void CopyCharSpanToMutableCharSpanWithTruncation(CharSpan span_to_copy, M
400402
{
401403
size_t size_to_copy = std::min(span_to_copy.size(), out_span.size());
402404

403-
memcpy(out_span.data(), span_to_copy.data(), size_to_copy);
405+
// There is no guarantee that span_to_copy and out_buf don't overlap, so use memmove()
406+
memmove(out_span.data(), span_to_copy.data(), size_to_copy);
404407
out_span.reduce_size(size_to_copy);
405408
}
406409

0 commit comments

Comments
 (0)