Open ncopa opened 4 months ago
This is the code it complains about:
static inline void report(const char *prefix, const char *err, va_list params)
{
char msg[1024];
vsnprintf(msg, sizeof(msg), err, params);
fprintf(stderr, " %s%s\n", prefix, msg);
}
So compiler complains that msg
may be uninitialized when initializing it.
Changing it to:
char msg[1024] = "";
makes it pass, but I don't think that is a good solution.
Good catch, this is indeed a copy-pasta typo. It should be fixed by 6f5423255b6d78b0d6979e6319642ae530f3e2b7
Seems to solve it. Thank you for a super fast fix!
Thank you for making Alpine Linux a willing guinea pig :)
Seems to also affect snprintf
:
DESCEND objtool
In file included from /home/ncopa/aports/main/linux-lts/src/linux-6.6/tools/include/linux/string.h:6,
from parse-options.c:3:
In function 'strncpy',
inlined from 'get_value' at parse-options.c:138:4:
/usr/include/fortify/string.h:327:16: error: '__orig_strncpy' reading 128 bytes from a region of size 17 [-Werror=stringop-overread]
327 | return __orig_strncpy(__d, __s, __n);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/fortify/strings.h:23,
from /usr/include/string.h:59,
from /usr/include/fortify/string.h:23:
/usr/include/fortify/string.h: In function 'get_value':
/usr/include/fortify/string.h:311:1: note: in a call to function '__orig_strncpy' declared with attribute 'access (read_only, 2, 3)'
311 | _FORTIFY_FN(strncpy) char *strncpy(char * _FORTIFY_POS0 __d,
| ^~~~~~~~~~~
In file included from parse-options.c:5:
In function 'snprintf',
inlined from 'get_value' at parse-options.c:89:5:
/usr/include/fortify/stdio.h:284:16: error: 'msg' may be used uninitialized [-Werror=maybe-uninitialized]
284 | return __orig_snprintf(__s, __n, __f, __builtin_va_arg_pack());
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/fortify/stdio.h: In function 'get_value':
/usr/include/fortify/stdio.h:274:1: note: in a call to '__orig_snprintf' declared with attribute 'access (read_write, 1, 2)' here
274 | _FORTIFY_FN(snprintf) int snprintf(char *__s, size_t __n,
| ^~~~~~~~~~~
parse-options.c:85:30: note: 'msg' declared here
85 | char msg[128];
| ^~~
In function 'snprintf',
inlined from 'get_value' at parse-options.c:92:5:
/usr/include/fortify/stdio.h:284:16: error: 'msg' may be used uninitialized [-Werror=maybe-uninitialized]
284 | return __orig_snprintf(__s, __n, __f, __builtin_va_arg_pack());
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/fortify/stdio.h: In function 'get_value':
/usr/include/fortify/stdio.h:274:1: note: in a call to '__orig_snprintf' declared with attribute 'access (read_write, 1, 2)' here
274 | _FORTIFY_FN(snprintf) int snprintf(char *__s, size_t __n,
| ^~~~~~~~~~~
parse-options.c:85:30: note: 'msg' declared here
85 | char msg[128];
| ^~~
In function 'snprintf',
inlined from 'get_value' at parse-options.c:130:9:
/usr/include/fortify/stdio.h:284:16: error: 'reason' may be used uninitialized [-Werror=maybe-uninitialized]
284 | return __orig_snprintf(__s, __n, __f, __builtin_va_arg_pack());
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/fortify/stdio.h: In function 'get_value':
/usr/include/fortify/stdio.h:274:1: note: in a call to '__orig_snprintf' declared with attribute 'access (read_write, 1, 2)' here
274 | _FORTIFY_FN(snprintf) int snprintf(char *__s, size_t __n,
| ^~~~~~~~~~~
parse-options.c:127:22: note: 'reason' declared here
127 | char reason[128];
| ^~~~~~
Sigh, I should have been more thorough. Fixed by 9014b0266147dbb74d5d9e6e2c24ae9d21ad7e07
Not sure if the strncpy should be reported separately? Seems to be another bug.
CALL /home/ncopa/aports/main/linux-lts/src/linux-6.6/scripts/checksyscalls.sh
DESCEND objtool
In file included from /home/ncopa/aports/main/linux-lts/src/linux-6.6/tools/include/linux/string.h:6,
from parse-options.c:3:
In function 'strncpy',
inlined from 'get_value' at parse-options.c:138:4:
/usr/include/fortify/string.h:327:16: error: '__orig_strncpy' reading 128 bytes from a region of size 17 [-Werror=stringop-overread]
327 | return __orig_strncpy(__d, __s, __n);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/fortify/strings.h:23,
from /usr/include/string.h:59,
from /usr/include/fortify/string.h:23:
/usr/include/fortify/string.h: In function 'get_value':
/usr/include/fortify/string.h:311:1: note: in a call to function '__orig_strncpy' declared with attribute 'access (read_only, 2, 3)'
311 | _FORTIFY_FN(strncpy) char *strncpy(char * _FORTIFY_POS0 __d,
| ^~~~~~~~~~~
cc1: all warnings being treated as errors
The code it comes from looks legit?
if (opt->flags & PARSE_OPT_NOBUILD) {
char reason[128];
bool noarg = false;
err = snprintf(reason, sizeof(reason),
opt->flags & PARSE_OPT_CANSKIP ?
"is being ignored because %s " :
"is not available because %s",
opt->build_opt);
reason[sizeof(reason) - 1] = '\0';
if (err < 0)
strncpy(reason, opt->flags & PARSE_OPT_CANSKIP ?
"is being ignored" :
"is not available",
sizeof(reason));
Maybe something like this? It will not read more than max_len_s
:
diff --git a/include/string.h b/include/string.h
index c317b1e..0347ddf 100644
--- a/include/string.h
+++ b/include/string.h
@@ -324,7 +324,7 @@ _FORTIFY_FN(strncpy) char *strncpy(char * _FORTIFY_POS0 __d,
if (__n > __b)
__builtin_trap();
- return __orig_strncpy(__d, __s, __n);
+ return __orig_strncpy(__d, __s, max_len_s);
#endif
}
And with the above fix applied it continues with:
DESCEND objtool
rm -f /home/ncopa/aports/main/linux-lts/src/build-lts.x86_64/tools/objtool/libsubcmd/libsubcmd.a && ar rcs /home/ncopa/aports/main/linux-lts/src/build-lts.x86_64/tools/objtool/libsubcmd/libsubcmd.a /home/ncopa/aports/main/linux-lts/src/build-lts.x86_64/tools/objtool/libsubcmd/libsubcmd-in.o
make[4]: 'install_headers' is up to date.
In file included from /home/ncopa/aports/main/linux-lts/src/linux-6.6/tools/include/linux/panic.h:6,
from /home/ncopa/aports/main/linux-lts/src/linux-6.6/tools/include/linux/kernel.h:11,
from /home/ncopa/aports/main/linux-lts/src/build-lts.x86_64/tools/objtool/libsubcmd/include/subcmd/parse-options.h:5,
from /home/ncopa/aports/main/linux-lts/src/linux-6.6/tools/objtool/include/objtool/builtin.h:8,
from check.c:11:
In function 'sprintf',
inlined from 'offstr' at /home/ncopa/aports/main/linux-lts/src/linux-6.6/tools/objtool/include/objtool/warn.h:33:9:
/usr/include/fortify/stdio.h:300:23: error: '__orig_snprintf' specified size 18446744073709551615 exceeds maximum object size 9223372036854775807 [-Werror=stringop-overflow=]
300 | __r = __orig_snprintf(__s, __b, __f, __builtin_va_arg_pack());
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/fortify/strings.h:23,
from /usr/include/string.h:59,
from /usr/include/fortify/string.h:23,
from check.c:6:
/usr/include/fortify/stdio.h: In function 'offstr':
/usr/include/fortify/stdio.h:274:1: note: in a call to function '__orig_snprintf' declared with attribute 'access (read_only, 3)'
274 | _FORTIFY_FN(snprintf) int snprintf(char *__s, size_t __n,
| ^~~~~~~~~~~
In function 'sprintf',
inlined from 'offstr' at /home/ncopa/aports/main/linux-lts/src/linux-6.6/tools/objtool/include/objtool/warn.h:35:4:
/usr/include/fortify/stdio.h:300:23: error: '__orig_snprintf' specified size 18446744073709551615 exceeds maximum object size 9223372036854775807 [-Werror=stringop-overflow=]
300 | __r = __orig_snprintf(__s, __b, __f, __builtin_va_arg_pack());
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/fortify/stdio.h: In function 'offstr':
/usr/include/fortify/stdio.h:274:1: note: in a call to function '__orig_snprintf' declared with attribute 'access (read_only, 3)'
274 | _FORTIFY_FN(snprintf) int snprintf(char *__s, size_t __n,
| ^~~~~~~~~~~
In function 'sprintf',
inlined from 'offstr' at /home/ncopa/aports/main/linux-lts/src/linux-6.6/tools/objtool/include/objtool/warn.h:38:3:
/usr/include/fortify/stdio.h:300:23: error: '__orig_snprintf' specified size 18446744073709551615 exceeds maximum object size 9223372036854775807 [-Werror=stringop-overflow=]
300 | __r = __orig_snprintf(__s, __b, __f, __builtin_va_arg_pack());
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/fortify/stdio.h: In function 'offstr':
/usr/include/fortify/stdio.h:274:1: note: in a call to function '__orig_snprintf' declared with attribute 'access (read_only, 3)'
274 | _FORTIFY_FN(snprintf) int snprintf(char *__s, size_t __n,
| ^~~~~~~~~~~
In function 'sprintf',
inlined from 'disas_warned_funcs' at check.c:4624:5,
inlined from 'check' at check.c:4814:3:
/usr/include/fortify/stdio.h:300:23: error: '__orig_snprintf' specified size 18446744073709551615 exceeds maximum object size 9223372036854775807 [-Werror=stringop-overflow=]
300 | __r = __orig_snprintf(__s, __b, __f, __builtin_va_arg_pack());
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/fortify/stdio.h: In function 'check':
/usr/include/fortify/stdio.h:274:1: note: in a call to function '__orig_snprintf' declared with attribute 'access (read_only, 3)'
274 | _FORTIFY_FN(snprintf) int snprintf(char *__s, size_t __n,
| ^~~~~~~~~~~
cc1: all warnings being treated as errors
make[4]: *** [/home/ncopa/aports/main/linux-lts/src/linux-6.6/tools/build/Makefile.build:98: /home/ncopa/aports/main/linux-lts/src/build-lts.x86_64/tools/objtool/check.o] Error 1
make[3]: *** [Makefile:66: /home/ncopa/aports/main/linux-lts/src/build-lts.x86_64/tools/objtool/objtool-in.o] Error 2
make[2]: *** [Makefile:73: objtool] Error 2
make[1]: *** [/home/ncopa/aports/main/linux-lts/src/linux-6.6/Makefile:1362: tools/objtool] Error 2
make: *** [/home/ncopa/aports/main/linux-lts/src/linux-6.6/Makefile:234: __sub-make] Error 2
The offstr
looks like:
static inline char *offstr(struct section *sec, unsigned long offset)
{
bool is_text = (sec->sh.sh_flags & SHF_EXECINSTR);
struct symbol *sym = NULL;
char *str;
int len;
if (is_text)
sym = find_func_containing(sec, offset);
if (!sym)
sym = find_symbol_containing(sec, offset);
if (sym) {
str = malloc(strlen(sym->name) + strlen(sec->name) + 40);
len = sprintf(str, "%s+0x%lx", sym->name, offset - sym->offset);
if (opts.sec_address)
sprintf(str+len, " (%s+0x%lx)", sec->name, offset);
} else {
str = malloc(strlen(sec->name) + 20);
sprintf(str, "%s+0x%lx", sec->name, offset);
}
return str;
}
/usr/include/fortify/stdio.h:300:23: error: '__orig_snprintf' specified size 18446744073709551615 exceeds maximum object size 9223372036854775807 [-Werror=stringop-overflow=]
Is a bit confusing, since 18446744073709551615
is (size_t)-1
on 64b, and the code is:
if (__b != (__fh_size_t)-1) {
__r = __orig_snprintf(__s, __b, __f, __builtin_va_arg_pack());
Weird indeed. It also happens with this:
if (__b != (__fh_size_t)-1 && __b != (__fh_size_t)18446744073709551615) {
__r = __orig_snprintf(__s, __b, __f, __builtin_va_arg_pack());
#define __fh_size_t __typeof__(sizeof(char))
is size_t
on my machine, so I'm really confused :/
I confirmed it is 8 bytes here, on my x86_64.
FYI, the type of sizeof(...)
always is size_t
.
(Edit: just passing by because our CI build on alpine:edge started to fail because of false fortify positives).
So wtf is going on :D
I have tried this to confirm that it actually is __b
.
__r = __orig_snprintf(__s, 20000, __f, __builtin_va_arg_pack());
It makes it build the objtool.
So it must be __b
that is the problem.
Then I tried with:
if (__b < 9223372036854775807) {
__r = __orig_snprintf(__s, __b, __f, __builtin_va_arg_pack());
But it still triggers the problem. I have no clue what is going on here.
(Edit: just passing by because our CI build on alpine:edge started to fail because of false fortify positives).
@markus-oberhumer is it the same error, or something else?
I think we should try create a smaller test case where we can debug this.
@ncopa Looks like we hit strncpy
https://github.com/upx/upx-test-build-with-zig/actions/runs/9874643415/job/27269509241
@ncopa Looks like we hit
strncpy
https://github.com/upx/upx-test-build-with-zig/actions/runs/9874643415/job/27269509241
I'll push the fix for that, while we scratch our heads.
This makes build pass:
if (__b < 1) {
__r = __orig_snprintf(__s, __b, __f, __builtin_va_arg_pack());
This fails with same error:
if (__b < 2) {
__r = __orig_snprintf(__s, __b, __f, __builtin_va_arg_pack());
Try building openssl - it will also fail to build with multiple false positive warnings if -Werror is used.
I have a smallish reproducer:
#include <stdio.h>
static char *offstr(char *str)
{
int len = 0;
len = sprintf(str, "%s+0x%lx", "foo", (long unsigned int)0);
sprintf(str+len, " (%s+0x%lx)","bar", (long unsigned int)0);
if (len < 0)
return NULL;
return str;
}
int main() {
char buf[100];
char *c = offstr(buf);
printf("%s\n", c);
return 0;
}
I have reverted the fortify-headers upgrade in Alpine Linux til we have this sorted.
@jvoisin Could you please create a single-file reproducer on Compiler Explorer https://godbolt.org/ ?
f2e7f24daaa43c0927130b6ed02c3ed17689b3ca should work around the issue, as I really don't want to dive into gcc's code.