Package: libc6 Version: 2.7-18lenny7 It is not a heisenbug as suggested by the file name. Its a hard one. It fails, but man page malloc example works.
Is this a bug in vsnprintf or my fprint.c? I use alloca which appears to succeed before calling vsnprintf which then segfaults. String is no larger than many auto arrays. Is stack allocation failing later?
/* 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; i=vfnprint(fdout, i, fmt, ap); if(i<-1) i=vfnprint(fdout, 1-i, fmt, ap); 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; }
/* fprint.h - unistdio fprint fuction - Andrew Buckeridge */ #define NONSTDBUF 1024 int vfnprint(int fdout, int r, const char *fmt, va_list ap); int vfprint(int fdout, const char *fmt, va_list ap); int fprint(int fdout, const char *fmt, ...);
/*BINFMTC: -O -Wuninitialized -Werror -pedantic-errors Goes away when you strace. With other example in which read from pipe gets broken up. This is now a hard bug. */ #include <string.h> #include "fprint.c" int main() { char b[1024]; memset(b,'H',1024); /* b[1022]='\n'; */ b[1023]='\0'; /* we succeed on first go */ fprint(1,"%s",b); /* we fail on first go but second go segfaults */ fprint(1,"%s\n",b); /* not reached */ fprint(1,"%dH%s\n",strlen(b),b); return 0; }
/*BINFMTC: -O -Wuninitialized -Werror -pedantic-errors The man page example works. */ #include <string.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <stdarg.h> char * make_message(const char *fmt, ...) { /* Guess we need no more than 100 bytes. */ int n, size = 100; char *p, *np; va_list ap; if ((p = malloc(size)) == NULL) return NULL; while (1) { /* Try to print in the allocated space. */ va_start(ap, fmt); n = vsnprintf(p, size, fmt, ap); va_end(ap); /* If that worked, return the string. */ if (n > -1 && n < size) return p; /* Else try again with more space. */ if (n > -1) /* glibc 2.1 */ size = n+1; /* precisely what is needed */ else /* glibc 2.0 */ size *= 2; /* twice the old size */ if ((np = realloc (p, size)) == NULL) { free(p); return NULL; } else { p = np; } } } int main() { char *s; char b[1024]; memset(b,'H',1024); /* b[1022]='\n'; */ b[1023]='\0'; /* we succeed on first go */ s=make_message("%s",b); write(1,s,strlen(s)); free(s); /* we fail on first go but second go segfaults */ s=make_message("%s\n",b); write(1,s,strlen(s)); free(s); /* not reached */ s=make_message("%dH%s\n",strlen(b),b); write(1,s,strlen(s)); free(s); return 0; }