https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127416

            Bug ID: 127416
           Summary: Bogus -Wformat-truncation for bounded %.*s with an
                    offset into a constexpr array member
           Product: gcc
           Version: 17.0
               URL: https://godbolt.org/z/YxnKK7Y4d
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: hr.jonas.hansen at gmail dot com
  Target Milestone: ---

Compiling the snippet below with g++ 10 (and newer) with at least -O1 and -Wall
 produce a false-positive -Wformat-truncation diagnostic when snprintf reads a
bounded portion of a non-NUL-terminated character array inside a constexpr
object.



#include <cstdio>

struct Buffer {
    char data[3];
};

constexpr auto buffer = Buffer{{'a', 'b', 'c'}};

int main() {
    char out[3];
    return std::snprintf(out, sizeof out, "%.*s", 2, buffer.data + 1) != 2;
}


Actual result:

Compilation fails with:

error: ā€˜%.*s’ directive argument is not a nul-terminated string
        [-Werror=format-truncation=]

Expected result:

Compilation succeeds without this warning. snprintf writes {'b', 'c', '\0'}
into out and returns 2.

The %.*s precision limits the source access to two characters. Exactly two
characters remain in the source array at buffer.data + 1, so no source NUL
terminator is required. The three-byte destination also accommodates the output
terminator.

Possible cause:

Debugging a larger reproducer suggests that constant_byte_string() /
fold_ctor_reference() reduces the array reference to a single-character
constant. Consequently, c_strlen() sees an incorrect available source length.
This is a preliminary diagnosis.

Reply via email to