Skip to content

ConfigurationBlobFlash::BlobIsValid() could give the wrong result #91

@zhmu

Description

@zhmu

I'm using gcc 9.3.1 for arm, as bundled with STM32CubeIDE 1.6.1 (gcc version 9.3.1 20200408 (release) (GNU Tools for STM32 9-2020-q2-update.20201001-1621)). When trying to build with -O3 -Werror, I get a warning regarding the following code:

bool ConfigurationBlobFlash::BlobIsValid() const
{
    Header header;
    infra::Copy(infra::Head(blob, sizeof(header)), infra::MakeByteRange(header));

    if (header.size + sizeof(Header) > blob.size())
        return false;

where the warning is:

'header.services::ConfigurationBlobFlash::Header::size' may be used uninitialized in this function [-Werror=maybe-uninitialized]
     76 |         if (header.size + sizeof(Header) > blob.size())
        |             ~~~~~~~^~~~

I believe this warning to be correct and the code to be wrong: by using infra::MakeByteRange, header will be cast to an uint8_t*, which will be used by infra::Copy (which seems to call std::copy internally) to fill the byte range.

However, due to the strict aliasing rule, the compiler is free to assume that the uint8_t* being written does not overlap with header as they have different types. I suspect it might even be legal to optimize away the copy completely as there are no observable side-effects within the rules of the language.

My recommendation would be to simply do the following:

std::memcpy( &header, blob.begin(), sizeof( header ) );

which will yield the desired result with no risk of causing troubles.

(There are more constructs like these, it may be worthwhile to build with -O3 -Werror to locate them)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions