Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!uunet!husc6!cmcl2!brl-adm!umd5!mimsy!chris From: chris@mimsy.UUCP (Chris Torek) Newsgroups: comp.unix.wizards,comp.os.minix Subject: Re: obscure questions on sprintf(3S) Message-ID: <8523@mimsy.UUCP> Date: Fri, 11-Sep-87 13:34:56 EDT Article-I.D.: mimsy.8523 Posted: Fri Sep 11 13:34:56 1987 Date-Received: Sun, 13-Sep-87 09:33:16 EDT References: <1484@cybvax0.UUCP> Sender: chris@mimsy.UUCP Lines: 97 Keywords: printf Xref: mnetor comp.unix.wizards:4211 comp.os.minix:1620 [Our sys file was broken for a while, and I think this did not go out to the net in general. Apologies if this is a repeat.] In article <1484@cybvax0.UUCP> amit@cybvax0.UUCP (Amit Green) writes: >I am implementing a secure version of sprintf(3S), something that won't >randomly overrun buffers. A curious coincidence.... >Since we don't have source; its a bit hard to find how sprintf(3S) >works in some of the more obscure areas. ... I would like help from >anyone who can legally divulge it* (See footnote). This is no help, as sprintf() works differently in different Unixes. 4BSD has a flag called _IOSTRG, I/O to string, but this is not in fact ever tested, and writing to a struct _iobuf that has _IOSTRG and _IOWRT set can surprise you (it certainly surprised *me*). I believe at least one version of Unix uses special static buffer structures to tell `file' buffers from `string' buffers. All of which brings me to. . . . I have reimplemented stdio for 4.3BSD with a new interface. All of the old documented functions are still there with the same interface; some undocumented functions are gone, and (due to widespread use) some still remain. There is one new interface: FILE *funopen( void *p, /* `char *p' in pre-ANSI-C version */ int (*readfn)(void *p, char *buf, int n), int (*writefn)(void *p, const char *buf, int n), long (*seekfn)(void *p, off_t off, int whence), int (*closefn)(void *p)); There are two aliases: #define fropen(p, fn) funopen(p, fn, NULL, NULL, NULL) #define fwopen(p, fn) funopen(p, NULL, fn, NULL, NULL) /* nb. there are casts in the pre-ANSI-C version */ The functions `readfn', `writefn', `seekfn', and `closefn' are called to perform read, write, seek, and close operations; they are expected to return the same values as a corresponding read, write, seek, or close call if the argument `p' were a file descriptor. The pointer `p' is never examined, and is passed to the four functions; it serves as an identifier, if required. If any of readfn, writefn, or seekfn are given as NULL, the corresponding operation is disabled; if closefn is NULL, no special operation is done at close time beyond flushing any buffered text. Note that given this interface, it is possible (though not necessarily efficient) to build any other interface, including the original stdio interface. In particular, it is possible to implement both a `safe sprintf' and a `dynamic string sprintf'. The former is not as efficient as it might be, and for this and a few other reasons, it might be best to present one more interface: FILE *memopen(char *addr, unsigned int len, char *mode); /* e.g., f = memopen(buf, sizeof (buf), "w") */ This would permit a `safe sprintf' as (any variation on) the following: int ssprintf(s, len, fmt, va_alist) char *s; unsigned int len; char *fmt; va_dcl { va_list ap; FILE *f; if ((f = memopen(s, len, "w")) == NULL) return (-1); /* could not write */ va_start(ap); (void) vfprintf(f, fmt, ap); va_end(ap); (void) putc(0, f); if (ferror(f)) { /* buffer overflow */ (void) fclose(f); return (1); /* note that string is not \0 terminated */ } return (0); /* all OK */ } Note that memopen() is purely for efficiency: ssprintf() can still be implemented without it, as long as one has funopen(). I hope that this interface, and perhaps my implementation, will be distributed with some future release of 4BSD (if there is in fact such a release [hedge, hedge]). If you have strong feelings on memopen, or on the names for any of the new functions, you might do well to send me mail by October or so, `before the concrete sets'. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris