NetBSD Problem Report #1862
From gnats Wed Dec 27 19:31:53 1995
Received: (from jtc@localhost) by pain.lcs.mit.edu (8.6.12/8.6.9) id TAA04634; Wed, 27 Dec 1995 19:31:53 -0500
Message-Id: <199512280031.TAA04634@pain.lcs.mit.edu>
Date: Wed, 27 Dec 1995 19:31:53 -0500
From: "J.T. Conklin" <jtc>
Reply-To: jtc@wimsey.com
To: sun-lamp-gnats
Subject: printf/scanf don't support X/Open positional parameters
X-Send-Pr-Version: 3.95
>Number: 1862
>Category: lib
>Synopsis: printf/scanf don't support X/Open positional parameters
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: kleink
>State: closed
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Wed Dec 27 19:35:23 +0000 1995
>Closed-Date: Sun Jun 26 06:49:48 +0000 2016
>Last-Modified: Sun Jun 26 06:49:48 +0000 2016
>Originator: J.T. Conklin
>Release: 1.1
>Organization:
>Environment:
System: NetBSD pain.lcs.mit.edu 1.0A NetBSD 1.0A (PAIN) #0: Sat Oct 7 08:07:40 EDT 1995 mycroft@pain.lcs.mit.edu:/a/users/mycroft/sys/arch/i386/compile/PAIN i386
>Description:
Printf and scanf do not support the X/Open positional parameters. This
makes message catalogs much less useful than they could be.
>How-To-Repeat:
Use code that uses this feature.
>Fix:
Add support to printf/scanf in a efficent manner.
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: lib-bug-people->jtc
Responsible-Changed-By: jtc
Responsible-Changed-When: Thu Dec 28 14:10:57 1995
Responsible-Changed-Why:
Responsible-Changed-From-To: jtc->lib-bug-people
Responsible-Changed-By: fair
Responsible-Changed-When: Thu Jun 17 14:37:47 PDT 1999
Responsible-Changed-Why:
jtc's attentions are elsewhere - someone else should pick this up.
(if I read this right, it's an i18n problem)
Responsible-Changed-From-To: lib-bug-people->kleink
Responsible-Changed-By: lukem
Responsible-Changed-When: Wed Apr 18 05:03:00 PDT 2001
Responsible-Changed-Why:
klaus is our standards guru; what are his thoughts?
From: Klaus Klein <kleink@er.reziprozitaet.de>
To: lukem@netbsd.org
Cc: gnats-bugs@netbsd.org, lib-bug-people@netbsd.org
Subject: Re: lib/1862
Date: 18 Apr 2001 14:36:34 +0200
These are indeed extensions defined in XPG4; Erik's comment about i18n
is likely to have been guided by that these positional parameters can
be handy when doing i18n work. They're one of the reasons why I added
va_copy.
I can look after this after the specified-width integer rototill,
which affects printf/scanf as well.
- Klaus
From: David Laight <david@l8s.co.uk>
To: gnats-bugs@gnats.netbsd.org
Subject: re: lib/1862: printf/scanf don't support X/Open positional parameters
Date: Mon, 1 Sep 2003 15:50:02 +0100
I've just sat down and implemented this for printf.
However there are definite security problems lurking for scanf and
even parts of printf.
Consider the following eror message:
printf("value %d unexpected\n", n);
Now if I have control over the format string and the value of 'n' I can
write a small integer to any location in the program by making 'n' its
address and the format "xxxx%n".
Without control of the data "xxxx%<argnum>$n..." could be arranged to
overwrite via ANY pointer on the callers stack.
Similarly use of %<argnum>$ in a scanf format string could overwrite
the value read using any on-stack pointer.
These overwrites can all be done with standard format strings, but the
%n$ variants make it so much easier!
Anyway the patch is below.
It allows upto 1024 arguments, but TOG say that NL_ARGMAX need only be 9.
Assuming a single digit would simplify some of the code, and a small number
does reduce the opportunity for locating a useful on-stack pointer.
David
Index: vfprintf.c
===================================================================
RCS file: /cvsroot/src/lib/libc/stdio/vfprintf.c,v
retrieving revision 1.45
diff -u -p -r1.45 vfprintf.c
--- vfprintf.c 2003/08/07 16:43:34 1.45
+++ vfprintf.c 2003/09/01 14:43:02
@@ -65,9 +65,20 @@ __RCSID("$NetBSD: vfprintf.c,v 1.45 2003
#include "fvwrite.h"
#include "extern.h"
+#ifdef FLOATING_POINT
+#define POSITIONAL_PARAMS
+#endif
+
static int __sprint __P((FILE *, struct __suio *));
static int __sbprintf __P((FILE *, const char *, va_list))
__attribute__((__format__(__printf__, 2, 0)));
+#ifdef POSITIONAL_PARAMS
+static void *set_printf_args(const char *, _BSD_VA_LIST_);
+static uintmax_t get_arg_int(void *, int);
+static double get_arg_double(void *, int);
+static void *get_arg_ptr(void *, int);
+static void free_parg(void *);
+#endif
/*
* Flush out all the vectors defined by the given uio,
@@ -187,6 +198,11 @@ __UNCONST(v)
#define SIZEINT 0x200 /* (signed) size_t */
#define ZEROPAD 0x400 /* zero (as opposed to blank) pad */
#define FPT 0x800 /* Floating point number */
+#ifdef POSITIONAL_PARAMS
+#define POINTER 0x10000 /* Pointer to something */
+#define SIGNED 0x20000 /* signed value */
+#define CHARINT 0x40000 /* move above when %hhd implemented */
+#endif
int
vfprintf(fp, fmt0, ap)
@@ -264,11 +280,16 @@ vfprintf_unlocked(fp, fmt0, ap)
{' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
static const char zeroes[PADSIZE] =
{'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
+#ifdef POSITIONAL_PARAMS /* %nnn$... */
+ void *parg = NULL;
+ int argnum = 0;
+ char *ncp;
+#endif
/*
* BEWARE, these `goto error' on error, and PAD uses `n'.
*/
-#define PRINT(ptr, len) { \
+#define PRINT(ptr, len) do { \
iovp->iov_base = __UNCONST(ptr); \
iovp->iov_len = (len); \
uio.uio_resid += (len); \
@@ -278,8 +299,9 @@ vfprintf_unlocked(fp, fmt0, ap)
goto error; \
iovp = iov; \
} \
-}
-#define PAD(howmany, with) { \
+} while (/*CONSTCOND*/0)
+
+#define PAD(howmany, with) do { \
if ((n = (howmany)) > 0) { \
while (n > PADSIZE) { \
PRINT(with, PADSIZE); \
@@ -287,19 +309,20 @@ vfprintf_unlocked(fp, fmt0, ap)
} \
PRINT(with, n); \
} \
-}
-#define FLUSH() { \
+} while (/*CONSTCOND*/0)
+
+#define FLUSH() do { \
if (uio.uio_resid && __sprint(fp, &uio)) \
goto error; \
uio.uio_iovcnt = 0; \
iovp = iov; \
-}
+} while (/*CONSTCOND*/0)
/*
* To extend shorts properly, we need both signed and unsigned
* argument extraction methods.
*/
-#define SARG() \
+#define SARG(flags, ap) \
(flags&MAXINT ? va_arg(ap, intmax_t) : \
flags&PTRINT ? va_arg(ap, ptrdiff_t) : \
flags&SIZEINT ? va_arg(ap, ssize_t) : /* XXX */ \
@@ -307,7 +330,7 @@ vfprintf_unlocked(fp, fmt0, ap)
flags&LONGINT ? va_arg(ap, long) : \
flags&SHORTINT ? (long)(short)va_arg(ap, int) : \
(long)va_arg(ap, int))
-#define UARG() \
+#define UARG(flags, ap) \
(flags&MAXINT ? va_arg(ap, uintmax_t) : \
flags&PTRINT ? va_arg(ap, uintptr_t) : /* XXX */ \
flags&SIZEINT ? va_arg(ap, size_t) : \
@@ -383,13 +406,24 @@ reswitch: switch (ch) {
flags |= ALT;
goto rflag;
case '*':
+#ifdef POSITIONAL_PARAMS
+ if (parg != NULL) {
+ n = strtoul(fmt, &ncp, 10);
+ fmt = ncp;
+ ch = *fmt++;
+ if (ch != '$')
+ goto reswitch;
+ width = (int)get_arg_int(parg, n);
+ } else
+#endif
+ width = va_arg(ap, int);
/*
* ``A negative field width argument is taken as a
* - flag followed by a positive field width.''
* -- ANSI X3J11
* They don't exclude field widths read from args.
*/
- if ((width = va_arg(ap, int)) >= 0)
+ if (width >= 0)
goto rflag;
width = -width;
/* FALLTHROUGH */
@@ -401,6 +435,16 @@ reswitch: switch (ch) {
goto rflag;
case '.':
if ((ch = *fmt++) == '*') {
+#ifdef POSITIONAL_PARAMS
+ if (parg != NULL) {
+ n = strtoul(fmt, &ncp, 10);
+ fmt = ncp;
+ ch = *fmt++;
+ if (ch != '$')
+ goto reswitch;
+ n = (int)get_arg_int(parg, n);
+ } else
+#endif
n = va_arg(ap, int);
prec = n < 0 ? -1 : n;
goto rflag;
@@ -427,6 +471,14 @@ reswitch: switch (ch) {
n = 10 * n + to_digit(ch);
ch = *fmt++;
} while (is_digit(ch));
+#ifdef POSITIONAL_PARAMS
+ if (ch == '$') {
+ if (parg == NULL)
+ parg = set_printf_args(fmt0, ap);
+ argnum = n;
+ goto rflag;
+ }
+#endif
width = n;
goto reswitch;
#ifdef FLOATING_POINT
@@ -458,6 +510,11 @@ reswitch: switch (ch) {
flags |= SIZEINT;
goto rflag;
case 'c':
+#ifdef POSITIONAL_PARAMS
+ if (parg != NULL)
+ *buf = (int)get_arg_int(parg, argnum);
+ else
+#endif
*buf = va_arg(ap, int);
cp = buf;
size = 1;
@@ -468,7 +525,12 @@ reswitch: switch (ch) {
/*FALLTHROUGH*/
case 'd':
case 'i':
- _uintmax = SARG();
+#ifdef POSITIONAL_PARAMS
+ if (parg != NULL)
+ _uintmax = get_arg_int(parg, argnum);
+ else
+#endif
+ _uintmax = SARG(flags, ap);
if ((intmax_t)_uintmax < 0) {
_uintmax = -_uintmax;
sign = '-';
@@ -488,6 +550,11 @@ reswitch: switch (ch) {
prec = 1;
}
+#ifdef POSITIONAL_PARAMS
+ if (parg != NULL)
+ _double = get_arg_double(parg, argnum);
+ else
+#endif
if (flags & LONGDBL) {
_double = (double) va_arg(ap, long double);
} else {
@@ -549,6 +616,15 @@ reswitch: switch (ch) {
break;
#endif /* FLOATING_POINT */
case 'n':
+#ifdef POSITIONAL_PARAMS
+ if (parg != NULL)
+ /*
+ * This could be implemented, but it stinks
+ * of a security risk.
+ */
+ PRINT("(%n unassigned)", 15);
+ else
+#endif
if (flags & MAXINT)
*va_arg(ap, intmax_t *) = ret;
else if (flags & PTRINT)
@@ -568,7 +644,12 @@ reswitch: switch (ch) {
flags |= LONGINT;
/*FALLTHROUGH*/
case 'o':
- _uintmax = UARG();
+#ifdef POSITIONAL_PARAMS
+ if (parg != NULL)
+ _uintmax = get_arg_int(parg, argnum);
+ else
+#endif
+ _uintmax = UARG(flags, ap);
base = OCT;
goto nosign;
case 'p':
@@ -579,15 +660,26 @@ reswitch: switch (ch) {
* defined manner.''
* -- ANSI X3J11
*/
+#ifdef POSITIONAL_PARAMS
+ if (parg != NULL)
+ _uintmax = (uintptr_t)get_arg_ptr(parg, argnum);
+ else
+#endif
/* NOSTRICT */
- _uintmax = (u_long)va_arg(ap, void *);
+ _uintmax = (uintptr_t)va_arg(ap, void *);
base = HEX;
xdigs = "0123456789abcdef";
flags |= HEXPREFIX;
ch = 'x';
goto nosign;
case 's':
- if ((cp = va_arg(ap, char *)) == NULL)
+#ifdef POSITIONAL_PARAMS
+ if (parg != NULL)
+ cp = get_arg_ptr(parg, argnum);
+ else
+#endif
+ cp = va_arg(ap, char *);
+ if (cp == NULL)
cp = "(null)";
if (prec >= 0) {
/*
@@ -611,7 +703,12 @@ reswitch: switch (ch) {
flags |= LONGINT;
/*FALLTHROUGH*/
case 'u':
- _uintmax = UARG();
+#ifdef POSITIONAL_PARAMS
+ if (parg != NULL)
+ _uintmax = get_arg_int(parg, argnum);
+ else
+#endif
+ _uintmax = UARG(flags, ap);
base = DEC;
goto nosign;
case 'X':
@@ -619,7 +716,13 @@ reswitch: switch (ch) {
goto hex;
case 'x':
xdigs = "0123456789abcdef";
-hex: _uintmax = UARG();
+hex:
+#ifdef POSITIONAL_PARAMS
+ if (parg != NULL)
+ _uintmax = get_arg_int(parg, argnum);
+ else
+#endif
+ _uintmax = UARG(flags, ap);
base = HEX;
/* leading 0x/X only if non-zero */
if (flags & ALT && _uintmax != 0)
@@ -797,6 +900,10 @@ done:
error:
if (__sferror(fp))
ret = -1;
+#ifdef POSITIONAL_PARAMS
+ if (parg != NULL)
+ free_parg(parg);
+#endif
return (ret);
}
@@ -883,3 +990,213 @@ exponent(p0, expon, fmtch)
return (p - p0);
}
#endif /* FLOATING_POINT */
+
+#ifdef POSITIONAL_PARAMS
+struct parg {
+ int flags;
+ union {
+ uintmax_t _uintmax;
+ void *_pointer;
+ double _double;
+ } val;
+};
+
+static void *parse_fmt(const char *);
+
+static uintmax_t
+get_arg_int(void *parg, int argnum)
+{
+ struct parg *arg = parg;
+
+ if (argnum >= arg->flags)
+ return 0;
+ return arg[argnum].val._uintmax;
+}
+
+static double
+get_arg_double(void *parg, int argnum)
+{
+ struct parg *arg = parg;
+
+ if (argnum >= arg->flags)
+ return 0;
+ return arg[argnum].val._double;
+}
+
+static void *
+get_arg_ptr(void *parg, int argnum)
+{
+ struct parg *arg = parg;
+
+ if (argnum >= arg->flags)
+ return 0;
+ return arg[argnum].val._pointer;
+}
+
+static void *
+set_printf_args(const char *fmt, _BSD_VA_LIST_ ap)
+{
+ struct parg *arg;
+ int flags;
+ int i;
+
+ /*
+ * In order to set ap so that the n'th argument can be picked next
+ * we have to know the type of all the arguments.
+ */
+ arg = parse_fmt(fmt);
+ if (arg == NULL)
+ return NULL;
+
+ /* Now walk ap along the arguments saving the values */
+ for (i = 1; i < arg[0].flags; i++) {
+ flags = arg[i].flags;
+ if (flags == 0)
+ /* unsigned int or arg not used in format */
+ arg[i].val._uintmax = va_arg(ap, int);
+ else if (flags & POINTER)
+ if (flags & CHARINT)
+ arg[i].val._pointer = va_arg(ap, char *);
+ else
+ arg[i].val._pointer = va_arg(ap, void *);
+ else if (flags & FPT)
+ if (flags & LONGDBL)
+ arg[i].val._double = va_arg(ap, long double);
+ else
+ arg[i].val._double = va_arg(ap, double);
+ else if (flags & SIGNED)
+ arg[i].val._uintmax = SARG(flags, ap);
+ else
+ arg[i].val._uintmax = UARG(flags, ap);
+ }
+ return arg;
+}
+
+static void
+free_parg(void *arg)
+{
+
+ free(arg);
+}
+
+static void
+save_arg(struct parg **parg, int argnum, int flags)
+{
+ struct parg *arg = *parg, *narg;
+ int newlim;
+
+ if (argnum <= 0 || argnum > 1024) /* Should be {NL_ARGMAX} */
+ return;
+
+ if (arg == NULL || argnum >= arg[0].flags) {
+ newlim = argnum + 15;
+ narg = realloc(arg, newlim * sizeof *arg);
+ if (narg == NULL)
+ return;
+ memset(narg + narg[0].flags, 0,
+ (newlim - narg[0].flags) * sizeof *arg);
+ narg[0].flags = newlim;
+ *parg = narg;
+ arg = narg;
+ }
+ arg += argnum;
+ arg->flags = flags;
+}
+
+static void *
+parse_fmt(const char *fmt)
+{
+ struct parg *arg = NULL;
+ char *ncp; /* avoid &fmt to kelp optimsation */
+ int argnum;
+ int flags;
+ int n;
+ char ch;
+ wchar_t wc;
+ mbstate_t ps;
+
+ mbrtowc(NULL, NULL, 0, &ps);
+
+ for (;;) {
+ do {
+ n = mbrtowc(&wc, fmt, MB_CUR_MAX, &ps);
+ if (n <= 0)
+ return arg;
+ fmt += n;
+ } while (wc != '%');
+ flags = 0;
+ argnum = 0;
+ for (;;) {
+ ch = *fmt++;
+ switch (ch) {
+ case ' ': continue;
+ case '#': continue;
+ case '-': continue;
+ case '+': continue;
+ case '*': continue;
+ case '0': continue;
+ case '.': continue;
+ case 'h': flags |= SHORTINT; continue;
+ case 'j': flags |= MAXINT; continue;
+#ifdef FLOATING_POINT
+ case 'L': flags |= LONGDBL; continue;
+#endif
+ case 'q': flags |= QUADINT; continue;
+ case 't': flags |= PTRINT; continue;
+ case 'z': flags |= SIZEINT; continue;
+ case 'l':
+ if (fmt[0] == 'l') {
+ fmt++;
+ flags |= QUADINT;
+ } else
+ flags |= LONGINT;
+ continue;
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ n = strtoul(fmt - 1, &ncp, 10);
+ fmt = ncp;
+ if (*fmt == '$') {
+ fmt++;
+ if (argnum == 0)
+ argnum = n;
+ else
+ save_arg(&arg, n, SIGNED);
+ }
+ continue;
+ case 'D':
+ flags |= LONGINT | SIGNED;
+ break;
+ case 'O': case 'U':
+ flags |= LONGINT;
+ break;
+ case 'd': case 'i':
+ flags |= SIGNED;
+ break;
+ case 'c': case 'o': case 'u': case 'X': case 'x':
+ break;
+#ifdef FLOATING_POINT
+ case 'e': case 'f': case 'g':
+ case 'E': case 'F': case 'G':
+ flags |= FPT;
+ break;
+#endif /* FLOATING_POINT */
+ case 's':
+ flags |= CHARINT | POINTER;
+ break;
+ case 'n': case 'p':
+ flags |= POINTER;
+ break;
+ default:
+ /* Unexpected end of format */
+ if (ch == 0)
+ return arg;
+ ch = 0;
+ break;
+ }
+ if (ch != 0)
+ save_arg(&arg, argnum, flags);
+ break;
+ }
+ }
+}
+#endif
--
David Laight: david@l8s.co.uk
From: Charles Blundell <cb@netbsd.org>
To: David Laight <david@l8s.co.uk>
Cc: gnats-bugs@gnats.netbsd.org
Subject: Re: lib/1862: printf/scanf don't support X/Open positional parameters
Date: Mon, 1 Sep 2003 17:32:41 +0100
on Mon, Sep 01, 2003 at 03:50:02PM +0100, David Laight wrote:
> These overwrites can all be done with standard format strings, but the
> %n$ variants make it so much easier!
When the parameters to printf are bounded to some length, the
presence of this feature can make things possible that were not
previously.
> Index: vfprintf.c
> ===================================================================
> RCS file: /cvsroot/src/lib/libc/stdio/vfprintf.c,v
> retrieving revision 1.45
> diff -u -p -r1.45 vfprintf.c
> --- vfprintf.c 2003/08/07 16:43:34 1.45
> +++ vfprintf.c 2003/09/01 14:43:02
> +static uintmax_t
> +get_arg_int(void *parg, int argnum)
> +{
> + struct parg *arg = parg;
> +
> + if (argnum >= arg->flags)
> + return 0;
> + return arg[argnum].val._uintmax;
> +}
I think you need to check for a negative argnum here, since argnum
is the return from strtoul? (which allows it to vary above INT_MAX
and negatives..)
Likewise for get_arg_double and get_arg_ptr.
From: Simon Gerraty <sjg@juniper.net>
To: David Laight <david@l8s.co.uk>
Cc: gnats-bugs@gnats.netbsd.org
Subject: Re: lib/1862: printf/scanf don't support X/Open positional parameters
Date: Mon, 01 Sep 2003 09:53:56 -0700
On Mon, 1 Sep 2003 15:50:02 +0100, David Laight writes:
>I've just sat down and implemented this for printf.
Thanks. Do we _need_ this though?
>However there are definite security problems lurking for scanf and
>even parts of printf.
Yep, I recall a paper about just how easy it is to use this feature
to hack addresses in linux.
What's the rationale (X/Open's) for these changes anyway?
Thanks
--sjg
From: Martin Husemann <martin@duskware.de>
To: Simon Gerraty <sjg@juniper.net>
Cc: David Laight <david@l8s.co.uk>, gnats-bugs@gnats.netbsd.org
Subject: Re: lib/1862: printf/scanf don't support X/Open positional parameters
Date: Mon, 1 Sep 2003 19:08:01 +0200
On Mon, Sep 01, 2003 at 09:53:56AM -0700, Simon Gerraty wrote:
> What's the rationale (X/Open's) for these changes anyway?
You load the format string from a message catalog and translators are able to
move filled in parameters around. Pretty nice feature, but the specification
is way overcomplicated. It would be enough to allow positional pre-formated
string parameters, maybe with a width field.
(That's my understanding; I don't know anything of X/Open's motivation)
Martin
From: David Laight <david@l8s.co.uk>
To: Martin Husemann <martin@duskware.de>
Cc: Simon Gerraty <sjg@juniper.net>, gnats-bugs@gnats.netbsd.org
Subject: Re: lib/1862: printf/scanf don't support X/Open positional parameters
Date: Mon, 1 Sep 2003 20:58:14 +0100
On Mon, Sep 01, 2003 at 07:08:01PM +0200, Martin Husemann wrote:
> On Mon, Sep 01, 2003 at 09:53:56AM -0700, Simon Gerraty wrote:
> > What's the rationale (X/Open's) for these changes anyway?
>
> You load the format string from a message catalog and translators are able to
> move filled in parameters around. Pretty nice feature, but the specification
> is way overcomplicated. It would be enough to allow positional pre-formated
> string parameters, maybe with a width field.
I think that part of the original rational came from an internationalisation
process that extracted all (and I mean ALL) of the text strings from programs
into a message catalog. The translators where then expected to be able
to translate the numbered string fragments without any context!
(even "\n" got into the catalog!)
The only problem I see is that "%*.*d" isn't treated as a single entity
and always requires 3 argument specifiers "%3$*1$.*2$d".
My 'gut' feel is that the original implementation (and hence the syntax)
assumed that all the arguments (to printf) were the same size on the stack
and hence that the stack could just be indexed to find the desired value.
I think I might actually reduce the maximum number of selectable
arguments to 9 (the minimum that IEEE 1003.1 2001 requires) in order to
make it much harder to do a sucessful hack - and make the code simpler.
> (That's my understanding; I don't know anything of X/Open's motivation)
I've just looked at the X/Open XRAT, nothing about printf there [1].
There is an implementation in the 1996 Unixware 2 sources, the copyright
suggests this goes back to 1988 (and was always copyright Novell - IIRC
they changed all the copyrights to be Novell regardless of the original one!)
However this doesn't look like the original implementation (and I definitely
haven't copied it!). I don't have any pre-UW2 SVR4 sources.
David
[1] some interesting words about mkdir xxx/ though
--
David Laight: david@l8s.co.uk
From: "Perry E. Metzger" <perry@piermont.com>
To: David Laight <david@l8s.co.uk>
Cc: gnats-bugs@gnats.netbsd.org
Subject: Re: lib/1862: printf/scanf don't support X/Open positional parameters
Date: 02 Sep 2003 16:05:03 -0400
David Laight <david@l8s.co.uk> writes:
> I've just sat down and implemented this for printf.
One note. Open and FreeBSD have an implementation of this already. I
think it would be best if we shared their implementation, if only so
that we could avoid implementing new tweaks in the future by stealing
their code...
Perry
From: "Steven M. Bellovin" <smb@research.att.com>
To: "Perry E. Metzger" <perry@piermont.com>
Cc: David Laight <david@l8s.co.uk>, gnats-bugs@gnats.netbsd.org
Subject: Re: lib/1862: printf/scanf don't support X/Open positional parameters
Date: Tue, 02 Sep 2003 16:32:55 -0400
In message <871xuz553k.fsf@snark.piermont.com>, "Perry E. Metzger" writes:
>
>David Laight <david@l8s.co.uk> writes:
>> I've just sat down and implemented this for printf.
>
>One note. Open and FreeBSD have an implementation of this already. I
>think it would be best if we shared their implementation, if only so
>that we could avoid implementing new tweaks in the future by stealing
>their code...
But perhaps we shouldn't use the feature in any NetBSD code...
--Steve Bellovin, http://www.research.att.com/~smb
From: "Perry E. Metzger" <perry@piermont.com>
To: "Steven M. Bellovin" <smb@research.att.com>
Cc: David Laight <david@l8s.co.uk>, gnats-bugs@gnats.netbsd.org
Subject: Re: lib/1862: printf/scanf don't support X/Open positional parameters
Date: 02 Sep 2003 16:39:15 -0400
"Steven M. Bellovin" <smb@research.att.com> writes:
> But perhaps we shouldn't use the feature in any NetBSD code...
I tend to agree that the main purpose of implementing this should be
standards compliance.
--
Perry E. Metzger perry@piermont.com
From: David Holland <dholland-bugs@netbsd.org>
To: gnats-bugs@netbsd.org
Cc:
Subject: Re: lib/1862: printf/scanf don't support X/Open positional parameters
Date: Sat, 9 Feb 2008 18:28:03 +0000
Updating this for the century of the fruitbat: positional parameter
support has been committed for printf, but not scanf.
--
David A. Holland
dholland@netbsd.org
State-Changed-From-To: open->suspended
State-Changed-By: dholland@NetBSD.org
State-Changed-When: Wed, 27 Aug 2014 19:26:27 +0000
State-Changed-Why:
The conclusion some time ago was that we didn't want positional parameters
for scanf due to it being an unnecessary attack/exploit vector.
State-Changed-From-To: suspended->closed
State-Changed-By: dholland@NetBSD.org
State-Changed-When: Sun, 26 Jun 2016 06:49:48 +0000
State-Changed-Why:
The conclusion some time ago was that we didn't want positional parameters
for scanf due to it being an unnecessary attack/exploit vector.
Thus: WONTFIX.
(the printf part got done a long time ago)
>Unformatted:
See also standards/19556.
(Contact us)
$NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.