diff options
| author | christos <christos@NetBSD.org> | 2007-06-09 18:51:19 +0000 |
|---|---|---|
| committer | christos <christos@NetBSD.org> | 2007-06-09 18:51:19 +0000 |
| commit | a9df04f00d8bf7d742f6ec93fb60ae6511baa67f (patch) | |
| tree | 213089b0572fb623165e3792e7aa537baf6ea38e /lib/libc/stdio/printf.3 | |
| parent | 1b15aa2347ffb615f5f0570c2f4493bf3747be53 (diff) | |
bring in many changes from FreeBSD
Diffstat (limited to 'lib/libc/stdio/printf.3')
| -rw-r--r-- | lib/libc/stdio/printf.3 | 668 |
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. |
