mirror of
https://github.com/espressif/openthread.git
synced 2026-09-05 16:50:05 +00:00
[message] update 'Write()' to use 'memmove()' instead of 'memcpy()' (#5462)
This change allows `CopyTo()` method to be used to copy bytes backwards within the same message (i.e., src and dest messages are the same and the dest offset is before src offset). Unit test `test_message` is updated in this commit to cover such a use. However, the `CopyTo()` implementing can still potentially overwrite the data when bytes are being copied forward within the same message. This commit adds an assert not allowing such a use and updates the method documentation mentioning this restriction.
This commit is contained in:
@@ -537,7 +537,7 @@ void Message::Write(uint16_t aOffset, uint16_t aLength, const void *aBuf)
|
|||||||
|
|
||||||
while (chunk.GetLength() > 0)
|
while (chunk.GetLength() > 0)
|
||||||
{
|
{
|
||||||
memcpy(chunk.GetData(), bufPtr, chunk.GetLength());
|
memmove(chunk.GetData(), bufPtr, chunk.GetLength());
|
||||||
bufPtr += chunk.GetLength();
|
bufPtr += chunk.GetLength();
|
||||||
GetNextChunk(aLength, chunk);
|
GetNextChunk(aLength, chunk);
|
||||||
}
|
}
|
||||||
@@ -548,6 +548,13 @@ uint16_t Message::CopyTo(uint16_t aSourceOffset, uint16_t aDestinationOffset, ui
|
|||||||
uint16_t bytesCopied = 0;
|
uint16_t bytesCopied = 0;
|
||||||
Chunk chunk;
|
Chunk chunk;
|
||||||
|
|
||||||
|
// This implementing can potentially overwrite the data when bytes are
|
||||||
|
// being copied forward within the same message, i.e., source and
|
||||||
|
// destination messages are the same, and source offset is smaller than
|
||||||
|
// the destination offset. We assert not allowing such a use.
|
||||||
|
|
||||||
|
OT_ASSERT((&aMessage != this) || (aSourceOffset >= aDestinationOffset));
|
||||||
|
|
||||||
GetFirstChunk(aSourceOffset, aLength, chunk);
|
GetFirstChunk(aSourceOffset, aLength, chunk);
|
||||||
|
|
||||||
while (chunk.GetLength() > 0)
|
while (chunk.GetLength() > 0)
|
||||||
|
|||||||
@@ -532,6 +532,10 @@ public:
|
|||||||
/**
|
/**
|
||||||
* This method copies bytes from one message to another.
|
* This method copies bytes from one message to another.
|
||||||
*
|
*
|
||||||
|
* If source and destination messages are the same, `CopyTo()` can be used to perform a backward copy, but
|
||||||
|
* it MUST not be used to forward copy within the same message (i.e., when source and destination messages are the
|
||||||
|
* same and source offset is smaller than the destination offset).
|
||||||
|
*
|
||||||
* @param[in] aSourceOffset Byte offset within the source message to begin reading.
|
* @param[in] aSourceOffset Byte offset within the source message to begin reading.
|
||||||
* @param[in] aDestinationOffset Byte offset within the destination message to begin writing.
|
* @param[in] aDestinationOffset Byte offset within the destination message to begin writing.
|
||||||
* @param[in] aLength Number of bytes to copy.
|
* @param[in] aLength Number of bytes to copy.
|
||||||
|
|||||||
@@ -144,7 +144,27 @@ void TestMessage(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verify `CopyTo()` with same source and destination message and a backward copy.
|
||||||
|
|
||||||
|
for (uint16_t srcOffset = 0; srcOffset < kMaxSize; srcOffset++)
|
||||||
|
{
|
||||||
|
uint16_t bytesCopied;
|
||||||
|
|
||||||
|
message->Write(0, kMaxSize, writeBuffer);
|
||||||
|
|
||||||
|
bytesCopied = message->CopyTo(srcOffset, 0, kMaxSize, *message);
|
||||||
|
VerifyOrQuit(bytesCopied == kMaxSize - srcOffset, "CopyTo() failed");
|
||||||
|
|
||||||
|
VerifyOrQuit(message->Read(0, kMaxSize, readBuffer) == kMaxSize, "Message::Read failed");
|
||||||
|
|
||||||
|
VerifyOrQuit(memcmp(&readBuffer[0], &writeBuffer[srcOffset], bytesCopied) == 0,
|
||||||
|
"CopyTo() changed before srcOffset");
|
||||||
|
VerifyOrQuit(memcmp(&readBuffer[bytesCopied], &writeBuffer[bytesCopied], kMaxSize - bytesCopied) == 0,
|
||||||
|
"CopyTo() write error");
|
||||||
|
}
|
||||||
|
|
||||||
message->Free();
|
message->Free();
|
||||||
|
message2->Free();
|
||||||
|
|
||||||
testFreeInstance(instance);
|
testFreeInstance(instance);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user