Skip to content

[RFC] Fix new GCC 15 warning [-Wunterminated-string-initialization] #628

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

Closed
wants to merge 2 commits into from

Conversation

ac000
Copy link
Member

@ac000 ac000 commented Apr 15, 2025

This is an RFC pull-request to check if this approach is acceptable. It's what we do in Unit and what I've proposed for njs.

GCC 15 (Fedora 42 which shipped today^H^H^Hyesterday has a GCC 15 snapshot) implements a new warning -Wunterminated-string-initialization that is also enabled by -Wextra that we enable.

This causes compilation failures (due to -Werror) due to the likes of

static const u_char nginx[5] = "\x84\xaa\x63\x55\xe7";

E.g.

src/http/v2/ngx_http_v2_filter_module.c:118:36: error: initializer-string for array of ‘unsigned char’ truncates NUL terminator but destination lacks ‘nonstring’ attribute (6 chars into 5 available) [-Werror=unterminated-string-initialization]
        118 |     static const u_char nginx[5] = "\x84\xaa\x63\x55\xe7";
            |                                    ^~~~~~~~~~~~~~~~~~~~~~

These are very much meant not to be NUL terminated.

Now we could just disable this new warning. But I think it is worth leaving it enabled (the GCC developers also obviously feel it's useful enough to enable under -Wexta), anything that helps the compiler help us avoid silly mistakes is a good thing(tm), particularly in the current climate.

So rather than disable this warning, we can make use of the GCC "nonstring" variable attribute __attribute__((nonstring)).

This attribute is used to mark character arrays that are intentionally not NUL terminated.

So the above example would become (we of course wrap it in a more friendly name NGX_NONSTRING)

 static const u_char nginx[5] NGX_NONSTRING = "\x84\xaa\x63\x55\xe7";

This attribute doesn't exist in clang (where we just define it to nothing), but then clang doesn't have this warning.

The good news is no released version of GCC had this warning that couldn't be quelled by the "nonstring" attribute. (This attribute existed before this new warning was added, the fix to allow this attribute to quell the warning went in sometime after the warning was added).

The first commit checks for the "nonstring" attribute.

The second commit is just a taster of what it looks like in practice.

Before I go through finding all the places that need fixing, I just wanted to check a couple of things.

So @arut @pluknet a couple of questions.

  1. Is this general approach acceptable?

I believe it to be superior to either simply disabling this new warning or removing the size from arrays making them NUL terminated, or setting the individual array elements.

I think it's a good idea to keep the warning enabled and aside from saving a byte it keeps it clear what their function is. Code may also assume these arrays to be of certain sizes.

  1. I couldn't find a great place to create the NGX_NONSTRING macro, so I just stuck it in src/core/ngx_config.h.

An alternative would be to create a new file something like src/core/ngx_clang.h for putting general C language stuff (we have this in Unit & njs).

ac000 added 2 commits April 15, 2025 23:55
This is a wrapper around __attribute__((nonstring)). Traditionally this
was used to mark char array variables that intentionally lacked a
terminating NUL byte, this would then cause warnings to either be
quelled or emitted for various memory/string functions.

GCC 15 introduced a new warning, Wunterminated-string-initialization,
which will always warn on things like

  static const char hex[16] = "0123456789ABCDEF";

However this is very much intentionally not NUL terminated.

The above attribute also quells this new warning (which is also enabled
by -Wextra).

So the above example would become

  static const char hex[16] NGX_NONSTRING = "0123456789ABCDEF";

This issue was attempted to be fixed in a previous pull-request, but I
believe this to be a superior solution (although the use of "nonstring"
to quell this warning wasn't available at that time).

Link: <https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=44c9403ed1833ae71a59e84f9e37af3182be0df5>
Link: <https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=622968990beee7499e951590258363545b4a3b57>
Link: <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117178#c21>
Link: <nginx#134>
Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
In nginx we have a number of character arrays which are intentionally
not NUL terminated which GCC 15 will now warn about e.g.

  src/http/v2/ngx_http_v2_filter_module.c:118:36: error: initializer-string for array of ‘unsigned char’ truncates NUL terminator but destination lacks ‘nonstring’ attribute (6 chars into 5 available) [-Werror=unterminated-string-initialization]
    118 |     static const u_char nginx[5] = "\x84\xaa\x63\x55\xe7";
        |                                    ^~~~~~~~~~~~~~~~~~~~~~

Fix this by tagging the array with NGX_NONSTRING which will quell this
warning.

Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
@arut
Copy link
Contributor

arut commented Apr 16, 2025

See #134 as well.

@ac000
Copy link
Member Author

ac000 commented Apr 16, 2025

See #134 as well.

Yes, I do make reference to that as IMO being the wrong way to fix it...

@ac000 ac000 closed this Apr 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants