Date: Sat, 8 Jun 1996 20:52:03 -0400 (EDT) From: Tim Vanderhoek <tim@X3000> To: FreeBSD-gnats-submit@freebsd.org Subject: docs/1303: printf(3) manpage lies patently Message-ID: <199606090052.UAA00331@X3000> Resent-Message-ID: <199606090500.WAA16650@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 1303 >Category: docs >Synopsis: printf(3) manpage lies patently >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Class: doc-bug >Submitter-Id: current-users >Arrival-Date: Sat Jun 8 22:00:01 PDT 1996 >Last-Modified: >Originator: Tim Vanderhoek >Organization: League of Those With Too Much Time >Release: FreeBSD 2.2-960501-SNAP i386 >Environment: bin and manpages distributions installed. FreeBSD is also installed somewhere. >Description: The sixth last line of the printf(3) manpage says "Because sprintf() and vsprintf() assume an infinitely long string, callers must be careful not to overflow the actual space; this is often impossible to assure." The last statement in the quote is a patent lie, as the following code will readily demonstrate. It is never impossible to assure that sprintf() and vsprintf() do not overflow the actual space available to them. cut here------> #include <stdio.h> #include <stdarg.h> /* main (); */ /* "... no type or storage class" :( */ signed int Vasprintf (char **, char *, ...); main () { char * string; int n; n = Vasprintf (&string, "FaVe%d%d%sDeAl", 2355, 1235, "asase"); printf ("The string \"%s\" occupies %d chars.\n", string, n); _exit (-7); } signed int Vasprintf (char **ret, char * template, ...) /* You didn't actually expect me to turn this into avsprintf(), did you!? */ { va_list xargs; int sockets[2], child; FILE *tf; int retlen; if (pipe(sockets) < 0) { perror ("Can't create pipe"); exit (10); } va_start (xargs, template); if (tf = fdopen (sockets[1], "w")) { retlen = vfprintf (tf, template, xargs); } else { perror ("Can't open stream"); exit (1); } va_end (xargs); if (!(*ret = (char *) malloc (retlen + 1))) perror ("Malloc failure (out of memory?)"); if (!*ret) exit (666); /* who really reads exit codes, anyways? */ /* we now know how many chars are to be printed. Let's DO IT! */ if (vsprintf (*ret, template, xargs) != retlen) { printf ("AHHH!!! The printf(3) manpages is correct!!\n"); exit (777); } return retlen; } /* sockets? close what sockets? */ <------end cutting here No matter what format string we hand Vasprintf() from main(), it [Vasprintf()] will return the number of characters we need to alloc for sprintf() and vsprintf() thus allowing us to prevent them from "overflowing the actual space" (printf(3)) available to them. >How-To-Repeat: I don't know. >Fix: Change the sentence starting on the sixth line of the printf(3) manpage to "Because sprintf() and vsprintf() assume an infinitely long string, callers must be careful not to overflow the actual space; this often requires a silly function to prevent from happening." >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199606090052.UAA00331>