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

Bug#609756: vsnprintf segfaults on second attempt with alloca



Package: libc6
Version: 2.7-18lenny7

C99 only va_copy does help. This is a new one for me.
Does vfnprint destroy the callers ap?
Does this break C89 and C90?

Gcc did not require -std=c99 or -std=gnu99 to accept va_copy.

Assuming <stdarg.h> was something like
#define va_start(ap, last) (ap)=(va_list)(&(last)+sizeof(last))
#define va_arg(ap, type) ((ap)+=sizeof(type),(type)*((ap)-sizeof(type)))
would be wrong.

On Wed, 12 Jan 2011 10:18:41 +0000
Florian Weimer <fweimer@bfk.de> wrote:

> * Andrew Buckeridge:
> 
> > int vfprint(int fdout, const char *fmt, va_list ap)
> > {
> > 	int i=NONSTDBUF;
> > 	i=vfnprint(fdout, i, fmt, ap);
> > 	if(i<-1)
> > 		i=vfnprint(fdout, 1-i, fmt, ap);
> > 	return i;
> > }
> 
> va_copy seems to be missing here.
> 
> -- 
> Florian Weimer                <fweimer@bfk.de>
> BFK edv-consulting GmbH       http://www.bfk.de/
> Kriegsstraße 100              tel: +49-721-96201-1
> D-76133 Karlsruhe             fax: +49-721-96201-99
/*
fprint.c - unistdio fprint function - Andrew Buckeridge
*/
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <alloca.h>
#include "fprint.h"
/*
#include <string.h>
*/
/* +Ve == bytes written -Ve == bytes required */

int vfnprint(int fdout, int r, const char *fmt, va_list ap)
{
	int i;
	char *p;

	p=alloca(r);

	p[r-1]='\0';
/*
	memset(p,0,r);
*/
/* NB: alloca may return shit, but no it _IS_ vsnprintf */

fprintf(stderr,"\nvsnprintf(%d,%d,%p,...)=",fdout,r,fmt);

/* segfault inside this  */
	i=vsnprintf(p,r,fmt,ap);

fprintf(stderr,"=%d\n",i);

	if(i<0) {
		return 1-2*r;
	}
	if(i<r) {
		return ((write(fdout,p,i))==i)?i:-1;
	}
	return -i;
}

/* +Ve == bytes written -Ve == failure */

int vfprint(int fdout, const char *fmt, va_list ap)
{
	int i=NONSTDBUF;
	va_list aq;

	va_copy(aq,ap);
	i=vfnprint(fdout, i, fmt, ap);
	if(i<-1)
		i=vfnprint(fdout, 1-i, fmt, aq);
	va_end(aq);
	return i;
}

int fprint(int fdout, const char *fmt, ...)
{
	va_list ap;
	int r;

	va_start(ap, fmt);
	r=vfprint(fdout, fmt, ap);
	va_end(ap);
	return r;
}



Reply to: