danmar / simplecpp

C++ preprocessor
BSD Zero Clause License
209 stars 83 forks source link

False positive returnDanglingLifetime returning pointer to stack char array as std::string (by way of a struct's constructor) #316

Closed aremmell closed 1 year ago

aremmell commented 1 year ago

Given the following struct:

struct error {
    uint16_t code = 0U;
    std::string message;
};

and the following function returning said struct:

error get_error() {
    std::array<char, 1024> message {};
    auto code = fake_get_error(message); // places error description in `message` and returns error code
    return { code, message.data() };
}

given that error::message is a std::string whose constructor makes a copy of a [const] char* argument, the following is a false positive:

returnDanglingLifetime | 562 | error | Returning object that points to local variable 'message' that will be invalid when returning.

I wrote a test to prove that the error struct contains a copy, rather than pointing to the stack-based std::array. The test scopes the error outside of the scope of the class that implements get_error, and the message showing its contents is emitted after the object containing the stack-based array has gone out of scope:

error err;

{
    default_logger log; // implements `get_error()`

    TEST_MSG_0("testing get_error by doing something stupid...");
    _sir_eqland(pass, !log.debug(nullptr));

    err = log.get_error();
    _sir_eqland(pass, log.debug("Error info: code = %hu, message = '%s'", err.code,
        err.message.c_str()));
}

TEST_MSG("ensuring error outlives logger: %hu, (%s) (address of err.message.c_str() = %p)",
    err.code, err.message.c_str(), err.message.c_str());

Here's the output:

testing get_error by doing something stupid... get_error (sir.hh:678): address of get_error's stack-based array: 0x7ff7b3d8c1e0 [debg]: Error info: code = 10, message = 'Error in debug (sir.hh:242): 'NULL pointer argument'' _sir_cleanup (sirinternal.c:237): cleaned up successfully ensuring error outlives logger: 10, (Error in debug (sir.hh:242): 'NULL pointer argument') (address of err.message.c_str() = 0x7fbffe7065e0)

I can provide the source that you can use to reproduce this if you need it.