一些非字符串湍流
Some __nonstring__ Turbulence

原始链接: https://lwn.net/SubscriberLink/1018486/1dcd29863655cb25/

GCC 15 引入的 `-Wunterminated-string-initialization` 警告最近在 Linux 内核开发过程中造成了混乱。该警告标记未以空字符结尾的字符数组初始化,但内核有时会故意将此类数组用作查找表,而不是字符串。Kees Cook 致力于添加 `__nonstring` 注解以抑制这些误报。 然而,Linus Torvalds 在发布 6.15-rc3 内核版本之前,将他的系统更新到了包含预发行版 GCC 15 的 Fedora 42。由于新的警告导致构建错误,Torvalds 匆忙应用了直接修复,从而破坏了旧版 GCC 版本的构建。然后,他完全禁用了该警告。 这引发了与 Cook 之间的激烈争论,Cook 认为预先准备好的修复方案是可用的,并且 Torvalds 未经协调就采取了行动,造成了合并冲突。Torvalds 指责 Cook 集成缓慢,并为自己的行为辩护,他优先考虑可构建的内核。这种情况仍然紧张,突显了在处理预发行版编译器版本时优先级和挫败感上的差异。Torvalds 还不同意基于变量的属性实现方式,他更倾向于基于类型的方法。

这个Hacker News帖子讨论了Linus Torvalds最近在内核开发和新GCC编译器版本方面的行为。起因是有人指责Torvalds虚伪,因为他升级到测试版编译器后,因匆忙提交未经审查的更改而导致问题,却批评维护人员。 评论者们辩论Torvalds的行为是否可以接受,考虑到他对内核的贡献,一些人认为没有人“理所应当可以成为混蛋”。讨论扩展到在关键系统中使用预发行软件的更广泛问题以及缺乏全面的内核CI系统。 帖子随后转向了关于C字符串的讨论,特别是空字符结尾字符串与长度前缀字符串的使用,一些人认为空字符结尾是一种过时且容易出错的设计选择。同时也讨论了帮助减轻此类问题的注释。
相关文章

原文

Welcome to LWN.net

The following subscription-only content has been made available to you by an LWN subscriber. Thousands of subscribers depend on LWN for the best news from the Linux and free software communities. If you enjoy this article, please consider subscribing to LWN. Thank you for visiting LWN.net!

By Jonathan Corbet
April 24, 2025

New compiler releases often bring with them new warnings; those warnings are usually welcome, since they help developers find problems before they turn into nasty bugs. Adapting to new warnings can also create disruption in the development process, though, especially when an important developer upgrades to a new compiler at an unfortunate time. This is just the scenario that played out with the 6.15-rc3 kernel release and the implementation of -Wunterminated-string-initialization in GCC 15.

Consider a C declaration like:

    char foo[8] = "bar";

The array will be initialized with the given string, including the normal trailing NUL byte indicating the end of the string. Now consider this variant:

    char foo[8] = "NUL-free";

This is a legal declaration, even though the declared array now lacks the room for the NUL byte. That byte will simply be omitted, creating an unterminated string. That is often not what the developer who wrote that code wants, and it can lead to unpleasant bugs that are not discovered until some later time. The -Wunterminated-string-initialization option emits a warning for this kind of initialization, with the result that, hopefully, the problem — if there is a problem — is fixed quickly.

The kernel community has worked to make use of this warning and, hopefully, eliminate a source of bugs. There is only one little problem with the new warning, though: sometimes the no-NUL initialization is exactly what is wanted and intended. See, for example, this declaration from fs/cachefiles/key.c:

    static const char cachefiles_charmap[64] =
	"0123456789"			/* 0 - 9 */
	"abcdefghijklmnopqrstuvwxyz"	/* 10 - 35 */
	"ABCDEFGHIJKLMNOPQRSTUVWXYZ"	/* 36 - 61 */
	"_-"				/* 62 - 63 */
	;

This char array is used as a lookup table, not as a string, so there is no need for a trailing NUL byte. GCC 15, being unaware of that usage, will emit a false-positive warning for this declaration. There are many places in the kernel with declarations like this; the ACPI code, for example, uses a lot of four-byte string arrays to handle the equally large set of four-letter ACPI acronyms.

Naturally, there is a way to suppress the warning when it does not apply by adding an attribute to the declaration indicating that the char array is not actually holding a string:

    __attribute__((__nonstring__))

Within the kernel, the macro __nonstring is used to shorten that attribute syntax. Work has been ongoing, primarily by Kees Cook, to fix all of the warnings added by GCC 15. Many patches have been circulated; quite a few of them are in linux-next. Cook has also been working with the GCC developers to improve how this annotation works and to fix a problem that the kernel project ran into. There was some time left to get this job done, though, since GCC 15 has not actually been released — or so Cook thought.

Fedora 42 has been released, though, and the Fedora developers, for better or worse, decided to include a pre-release version of GCC 15 with it as the default compiler. The Fedora project, it seems, has decided to follow a venerable Red Hat tradition with this release. Linus Torvalds, for better or worse, decided to update his development systems to Fedora 42 the day before tagging and releasing 6.15-rc3. Once he tried building the kernel with the new compiler, though, things started to go wrong, since the relevant patches were not yet in his repository. Torvalds responded with a series of changes of his own, applied directly to the mainline about two hours before the release, to fix the problems that he had encountered. They included this patch fixing warnings in the ACPI subsystem, and this one fixing several others, including the example shown above. He then tagged and pushed out 6.15-rc3 with those changes.

Unfortunately, his last-minute changes broke the build on any version of GCC prior to the GCC 15 pre-release — a problem that was likely to create a certain amount of inconvenience for any developers who were not running Fedora 42. So, shortly after the 6.15-rc3 release, Torvalds tacked on one more patch backing out the breaking change and disabling the new warning altogether.

This drew a somewhat grumpy note from Cook, who said that he had already sent patches fixing all of the problems, including the build-breaking one that Torvalds ran into. He asked Torvalds to revert the changes and use the planned fixes, adding: "It is, once again, really frustrating when you update to unreleased compiler versions". Torvalds disagreed, saying that he needed to make the changes because the kernel failed to build otherwise. He also asserted that GCC 15 was released by virtue of its presence in Fedora 42. Cook was unimpressed:

Yes, I understand that, but you didn't coordinate with anyone. You didn't search lore for the warning strings, you didn't even check -next where you've now created merge conflicts. You put insufficiently tested patches into the tree at the last minute and cut an rc release that broke for everyone using GCC <15. You mercilessly flame maintainers for much much less.

Torvalds stood his ground, though, blaming Cook for not having gotten the fixes into the mainline quickly enough.

That is where the situation stands, as of this writing. Others will undoubtedly take the time to fix the problems properly, adding the changes that were intended all along. But this course of events has created some bad feelings all around, feelings that could maybe have been avoided with a better understanding of just when a future version of GCC is expected to be able to build the kernel.

As a sort of coda, it is worth saying that Torvalds also has a fundamental disagreement with how this attribute is implemented. The __nonstring__ attribute applies to variables, not types, so it must be used in every place where a char array is used without trailing NUL bytes. He would rather annotate the type, indicating that every instance of that type holds bytes rather than a character string, and avoid the need to mark rather larger numbers of variable declarations. But that is not how the attribute works, so the kernel will have to include __nonstring markers for every char array that is used in that way.




联系我们 contact @ memedata.com