Skip site navigation (1)Skip section navigation (2)
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>