From Bugzilla Helper: User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030922 Description of problem: The following code breaks on Opteron RHE 3 WS. It does not break on SuSE. It also works fine when compiled and run on RHEL 3 WS x86. This is on an x86_64 box with "Everything" installed + all current errata. #include <stdio.h> #include <stdarg.h> #include <stdlib.h> typedef char *String; #define SY_OK 0 #define NIL(T) (T*)NULL FILE *logFile = NIL(FILE); int prInfo(String fmt, ...) { va_list args; va_start(args, fmt); vprintf(fmt, args); if (logFile) { vfprintf(logFile, fmt, args); fflush(logFile); } va_end(args); return SY_OK; } int main() { logFile = fopen("test.log", "w"); prInfo("%s %s\n", "HELLO", "CORE"); return SY_OK; } Version-Release number of selected component (if applicable): How reproducible: Always Steps to Reproduce: 1. cc tes.c 2. ./test Actual Results: ./test HELLO CORE Segmentation fault (core dumped) Expected Results: ./test HELLO CORE Additional info: [lennyd@linuxamd4 ~]$ gdb test GNU gdb Red Hat Linux (5.3.90-0.20030710.40rh) Copyright 2003 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "x86_64-redhat-linux-gnu"...(no debugging symbols found)...Using host libthread_db library "/lib64/tls/libthread_db.so.1". (gdb) run Starting program: /home/lennyd/test (no debugging symbols found)...(no debugging symbols found)...HELLO CORE Program received signal SIGSEGV, Segmentation fault. 0x0000002a956e9890 in strlen () from /lib64/tls/libc.so.6 (gdb) bt #0 0x0000002a956e9890 in strlen () from /lib64/tls/libc.so.6 #1 0x0000002a956b71b3 in vfprintf () from /lib64/tls/libc.so.6 #2 0x00000000004006a9 in prInfo () #3 0x00000000004006ef in main () (gdb)
The testcase is buggy. See ISO C99, 7.15: "The object ap may be passed as an argument to another function; if that function invokes the va_arg macro with parameter ap, the value of ap in the calling function is indeterminate and shall be passed to the va_end macro prior to any further reference to ap.212)" "212) It is permitted to create a pointer to a va_list and pass that pointer to another function, in which case the original function may make further use of the original list after the other function returns." The vprintf function uses va_arg, so you can only pass args to va_end, certainly not to another function which will do va_arg on it. If you add va_end (args); va_start (args, fmt); right before the vfprintf call, it will work just fine.