From owner-freebsd-bugs Sat Jun 8 22:00:06 1996 Return-Path: owner-bugs Received: (from root@localhost) by freefall.freebsd.org (8.7.5/8.7.3) id WAA16668 for bugs-outgoing; Sat, 8 Jun 1996 22:00:06 -0700 (PDT) Received: (from gnats@localhost) by freefall.freebsd.org (8.7.5/8.7.3) id WAA16650; Sat, 8 Jun 1996 22:00:03 -0700 (PDT) Resent-Date: Sat, 8 Jun 1996 22:00:03 -0700 (PDT) Resent-Message-Id: <199606090500.WAA16650@freefall.freebsd.org> Resent-From: gnats (GNATS Management) Resent-To: freebsd-bugs Resent-Reply-To: FreeBSD-gnats@freefall.FreeBSD.org, ac199@freenet.hamilton.on.ca Received: from X3000 (ppp1544.on.sympatico.ca [206.172.249.8]) by freefall.freebsd.org (8.7.5/8.7.3) with ESMTP id VAA16111 for ; Sat, 8 Jun 1996 21:54:42 -0700 (PDT) Received: (from tim@localhost) by X3000 (8.7.5/8.7.3) id UAA00331; Sat, 8 Jun 1996 20:52:03 -0400 (EDT) Message-Id: <199606090052.UAA00331@X3000> Date: Sat, 8 Jun 1996 20:52:03 -0400 (EDT) From: Tim Vanderhoek Reply-To: ac199@freenet.hamilton.on.ca To: FreeBSD-gnats-submit@freebsd.org X-Send-Pr-Version: 3.2 Subject: docs/1303: printf(3) manpage lies patently Sender: owner-bugs@freebsd.org X-Loop: FreeBSD.org Precedence: bulk >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 #include /* 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: