summaryrefslogtreecommitdiff
path: root/lib/libc/stdio/printf.3
diff options
context:
space:
mode:
authorchristos <christos@NetBSD.org>2007-06-09 18:51:19 +0000
committerchristos <christos@NetBSD.org>2007-06-09 18:51:19 +0000
commita9df04f00d8bf7d742f6ec93fb60ae6511baa67f (patch)
tree213089b0572fb623165e3792e7aa537baf6ea38e /lib/libc/stdio/printf.3
parent1b15aa2347ffb615f5f0570c2f4493bf3747be53 (diff)
bring in many changes from FreeBSD
Diffstat (limited to 'lib/libc/stdio/printf.3')
-rw-r--r--lib/libc/stdio/printf.3668
1 files changed, 371 insertions, 297 deletions
diff --git a/lib/libc/stdio/printf.3 b/lib/libc/stdio/printf.3
index e29edd605f4..997b67d41e5 100644
--- a/lib/libc/stdio/printf.3
+++ b/lib/libc/stdio/printf.3
@@ -1,4 +1,4 @@
-.\" $NetBSD: printf.3,v 1.43 2006/09/25 08:55:33 martin Exp $
+.\" $NetBSD: printf.3,v 1.44 2007/06/09 18:51:19 christos Exp $
.\"
.\" Copyright (c) 1990, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -33,7 +33,7 @@
.\"
.\" @(#)printf.3 8.1 (Berkeley) 6/4/93
.\"
-.Dd September 25, 2006
+.Dd June 9, 2007
.Dt PRINTF 3
.Os
.Sh NAME
@@ -79,9 +79,11 @@ The
family of functions produces output according to a
.Fa format
as described below.
+The
.Fn printf
and
.Fn vprintf
+functions
write output to
.Em stdout ,
the standard output stream;
@@ -97,6 +99,7 @@ and
.Fn vsnprintf
write to the character string
.Fa str ;
+and
.Fn asprintf
and
.Fn vasprintf
@@ -188,13 +191,21 @@ After the
the following appear in sequence:
.Bl -bullet
.It
-Zero or more of the following flags:
-.Bl -hyphen
+An optional field, consisting of a decimal digit string followed by a
+.Cm $ ,
+specifying the next argument to access.
+If this field is not provided, the argument following the last
+argument accessed will be used.
+Arguments are numbered starting at
+.Cm 1 .
+If unaccessed arguments in the format string are interspersed with ones that
+are accessed the results will be indeterminate.
.It
-A
-.Cm #
-character
-specifying that the value should be converted to an ``alternative form''.
+Zero or more of the following flags:
+.Bl -tag -width ".So \ Sc (space)"
+.It Sq Cm #
+The value should be converted to an
+.Dq alternate form .
For
.Cm c ,
.Cm d ,
@@ -222,6 +233,8 @@ for
.Cm X
conversions) prepended to it.
For
+.Cm a ,
+.Cm A ,
.Cm e ,
.Cm E ,
.Cm f ,
@@ -238,10 +251,8 @@ and
.Cm G
conversions, trailing zeros are not removed from the result as they
would otherwise be.
-.It
-A zero
-.Sq Cm \&0
-character specifying zero padding.
+.It So Cm 0 Sc (zero)
+Zero padding.
For all conversions except
.Cm n ,
the converted value is padded on the left with zeros rather than blanks.
@@ -255,12 +266,11 @@ If a precision is given with a numeric conversion
and
.Cm X ) ,
the
-.Sq Cm \&0
+.Cm 0
flag is ignored.
-.It
-A negative field width flag
-.Sq Cm \-
-indicates the converted value is to be left adjusted on the field boundary.
+.It Sq Cm \-
+A negative field width flag;
+the converted value is to be left adjusted on the field boundary.
Except for
.Cm n
conversions, the converted value is padded on the right with blanks,
@@ -270,10 +280,12 @@ A
overrides a
.Sq Cm \&0
if both are given.
-.It
-A space, specifying that a blank should be left before a positive number
+.It So "\ " Sc (space)
+A blank should be left before a positive number
produced by a signed conversion
-.Pf ( Cm d ,
+.Pf ( Cm a ,
+.Cm A
+.Cm d ,
.Cm e ,
.Cm E ,
.Cm f ,
@@ -282,14 +294,24 @@ produced by a signed conversion
.Cm G ,
or
.Cm i ) .
-.It
-A
-.Sq Cm +
-character specifying that a sign always be placed before a
+.It Sq Cm +
+A sign must always be placed before a
number produced by a signed conversion.
A
.Sq Cm +
overrides a space if both are used.
+.It Sq Cm '
+Decimal conversions
+.Cm ( d , u ,
+or
+.Cm i )
+or the integral portion of a floating point conversion
+.Cm ( f
+or
+.Cm F )
+should be grouped and separated by thousands using
+the non-monetary separator returned by
+.Xr localeconv 3 .
.El
.It
An optional decimal digit string specifying a minimum field width.
@@ -310,6 +332,8 @@ This gives the minimum number of digits to appear for
and
.Cm X
conversions, the number of digits to appear after the decimal-point for
+.Cm a ,
+.Cm A ,
.Cm e ,
.Cm E ,
.Cm f ,
@@ -324,164 +348,76 @@ string for
.Cm s
conversions.
.It
-The optional character
-.Cm h ,
-specifying that a following
-.Cm d ,
-.Cm i ,
-.Cm o ,
-.Cm u ,
-.Cm x ,
-or
-.Cm X
-conversion corresponds to a
-.Em short int
-or
-.Em unsigned short int
-argument, or that a following
-.Cm n
-conversion corresponds to a pointer to a
-.Em short int
-argument.
-.It
-The optional character
-.Cm j ,
-specifying that a following
-.Cm d ,
-.Cm i ,
-.Cm o ,
-.Cm u ,
-.Cm x ,
-or
-.Cm X
-conversion corresponds to an
-.Em intmax_t
-or
-.Em uintmax_t
-argument, or that a following
-.Cm n
-conversion corresponds to a pointer to a
-.Em intmax_t
-argument.
-.It
-The optional character
-.Cm l
-(ell) specifying that a following
-.Cm d ,
-.Cm i ,
-.Cm o ,
-.Cm u ,
-.Cm x ,
-or
-.Cm X
-conversion corresponds to a
-.Em long int
-or
-.Em unsigned long int
-argument, or that a following
-.Cm n
-conversion corresponds to a pointer to a
-.Em long int
-argument.
-.It
-Two optional consecutive
-.Cm l
-(ell) characters,
-specifying that a following
-.Cm d ,
-.Cm i ,
-.Cm o ,
-.Cm u ,
-.Cm x ,
+An optional length modifier, that specifies the size of the argument.
+The following length modifiers are valid for the
+.Cm d , i , n , o , u , x ,
or
.Cm X
-conversion corresponds to a
-.Em long long
-or
-.Em unsigned long long
-argument, or that a following
-.Cm n
-conversion corresponds to a pointer to a
-.Em long long
-argument.
-.It
-The optional character
-.Cm q ,
-specifying that a following
-.Cm d ,
-.Cm i ,
-.Cm o ,
-.Cm u ,
-.Cm x ,
+conversion:
+.Bl -column ".Cm q Em (deprecated)" ".Vt signed char" ".Vt unsigned long long" ".Vt long long *"
+.It Sy Modifier Ta Cm d , i Ta Cm o , u , x , X Ta Cm n
+.It Cm hh Ta Vt "signed char" Ta Vt "unsigned char" Ta Vt "signed char *"
+.It Cm h Ta Vt short Ta Vt "unsigned short" Ta Vt "short *"
+.It Cm l No (ell) Ta Vt long Ta Vt "unsigned long" Ta Vt "long *"
+.It Cm ll No (ell ell) Ta Vt "long long" Ta Vt "unsigned long long" Ta Vt "long long *"
+.It Cm j Ta Vt intmax_t Ta Vt uintmax_t Ta Vt "intmax_t *"
+.It Cm t Ta Vt ptrdiff_t Ta (see note) Ta Vt "ptrdiff_t *"
+.It Cm z Ta (see note) Ta Vt size_t Ta (see note)
+.It Cm q Em (deprecated) Ta Vt quad_t Ta Vt u_quad_t Ta Vt "quad_t *"
+.El
+.Pp
+Note:
+the
+.Cm t
+modifier, when applied to a
+.Cm o , u , x ,
or
.Cm X
-conversion corresponds to a
-.Em quad_t
-or
-.Em u_quad_t
-argument, or that a following
-.Cm n
-conversion corresponds to a pointer to a
-.Em quad_t
-argument.
+conversion, indicates that the argument is of an unsigned type
+equivalent in size to a
+.Vt ptrdiff_t .
The
-.Cm q
-modifier is a BSD extension and should not be used in portable programs.
-.It
-The optional character
-.Cm t ,
-specifying that a following
-.Cm d ,
-.Cm i ,
-.Cm o ,
-.Cm u ,
-.Cm x ,
-or
-.Cm X
-conversion corresponds to a
-.Em ptrdiff_t
-or
-the corresponding unsigned integer type
-argument, or that a following
-.Cm n
-conversion corresponds to a pointer to a
-.Em ptrdiff_t
-argument.
-.It
-The optional character
-.Cm z ,
-specifying that a following
-.Cm d ,
-.Cm i ,
-.Cm o ,
-.Cm u ,
-.Cm x ,
-or
-.Cm X
-conversion corresponds to a
-.Em size_t
+.Cm z
+modifier, when applied to a
+.Cm d
or
-the corresponding signed integer type
-argument, or that a following
+.Cm i
+conversion, indicates that the argument is of a signed type equivalent in
+size to a
+.Vt size_t .
+Similarly, when applied to an
.Cm n
-conversion corresponds to a pointer to a
-signed integer type corresponding to
-.Em size_t
-argument.
-.It
-The character
-.Cm L
-specifying that a following
-.Cm e ,
-.Cm E ,
-.Cm f ,
-.Cm F ,
+conversion, it indicates that the argument is a pointer to a signed type
+equivalent in size to a
+.Vt size_t .
+.Pp
+The following length modifier is valid for the
+.Cm a ,
+.Cm A ,
+.Cm e ,
+.Cm E ,
+.Cm f ,
+.Cm F ,
.Cm g ,
or
.Cm G
-conversion corresponds to a
-.Em long double
-argument.
+conversion:
+.Bl -column ".Sy Modifier" ".Cm a , A , e , E , f , F , g , G"
+.It Sy Modifier Ta Cm a , A , e , E , f , F , g , G
+.It Cm l No (ell) Ta Vt double
+(ignored, same behavior as without it)
+.It Cm L Ta Vt "long double"
+.El
+.Pp
+The following length modifier is valid for the
+.Cm c
+or
+.Cm s
+conversion:
+.Bl -column ".Sy Modifier" ".Vt wint_t" ".Vt wchar_t *"
+.It Sy Modifier Ta Cm c Ta Cm s
+.It Cm l No (ell) Ta Vt wint_t Ta Vt "wchar_t *"
+.El
.It
A character that specifies the type of conversion to be applied.
.El
@@ -489,19 +425,25 @@ A character that specifies the type of conversion to be applied.
A field width or precision, or both, may be indicated by
an asterisk
.Ql *
-instead of a digit string.
+or an asterisk followed by one or more decimal digits and a
+.Ql $
+instead of a
+digit string.
In this case, an
-.Em int
+.Vt int
argument supplies the field width or precision.
A negative field width is treated as a left adjustment flag followed by a
positive field width; a negative precision is treated as though it were
missing.
+If a single format directive mixes positional
+.Pq Li nn$
+and non-positional arguments, the results are undefined.
.Pp
The conversion specifiers and their meanings are:
-.Bl -tag -width "diouxX"
+.Bl -tag -width ".Cm diouxX"
.It Cm diouxX
The
-.Em int
+.Vt int
(or appropriate variant) argument is converted to signed decimal
.Pf ( Cm d
and
@@ -516,11 +458,11 @@ and
.Cm X )
notation.
The letters
-.Cm abcdef
+.Dq Li abcdef
are used for
.Cm x
conversions; the letters
-.Cm ABCDEF
+.Dq Li ABCDEF
are used for
.Cm X
conversions.
@@ -529,7 +471,7 @@ appear; if the converted value requires fewer digits, it is padded on
the left with zeros.
.It Cm DOU
The
-.Em long int
+.Vt long int
argument is converted to signed decimal, unsigned octal, or unsigned
decimal, as if the format had been
.Cm ld ,
@@ -538,38 +480,12 @@ or
.Cm lu
respectively.
These conversion characters are deprecated, and will eventually disappear.
-.It Cm fF
-The
-.Em double
-argument is rounded and converted to decimal notation in the style
-.Sm off
-.Pf [-]ddd Cm \&. No ddd ,
-.Sm on
-where the number of digits after the decimal-point character
-is equal to the precision specification.
-If the precision is missing, it is taken as 6; if the precision is
-explicitly zero, no decimal-point character appears.
-If a decimal point appears, at least one digit appears before it.
-.Pp
-If the double argument represents an infinity it is converted
-in the style
-.Pf [-] Cm inf .
-If the double argument represents a NaN it is converted
-in the style
-.Pf [-] Cm nan .
-An
-.Cm F
-conversion produces
-.Pf [-] Cm INF
-and
-.Pf [-] Cm NAN ,
-respectively.
.It Cm eE
The
-.Em double
+.Vt double
argument is rounded and converted in the style
.Sm off
-.Pf [\-]d Cm \&. No ddd Cm e No \\*(Pmdd
+.Oo \- Oc Ar d Li \&. Ar ddd Li e \\*[Pm] Ar dd
.Sm on
where there is one digit before the
decimal-point character
@@ -580,22 +496,52 @@ zero, no decimal-point character appears.
An
.Cm E
conversion uses the letter
-.Cm E
+.Ql E
(rather than
-.Cm e )
+.Ql e )
to introduce the exponent.
The exponent always contains at least two digits; if the value is zero,
the exponent is 00.
.Pp
-Double arguments representing infinities or NaNs are converted in the
-same styles as in the
-.Cm f
+For
+.Cm a ,
+.Cm A ,
+.Cm e ,
+.Cm E ,
+.Cm f ,
+.Cm F ,
+.Cm g ,
and
-.Cm F
-conversions.
+.Cm G
+conversions, positive and negative infinity are represented as
+.Li inf
+and
+.Li -inf
+respectively when using the lowercase conversion character, and
+.Li INF
+and
+.Li -INF
+respectively when using the uppercase conversion character.
+Similarly, NaN is represented as
+.Li nan
+when using the lowercase conversion, and
+.Li NAN
+when using the uppercase conversion.
+.It Cm fF
+The
+.Vt double
+argument is rounded and converted to decimal notation in the style
+.Sm off
+.Oo \- Oc Ar ddd Li \&. Ar ddd ,
+.Sm on
+where the number of digits after the decimal-point character
+is equal to the precision specification.
+If the precision is missing, it is taken as 6; if the precision is
+explicitly zero, no decimal-point character appears.
+If a decimal point appears, at least one digit appears before it.
.It Cm gG
The
-.Em double
+.Vt double
argument is converted in style
.Cm f
or
@@ -612,26 +558,90 @@ If the precision is missing, 6 digits are given; if the precision is zero,
it is treated as 1.
Style
.Cm e
-is used if the exponent from its conversion is less than -4 or greater than
+is used if the exponent from its conversion is less than \-4 or greater than
or equal to the precision.
Trailing zeros are removed from the fractional part of the result; a
decimal point appears only if it is followed by at least one digit.
+.It Cm aA
+The
+.Vt double
+argument is rounded and converted to hexadecimal notation in the style
+.Sm off
+.Oo \- Oc Li 0x Ar h Li \&. Ar hhhp Oo \\*[Pm] Oc Ar d ,
+.Sm on
+where the number of digits after the hexadecimal-point character
+is equal to the precision specification.
+If the precision is missing, it is taken as enough to represent
+the floating-point number exactly, and no rounding occurs.
+If the precision is zero, no hexadecimal-point character appears.
+The
+.Cm p
+is a literal character
+.Ql p ,
+and the exponent consists of a positive or negative sign
+followed by a decimal number representing an exponent of 2.
+The
+.Cm A
+conversion uses the prefix
+.Dq Li 0X
+(rather than
+.Dq Li 0x ) ,
+the letters
+.Dq Li ABCDEF
+(rather than
+.Dq Li abcdef )
+to represent the hex digits, and the letter
+.Ql P
+(rather than
+.Ql p )
+to separate the mantissa and exponent.
.Pp
-Double arguments representing infinities or NaNs are converted in the
-same styles as in the
-.Cm f
-and
-.Cm F
-conversions.
+Note that there may be multiple valid ways to represent floating-point
+numbers in this hexadecimal format.
+For example,
+.Li 0x3.24p+0 , 0x6.48p-1
+and
+.Li 0xc.9p-2
+are all equivalent.
+The format chosen depends on the internal representation of the
+number, but the implementation guarantees that the length of the
+mantissa will be minimized.
+Zeroes are always represented with a mantissa of 0 (preceded by a
+.Ql -
+if appropriate) and an exponent of
+.Li +0 .
+.It Cm C
+Treated as
+.Cm c
+with the
+.Cm l
+(ell) modifier.
.It Cm c
The
-.Em int
+.Vt int
argument is converted to an
-.Em unsigned char ,
+.Vt "unsigned char" ,
and the resulting character is written.
+.Pp
+If the
+.Cm l
+(ell) modifier is used, the
+.Vt wint_t
+argument shall be converted to a
+.Vt wchar_t ,
+and the (potentially multi-byte) sequence representing the
+single wide character is written, including any shift sequences.
+If a shift sequence is used, the shift state is also restored
+to the original state after the character.
+.It Cm S
+Treated as
+.Cm s
+with the
+.Cm l
+(ell) modifier.
.It Cm s
The
-.Dq Em char *
+.Vt "char *"
argument is expected to be a pointer to an array of character type (pointer
to a string).
Characters from the array are written up to (but not including)
@@ -645,9 +655,34 @@ need be present; if the precision is not specified, or is greater than
the size of the array, the array must contain a terminating
.Dv NUL
character.
+.Pp
+If the
+.Cm l
+(ell) modifier is used, the
+.Vt "wchar_t *"
+argument is expected to be a pointer to an array of wide characters
+(pointer to a wide string).
+For each wide character in the string, the (potentially multi-byte)
+sequence representing the
+wide character is written, including any shift sequences.
+If any shift sequence is used, the shift state is also restored
+to the original state after the string.
+Wide characters from the array are written up to (but not including)
+a terminating wide
+.Dv NUL
+character;
+if a precision is specified, no more than the number of bytes specified are
+written (including shift sequences).
+Partial characters are never written.
+If a precision is given, no null character
+need be present; if the precision is not specified, or is greater than
+the number of bytes required to render the multibyte representation of
+the string, the array must contain a terminating wide
+.Dv NUL
+character.
.It Cm p
The
-.Dq Em void *
+.Vt "void *"
pointer argument is printed in hexadecimal (as if by
.Ql %#x
or
@@ -655,7 +690,7 @@ or
.It Cm n
The number of characters written so far is stored into the
integer indicated by the
-.Dq Em int *
+.Vt "int *"
(or variant) pointer argument.
No argument is converted.
.It Cm %
@@ -667,71 +702,22 @@ The complete conversion specification is
.Ql %% .
.El
.Pp
+The decimal point
+character is defined in the program's locale (category
+.Dv LC_NUMERIC ) .
+.Pp
In no case does a non-existent or small field width cause truncation of
-a field; if the result of a conversion is wider than the field width, the
+a numeric field; if the result of a conversion is wider than the field
+width, the
field is expanded to contain the conversion result.
-.Sh RETURN VALUES
-Upon successful completion
-.Fn printf ,
-.Fn fprintf ,
-.Fn vprintf ,
-and
-.Fn vfprintf
-return the number of characters printed.
-Otherwise a negative value is returned and
-.Dv errno
-is set to indicate the error.
-.Pp
-Upon successful completion
-.Fn sprintf
-and
-.Fn vsprintf
-return the number of characters written to
-.Fa str ,
-excluding the terminating
-.Dv NUL
-character.
-Otherwise a negative value is returned and
-.Dv errno
-is set to indicate the error.
-.Pp
-Upon successful completion
-.Fn snprintf
-and
-.Fn vsnprintf
-return the number of characters that would have been written
-to a sufficiently sized
-.Fa str ,
-excluding the terminating
-.Dv NUL
-character.
-Otherwise a negative value is returned and
-.Dv errno
-is set to indicate the error.
-.Pp
-Upon successful completion
-.Fn asprintf
-and
-.Fn vasprintf
-return the number of characters written to
-.Fa ret ,
-excluding the terminating
-.Dv NUL
-character.
-Otherwise \-1 is returned,
-.Fa ret
-is set to
-.Dv NULL ,
-and
-.Dv errno
-is set to indicate the error.
.Sh EXAMPLES
.br
-To print a date and time in the form `Sunday, July 3, 10:02',
+To print a date and time in the form
+.Dq Li "Sunday, July 3, 10:02" ,
where
-.Em weekday
+.Fa weekday
and
-.Em month
+.Fa month
are pointers to strings:
.Bd -literal -offset indent
#include \*[Lt]stdio.h\*[Gt]
@@ -764,12 +750,100 @@ char *newfmt(const char *fmt, ...)
return (p);
}
.Ed
+.Sh SECURITY CONSIDERATIONS
+The
+.Fn sprintf
+and
+.Fn vsprintf
+functions are easily misused in a manner which enables malicious users
+to arbitrarily change a running program's functionality through
+a buffer overflow attack.
+Because
+.Fn sprintf
+and
+.Fn vsprintf
+assume an infinitely long string,
+callers must be careful not to overflow the actual space;
+this is often hard to assure.
+For safety, programmers should use the
+.Fn snprintf
+interface instead.
+For example:
+.Bd -literal
+void
+foo(const char *arbitrary_string, const char *and_another)
+{
+ char onstack[8];
+
+#ifdef BAD
+ /*
+ * This first sprintf is bad behavior. Do not use sprintf!
+ */
+ sprintf(onstack, "%s, %s", arbitrary_string, and_another);
+#else
+ /*
+ * The following two lines demonstrate better use of
+ * snprintf().
+ */
+ snprintf(onstack, sizeof(onstack), "%s, %s", arbitrary_string,
+ and_another);
+#endif
+}
+.Ed
+.Pp
+The
+.Fn printf
+and
+.Fn sprintf
+family of functions are also easily misused in a manner
+allowing malicious users to arbitrarily change a running program's
+functionality by either causing the program
+to print potentially sensitive data
+.Dq "left on the stack" ,
+or causing it to generate a memory fault or bus error
+by dereferencing an invalid pointer.
+.Pp
+.Cm %n
+can be used to write arbitrary data to potentially carefully-selected
+addresses.
+Programmers are therefore strongly advised to never pass untrusted strings
+as the
+.Fa format
+argument, as an attacker can put format specifiers in the string
+to mangle your stack,
+leading to a possible security hole.
+This holds true even if the string was built using a function like
+.Fn snprintf ,
+as the resulting string may still contain user-supplied conversion specifiers
+for later interpolation by
+.Fn printf .
+.Pp
+Always use the proper secure idiom:
+.Pp
+.Dl "snprintf(buffer, sizeof(buffer), \*q%s\*q, string);"
+.Sh ERRORS
+In addition to the errors documented for the
+.Xr write 2
+system call, the
+.Fn printf
+family of functions may fail if:
+.Bl -tag -width Er
+.It Bq Er EILSEQ
+An invalid wide character code was encountered.
+.It Bq Er ENOMEM
+Insufficient storage space is available.
+.El
.Sh SEE ALSO
.Xr printf 1 ,
+.Xr fmtcheck 3 ,
+.Xr printf 9 ,
.Xr scanf 3 ,
-.Xr printf 9
+.Xr setlocale 3 ,
+.Xr wprintf 3
.Sh STANDARDS
-The
+Subject to the caveats noted in the
+.Sx BUGS
+section below, the
.Fn fprintf ,
.Fn printf ,
.Fn sprintf ,
@@ -779,20 +853,14 @@ and
.Fn vsprintf
functions
conform to
-.St -isoC-90 .
-The conversion format modifiers
-.Cm %j ,
-.Cm %t
+.St -ansiC
and
-.Cm %z
-conform to
.St -isoC-99 .
-The
+With the same reservation, the
.Fn snprintf
and
.Fn vsnprintf
-functions
-conform to
+functions conform to
.St -isoC-99 .
.Sh HISTORY
The functions
@@ -880,3 +948,9 @@ and
conversions, as well as other nonsensical combinations such as
.Cm %Ld ,
are not standard; such combinations should be avoided.
+.Pp
+The
+.Nm
+family of functions do not correctly handle multibyte characters in the
+.Fa format
+argument.