Bug 111284

Summary: core dump when using strlen on x86_64
Product: Red Hat Enterprise Linux 3 Reporter: Ken Crandall <ken.crandall>
Component: glibcAssignee: Jakub Jelinek <jakub>
Status: CLOSED NOTABUG QA Contact: Brian Brock <bbrock>
Severity: medium Docs Contact:
Priority: medium    
Version: 3.0   
Target Milestone: ---   
Target Release: ---   
Hardware: x86_64   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2003-12-01 17:31:45 EST Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:

Description Ken Crandall 2003-12-01 14:00:27 EST
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)
Comment 1 Jakub Jelinek 2003-12-01 17:31:45 EST
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.