[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: (lack of) va_copy, and segfaults on x86_64

From: Thomas Dickey
Subject: Re: (lack of) va_copy, and segfaults on x86_64
Date: Wed, 3 Mar 2010 16:41:48 -0500 (EST)

On Tue, 2 Mar 2010, Wim Lewis wrote:

Compiling ncurses-5.7 on macosx-x86_64, I find that it segfaults frequently within _nc_printf_string() in printw(). The reason seems to be the way that the va_list is used twice (once to compute the buffer's length, and once to actually format the string). Like some other architectures with a register passing convention, va_list on this machine is a (pointer to a) structure, not a simple pointer to stack memory as it is on an i386 or vax, and so the implicit copy made by a function call doesn't actually keep the caller's argument pointer from being modified by the callee.

The solution is pretty simple, to use va_copy() to explicitly make a copy of the argument pointer. It looks like an (unrelated?) use of va_copy was added and then reverted in 20061202/20061217, though, so I'm not sure what issue

The change then didn't actually work (portably for sure), and none of the
platforms that I could test on had a C runtime that could exercise the
change (and need it...).

By coincidence, I hit the same issue with vile this week (predictably, for glibc on amd64). So I worked through the kinks in the configure check to make it usable, and can add that to ncurses.

needs to be dealt with in order to use va_copy(). (Perhaps just an autoconf test for its existence?)

I'd guess that this problem affects other architectures too --- I've had to make similar changes in the past to get stuff to run on linux-ppc, eg.

This is the change I made to my local copy --- not intended as a patch submission, just to show what I'm talking about. With this change ncurses seems to work fine:

 _nc_printf_string(const char *fmt, va_list ap)
     char *result = 0;

     if (fmt != 0) {
!       va_list ap_copy;
!       va_copy(ap_copy, ap);
!       int len = _nc_printf_length(fmt, ap_copy);
!       va_end(ap_copy);

        if ((int) my_length < len + 1) {
            my_length = 2 * (len + 1);

Bug-ncurses mailing list

Thomas E. Dickey

reply via email to

[Prev in Thread] Current Thread [Next in Thread]