diff --git a/src/app/clusters/door-lock-server/door-lock-server.h b/src/app/clusters/door-lock-server/door-lock-server.h index 699852da219f73..36b339030c8b19 100644 --- a/src/app/clusters/door-lock-server/door-lock-server.h +++ b/src/app/clusters/door-lock-server/door-lock-server.h @@ -35,6 +35,9 @@ #include #include +#include +#include + #ifndef DOOR_LOCK_SERVER_ENDPOINT #define DOOR_LOCK_SERVER_ENDPOINT 1 #endif @@ -785,6 +788,34 @@ struct EmberAfPluginDoorLockCredentialInfo #if DOOR_LOCK_USE_LOCAL_BUFFER uint8_t credentialDataBuffer[DOOR_LOCK_CREDENTIAL_BUFFER_LENGTH]; EmberAfPluginDoorLockCredentialInfo() { credentialData = chip::MutableByteSpan(credentialDataBuffer); } + + // credentialData is a span into credentialDataBuffer, so the implicitly-defined copy would leave a + // copy's span pointing into the source's buffer (dangling once the source is gone). Deep-copy the + // bytes and re-bind the span to this object's own buffer. + EmberAfPluginDoorLockCredentialInfo(const EmberAfPluginDoorLockCredentialInfo & other) { *this = other; } + + EmberAfPluginDoorLockCredentialInfo & operator=(const EmberAfPluginDoorLockCredentialInfo & other) + { + if (this == &other) + { + return *this; + } + + status = other.status; + credentialType = other.credentialType; + creationSource = other.creationSource; + createdBy = other.createdBy; + modificationSource = other.modificationSource; + lastModifiedBy = other.lastModifiedBy; + + size_t dataLen = std::min(other.credentialData.size(), sizeof(credentialDataBuffer)); + if (dataLen > 0) + { + memcpy(credentialDataBuffer, other.credentialData.data(), dataLen); + } + credentialData = chip::MutableByteSpan(credentialDataBuffer, dataLen); + return *this; + } #endif }; @@ -818,6 +849,43 @@ struct EmberAfPluginDoorLockUserInfo userName = chip::MutableCharSpan(nameBuffer); credentials = chip::Span(credentialsBuffer); } + + // userName and credentials are spans into nameBuffer/credentialsBuffer, so the implicitly-defined + // copy would leave a copy's spans pointing into the source's buffers (dangling once the source is + // gone). Deep-copy the contents and re-bind the spans to this object's own buffers. + EmberAfPluginDoorLockUserInfo(const EmberAfPluginDoorLockUserInfo & other) { *this = other; } + + EmberAfPluginDoorLockUserInfo & operator=(const EmberAfPluginDoorLockUserInfo & other) + { + if (this == &other) + { + return *this; + } + + userUniqueId = other.userUniqueId; + userStatus = other.userStatus; + userType = other.userType; + credentialRule = other.credentialRule; + creationSource = other.creationSource; + createdBy = other.createdBy; + modificationSource = other.modificationSource; + lastModifiedBy = other.lastModifiedBy; + + size_t nameLen = std::min(other.userName.size(), sizeof(nameBuffer)); + if (nameLen > 0) + { + memcpy(nameBuffer, other.userName.data(), nameLen); + } + userName = chip::MutableCharSpan(nameBuffer, nameLen); + + size_t credentialCount = std::min(other.credentials.size(), sizeof(credentialsBuffer) / sizeof(credentialsBuffer[0])); + for (size_t i = 0; i < credentialCount; i++) + { + credentialsBuffer[i] = other.credentials[i]; + } + credentials = chip::Span(credentialsBuffer, credentialCount); + return *this; + } #endif };