-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for signed/bool to BufferReader/Writer #27637
Conversation
Problem: - Safe buffer reader/writer doesn't support signed values - Safe buffer reader/writer doesn't support bools - Fixes project-chip#27629 This PR: - Adds signed and bool support to BufferWriter and to Reader - Adds missing unit tests - Makes it clear that low-level reads are not to be used directly Testing done: - Integration tests pass - New unit tests added and pass - Existing unit tests all pass
PR #27637: Size comparison from 7e3aa84 to 4d1f6b0 Increases (58 builds for bl602, bl702, bl702l, cc32xx, cyw30739, efr32, esp32, k32w, linux, mbed, nrfconnect, psoc6, qpg, telink)
Decreases (8 builds for bl702, bl702l, cc32xx, psoc6)
Full report (58 builds for bl602, bl702, bl702l, cc32xx, cyw30739, efr32, esp32, k32w, linux, mbed, nrfconnect, psoc6, qpg, telink)
|
|
||
namespace chip { | ||
namespace Encoding { | ||
namespace LittleEndian { | ||
|
||
namespace { | ||
// These helper methods return void and put the value being read into an | ||
|
||
// This helper methods return void and put the value being read into an |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"method returns" and "puts"
memcpy(&result, p, sizeof(result)); | ||
result = chip::Encoding::LittleEndian::HostSwap(result); | ||
|
||
*dest = static_cast<T>(result); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Casting to signed of things that are "negative" (i.e. out of range) has implementation-defined behavior until c++20...
This should probably use CastToSigned
for the casting; that's what we have that utility for.
{ | ||
static_assert(CHAR_BIT == 8, "Our various sizeof checks rely on bytes and octets being the same thing"); | ||
static_assert((-1 & 3) == 3, "LittleEndian::BufferReader only works with 2's complement architectures."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this the part that's meant to make the static_cast above safe? Or is this something we depend on for the HostSwap bits to work right for negative numbers? Would be good to make it clearer what the actual 2's complement dependency is here.
{ | ||
while (size > 0) | ||
{ | ||
Put(static_cast<uint8_t>(x & 0xff)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it not be safer to just cast to uint64_t and then EndianPut that? That's obviously the reverse of what we do when reading in the BufferReader, whereas it's not entirely obvious without digging through C++ specs what the bitwise ops here will end up doing.
BufferWriter(uint8_t * buf, size_t len) : EndianBufferWriterBase<BufferWriter>(buf, len) {} | ||
BufferWriter(uint8_t * buf, size_t len) : EndianBufferWriterBase<BufferWriter>(buf, len) | ||
{ | ||
static_assert((-1 & 3) == 3, "LittleEndian::BufferWriter only works with 2's complement architectures."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, would be good to document exactly where this dependency comes in. I think if you do cast to unsigned as suggested above there is no such dependency here (because cast to unsigned is well-defined in the C++ standard).
Problem
Changes in this PR
Testing done