Skip to content

The flag -fno-strict-overflow has not effect with clang #134577

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

Open
yonghong-song opened this issue Apr 7, 2025 · 10 comments
Open

The flag -fno-strict-overflow has not effect with clang #134577

yonghong-song opened this issue Apr 7, 2025 · 10 comments
Labels
clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' regression:19 Regression in 19 release

Comments

@yonghong-song
Copy link
Contributor

yonghong-song commented Apr 7, 2025

The 'fno-strict-overflow' intends to not print out signed-integer-overflow.
gcc honors this but clang not. Based on clang documentation https://clang.llvm.org/docs/DiagnosticsReference.html#wstrict-overflow
-fstrict-overflow (and -fno-strict-overflow) does not have impact all.

The following are some examples:

$ cat t.c
#include <stdio.h>
extern int a, b;
int main() {
  int c = a + b;
  fprintf(stderr, "c = %d\n", c);
  return 0;
}
$ cat t1.c
int a = 0x7fffFFFF;
int b = 0x7fffFFFF;
$ gcc --version
gcc (GCC) [11.5.0](https://github.com/intern/bunny/?q=obi%2011.5.0) 20240719 (Red Hat 11.5.0-2)
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ clang --version
clang version 21.0.0git (https://github.com/llvm/llvm-project.git b9207aef09387342837069d2c0857e6d331a516c)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /home/yhs/work/llvm-project/llvm/build.20/Release/bin
$ gcc -O2 -fsanitize=signed-integer-overflow -fno-strict-overflow t.c t1.c && ./a.out
c = -2
$ gcc -O2 -fsanitize=signed-integer-overflow t.c t1.c && ./a.out
t.c:4:7: runtime error: signed integer overflow: 2147483647 + 2147483647 cannot be represented in type 'int'
c = -2
$ clang -O2 -fsanitize=signed-integer-overflow -fno-strict-overflow t.c t1.c && ./a.out
t.c:4:13: runtime error: signed integer overflow: 2147483647 + 2147483647 cannot be represented in type 'int'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior t.c:4:13 
c = -2
$ clang -O2 -fsanitize=signed-integer-overflow t.c t1.c && ./a.out
t.c:4:13: runtime error: signed integer overflow: 2147483647 + 2147483647 cannot be represented in type 'int'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior t.c:4:13 
c = -2
$

So in summary, for '-fno-strict-overflow' (which is supposed to surpress overflow error), gcc works properly and clang ignores that flag and will emit error regardless.

In linux/Makefile, we have

# disable invalid "can't wrap" optimizations for signed / pointers
KBUILD_CFLAGS   += -fno-strict-overflow

so the kernel expects to silence signed overflow when ubsan is enabled.
But it only works for gcc build kernel, but not for clang build kernel.

Are there any discussions about implementing -fno-strict-overflow properly? Or any alternative?

@yonghong-song yonghong-song added clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Apr 7, 2025
@llvmbot
Copy link
Member

llvmbot commented Apr 7, 2025

@llvm/issue-subscribers-clang-frontend

Author: None (yonghong-song)

The 'fno-strict-overflow' intends to not print out signed-integer-overflow. gcc honors this but clang not. Based on clang documentation https://clang.llvm.org/docs/DiagnosticsReference.html#wstrict-overflow -fstrict-overflow (and -fno-strict-overflow) does not have impact all.

The following are some examples:

$ cat t.c
#include &lt;stdio.h&gt;
extern int a, b;
int main() {
  int c = a + b;
  fprintf(stderr, "c = %d\n", c);
  return 0;
}
$ cat t1.c
int a = 0x7fffFFFF;
int b = 0x7fffFFFF;
$ gcc --version
gcc (GCC) [11.5.0](https://github.com/intern/bunny/?q=obi%2011.5.0) 20240719 (Red Hat 11.5.0-2)
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ clang --version
clang version 21.0.0git (https://github.com/llvm/llvm-project.git b9207aef09387342837069d2c0857e6d331a516c)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /home/yhs/work/llvm-project/llvm/build.20/Release/bin
$ gcc -O2 -fsanitize=signed-integer-overflow -fno-strict-overflow t.c t1.c &amp;&amp; ./a.out
c = -2
$ gcc -O2 -fsanitize=signed-integer-overflow t.c t1.c &amp;&amp; ./a.out
t.c:4:7: runtime error: signed integer overflow: 2147483647 + 2147483647 cannot be represented in type 'int'
c = -2
$ clang -O2 -fsanitize=signed-integer-overflow -fno-strict-overflow t.c t1.c &amp;&amp; ./a.out
t.c:4:13: runtime error: signed integer overflow: 2147483647 + 2147483647 cannot be represented in type 'int'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior t.c:4:13 
c = -2
$ clang -O2 -fsanitize=signed-integer-overflow t.c t1.c &amp;&amp; ./a.out
t.c:4:13: runtime error: signed integer overflow: 2147483647 + 2147483647 cannot be represented in type 'int'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior t.c:4:13 
c = -2
$

So in summary, for '-fno-strict-overflow' (which is supposed to surpress overflow error), gcc works properly and clang ignores that flag and will emit error regardless.

In linux/Makefile, we have

# disable invalid "can't wrap" optimizations for signed / pointers
KBUILD_CFLAGS   += -fno-strict-overflow

so the kernel expects to silence signed overflow when ubsan is enabled.
But it only works for gcc build kernel, but not for clang build kernel.

Are there any discussions about implementing -fno-strict-overflow properly?

@llvmbot
Copy link
Member

llvmbot commented Apr 7, 2025

@llvm/issue-subscribers-clang-driver

Author: None (yonghong-song)

The 'fno-strict-overflow' intends to not print out signed-integer-overflow. gcc honors this but clang not. Based on clang documentation https://clang.llvm.org/docs/DiagnosticsReference.html#wstrict-overflow -fstrict-overflow (and -fno-strict-overflow) does not have impact all.

The following are some examples:

$ cat t.c
#include &lt;stdio.h&gt;
extern int a, b;
int main() {
  int c = a + b;
  fprintf(stderr, "c = %d\n", c);
  return 0;
}
$ cat t1.c
int a = 0x7fffFFFF;
int b = 0x7fffFFFF;
$ gcc --version
gcc (GCC) [11.5.0](https://github.com/intern/bunny/?q=obi%2011.5.0) 20240719 (Red Hat 11.5.0-2)
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ clang --version
clang version 21.0.0git (https://github.com/llvm/llvm-project.git b9207aef09387342837069d2c0857e6d331a516c)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /home/yhs/work/llvm-project/llvm/build.20/Release/bin
$ gcc -O2 -fsanitize=signed-integer-overflow -fno-strict-overflow t.c t1.c &amp;&amp; ./a.out
c = -2
$ gcc -O2 -fsanitize=signed-integer-overflow t.c t1.c &amp;&amp; ./a.out
t.c:4:7: runtime error: signed integer overflow: 2147483647 + 2147483647 cannot be represented in type 'int'
c = -2
$ clang -O2 -fsanitize=signed-integer-overflow -fno-strict-overflow t.c t1.c &amp;&amp; ./a.out
t.c:4:13: runtime error: signed integer overflow: 2147483647 + 2147483647 cannot be represented in type 'int'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior t.c:4:13 
c = -2
$ clang -O2 -fsanitize=signed-integer-overflow t.c t1.c &amp;&amp; ./a.out
t.c:4:13: runtime error: signed integer overflow: 2147483647 + 2147483647 cannot be represented in type 'int'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior t.c:4:13 
c = -2
$

So in summary, for '-fno-strict-overflow' (which is supposed to surpress overflow error), gcc works properly and clang ignores that flag and will emit error regardless.

In linux/Makefile, we have

# disable invalid "can't wrap" optimizations for signed / pointers
KBUILD_CFLAGS   += -fno-strict-overflow

so the kernel expects to silence signed overflow when ubsan is enabled.
But it only works for gcc build kernel, but not for clang build kernel.

Are there any discussions about implementing -fno-strict-overflow properly?

@yonghong-song
Copy link
Contributor Author

cc @4ast @eddyz87

@dtcxzyw dtcxzyw removed the clang:frontend Language frontend issues, e.g. anything involving "Sema" label Apr 7, 2025
@nikic
Copy link
Contributor

nikic commented Apr 7, 2025

Clang supports -fno-strict-overflow. It looks like this is a regression between Clang 18 and 19.

@nikic
Copy link
Contributor

nikic commented Apr 7, 2025

Note that it works with -fsanitize=undefined. I guess clang is interpreting the -fsanitize=signed-integer-overflow as overriding the -fno-strict-overflow, in much the same way you can use -fsanitize=unsigned-integer-overflow even though unsigned integer overflow is never UB.

But probably the interaction of these flags should still match what GCC does.

@shafik shafik added the regression:19 Regression in 19 release label Apr 7, 2025
@yonghong-song
Copy link
Contributor Author

This pull request
#82432
caused the regression.
From the pull request description, I see

The Linux kernel enables -fno-strict-overflow which implies -fwrapv. This means we are https://github.com/KSPP/linux/issues/26. All the while, the root cause of many security vulnerabilities in the Linux kernel is [arithmetic overflow](https://cwe.mitre.org/data/definitions/190.html)

Looks like it intentionally ignores -fno-strict-overflow flag?

@yonghong-song
Copy link
Contributor Author

@nikic What do you think about the next step?

@nikic
Copy link
Contributor

nikic commented Apr 9, 2025

Given that this was an intentional change (cc @JustinStitt), I don't know. I'm not sure whether the fact that this diverges from GCC behavior has been considered in the decision. Possibly the behavior should depend on the order of the flags? (Though that does not match GCC either.)

Maybe @AaronBallman knows what to do here :)

@MaskRay
Copy link
Member

MaskRay commented Apr 9, 2025

The sanitizer behavior overriding -fwrapv/-fno-strict-overflow is an intentional decision. Some Linux kernel developers were pushing forward this and I think it makes sense.
GCC developers have been notified https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102317#c13

@JustinStitt
Copy link
Contributor

JustinStitt commented Apr 9, 2025

Given that this was an intentional change (cc @JustinStitt), I don't know. I'm not sure whether the fact that this diverges from GCC behavior has been considered in the decision. Possibly the behavior should depend on the order of the flags? (Though that does not match GCC either.)

Maybe @AaronBallman knows what to do here :)

Originally, my changelist suggested a new sanitizer signed-integer-wrap for use with -fwrapv but we ultimately decided to override the existing sanitizer (and thus diverge from GCC).

Context at #80089 and #82432

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' regression:19 Regression in 19 release
Projects
None yet
Development

No branches or pull requests

7 participants