1998-09-04 16:34:23 +02:00
|
|
|
/*
|
|
|
|
* Copyright (c) 1983, 1995, 1996 Eric P. Allman
|
|
|
|
* Copyright (c) 1988, 1993
|
1998-08-01 21:30:29 +02:00
|
|
|
* The Regents of the University of California. All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
1998-10-07 19:12:52 +02:00
|
|
|
* notice, this list of conditions and the following disclaimer.
|
1998-08-01 21:30:29 +02:00
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
1998-10-07 19:12:52 +02:00
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
2007-03-26 23:44:11 +02:00
|
|
|
* 3. Neither the name of the University nor the names of its contributors
|
1998-10-07 19:12:52 +02:00
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
1998-08-01 21:30:29 +02:00
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
2014-05-06 18:12:18 +02:00
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
1998-08-01 21:30:29 +02:00
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
2005-12-05 03:39:38 +01:00
|
|
|
*
|
2010-09-20 22:08:53 +02:00
|
|
|
* src/port/snprintf.c
|
1998-08-01 21:30:29 +02:00
|
|
|
*/
|
1998-09-10 06:11:52 +02:00
|
|
|
|
2005-07-28 06:03:14 +02:00
|
|
|
#include "c.h"
|
2001-02-10 03:31:31 +01:00
|
|
|
|
2015-02-02 16:00:45 +01:00
|
|
|
#include <ctype.h>
|
2015-02-04 13:27:31 +01:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
#include <float.h> /* for _isnan */
|
|
|
|
#endif
|
2005-12-05 03:39:38 +01:00
|
|
|
#include <limits.h>
|
2015-02-02 16:00:45 +01:00
|
|
|
#include <math.h>
|
2005-02-28 15:16:16 +01:00
|
|
|
#ifndef WIN32
|
1998-10-07 19:12:52 +02:00
|
|
|
#include <sys/ioctl.h>
|
2005-02-28 15:16:16 +01:00
|
|
|
#endif
|
1998-10-07 19:12:52 +02:00
|
|
|
#include <sys/param.h>
|
1998-09-01 06:40:42 +02:00
|
|
|
|
2005-12-05 03:39:38 +01:00
|
|
|
#ifndef NL_ARGMAX
|
|
|
|
#define NL_ARGMAX 16
|
|
|
|
#endif
|
|
|
|
|
2005-03-20 04:53:39 +01:00
|
|
|
|
1998-09-04 16:34:23 +02:00
|
|
|
/*
|
2005-12-05 03:39:38 +01:00
|
|
|
* SNPRINTF, VSNPRINTF and friends
|
|
|
|
*
|
|
|
|
* These versions have been grabbed off the net. They have been
|
2005-12-05 22:57:00 +01:00
|
|
|
* cleaned up to compile properly and support for most of the Single Unix
|
|
|
|
* Specification has been added. Remaining unimplemented features are:
|
2005-12-05 03:39:38 +01:00
|
|
|
*
|
|
|
|
* 1. No locale support: the radix character is always '.' and the '
|
|
|
|
* (single quote) format flag is ignored.
|
|
|
|
*
|
|
|
|
* 2. No support for the "%n" format specification.
|
|
|
|
*
|
|
|
|
* 3. No support for wide characters ("lc" and "ls" formats).
|
|
|
|
*
|
|
|
|
* 4. No support for "long double" ("Lf" and related formats).
|
|
|
|
*
|
|
|
|
* 5. Space and '#' flags are not implemented.
|
2005-12-05 22:57:00 +01:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* The result values of these functions are not the same across different
|
|
|
|
* platforms. This implementation is compatible with the Single Unix Spec:
|
|
|
|
*
|
|
|
|
* 1. -1 is returned only if processing is abandoned due to an invalid
|
2014-05-06 18:12:18 +02:00
|
|
|
* parameter, such as incorrect format string. (Although not required by
|
2005-12-05 22:57:00 +01:00
|
|
|
* the spec, this happens only when no characters have yet been transmitted
|
|
|
|
* to the destination.)
|
|
|
|
*
|
|
|
|
* 2. For snprintf and sprintf, 0 is returned if str == NULL or count == 0;
|
|
|
|
* no data has been stored.
|
|
|
|
*
|
|
|
|
* 3. Otherwise, the number of bytes actually transmitted to the destination
|
|
|
|
* is returned (excluding the trailing '\0' for snprintf and sprintf).
|
|
|
|
*
|
|
|
|
* For snprintf with nonzero count, the result cannot be more than count-1
|
|
|
|
* (a trailing '\0' is always stored); it is not possible to distinguish
|
|
|
|
* buffer overrun from exact fit. This is unlike some implementations that
|
|
|
|
* return the number of bytes that would have been needed for the complete
|
|
|
|
* result string.
|
2005-12-05 03:39:38 +01:00
|
|
|
*/
|
1998-09-01 06:40:42 +02:00
|
|
|
|
1998-09-04 16:34:23 +02:00
|
|
|
/**************************************************************
|
|
|
|
* Original:
|
|
|
|
* Patrick Powell Tue Apr 11 09:48:21 PDT 1995
|
|
|
|
* A bombproof version of doprnt (dopr) included.
|
2014-05-06 18:12:18 +02:00
|
|
|
* Sigh. This sort of thing is always nasty do deal with. Note that
|
1999-02-06 22:51:03 +01:00
|
|
|
* the version here does not include floating point. (now it does ... tgl)
|
1998-09-04 16:34:23 +02:00
|
|
|
**************************************************************/
|
1998-08-01 21:30:29 +02:00
|
|
|
|
2005-03-11 20:13:43 +01:00
|
|
|
/* Prevent recursion */
|
|
|
|
#undef vsnprintf
|
|
|
|
#undef snprintf
|
2005-03-16 22:27:23 +01:00
|
|
|
#undef sprintf
|
2006-11-28 02:12:34 +01:00
|
|
|
#undef vfprintf
|
2005-03-11 20:13:43 +01:00
|
|
|
#undef fprintf
|
|
|
|
#undef printf
|
|
|
|
|
2005-12-05 03:39:38 +01:00
|
|
|
/* Info about where the formatted output is going */
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
char *bufptr; /* next buffer output position */
|
|
|
|
char *bufstart; /* first buffer element */
|
|
|
|
char *bufend; /* last buffer element, or NULL */
|
|
|
|
/* bufend == NULL is for sprintf, where we assume buf is big enough */
|
|
|
|
FILE *stream; /* eventual output destination, or NULL */
|
|
|
|
int nchars; /* # chars already sent to stream */
|
Add error-throwing wrappers for the printf family of functions.
All known standard library implementations of these functions can fail
with ENOMEM. A caller neglecting to check for failure would experience
missing output, information exposure, or a crash. Check return values
within wrappers and code, currently just snprintf.c, that bypasses the
wrappers. The wrappers do not return after an error, so their callers
need not check. Back-patch to 9.0 (all supported versions).
Popular free software standard library implementations do take pains to
bypass malloc() in simple cases, but they risk ENOMEM for floating point
numbers, positional arguments, large field widths, and large precisions.
No specification demands such caution, so this commit regards every call
to a printf family function as a potential threat.
Injecting the wrappers implicitly is a compromise between patch scope
and design goals. I would prefer to edit each call site to name a
wrapper explicitly. libpq and the ECPG libraries would, ideally, convey
errors to the caller rather than abort(). All that would be painfully
invasive for a back-patched security fix, hence this compromise.
Security: CVE-2015-3166
2015-05-18 16:02:31 +02:00
|
|
|
bool failed; /* call is a failure; errno is set */
|
2011-04-10 17:42:00 +02:00
|
|
|
} PrintfTarget;
|
2005-12-05 03:39:38 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Info about the type and value of a formatting parameter. Note that we
|
|
|
|
* don't currently support "long double", "wint_t", or "wchar_t *" data,
|
|
|
|
* nor the '%n' formatting code; else we'd need more types. Also, at this
|
|
|
|
* level we need not worry about signed vs unsigned values.
|
|
|
|
*/
|
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
ATYPE_NONE = 0,
|
|
|
|
ATYPE_INT,
|
|
|
|
ATYPE_LONG,
|
|
|
|
ATYPE_LONGLONG,
|
|
|
|
ATYPE_DOUBLE,
|
|
|
|
ATYPE_CHARPTR
|
2011-04-10 17:42:00 +02:00
|
|
|
} PrintfArgType;
|
2005-12-05 03:39:38 +01:00
|
|
|
|
|
|
|
typedef union
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
long l;
|
|
|
|
int64 ll;
|
|
|
|
double d;
|
|
|
|
char *cptr;
|
2011-04-10 17:42:00 +02:00
|
|
|
} PrintfArgValue;
|
2005-12-05 03:39:38 +01:00
|
|
|
|
|
|
|
|
2011-04-10 17:42:00 +02:00
|
|
|
static void flushbuffer(PrintfTarget *target);
|
Add error-throwing wrappers for the printf family of functions.
All known standard library implementations of these functions can fail
with ENOMEM. A caller neglecting to check for failure would experience
missing output, information exposure, or a crash. Check return values
within wrappers and code, currently just snprintf.c, that bypasses the
wrappers. The wrappers do not return after an error, so their callers
need not check. Back-patch to 9.0 (all supported versions).
Popular free software standard library implementations do take pains to
bypass malloc() in simple cases, but they risk ENOMEM for floating point
numbers, positional arguments, large field widths, and large precisions.
No specification demands such caution, so this commit regards every call
to a printf family function as a potential threat.
Injecting the wrappers implicitly is a compromise between patch scope
and design goals. I would prefer to edit each call site to name a
wrapper explicitly. libpq and the ECPG libraries would, ideally, convey
errors to the caller rather than abort(). All that would be painfully
invasive for a back-patched security fix, hence this compromise.
Security: CVE-2015-3166
2015-05-18 16:02:31 +02:00
|
|
|
static void dopr(PrintfTarget *target, const char *format, va_list args);
|
2005-12-05 03:39:38 +01:00
|
|
|
|
|
|
|
|
2005-02-22 04:56:22 +01:00
|
|
|
int
|
2005-03-11 18:20:35 +01:00
|
|
|
pg_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
|
2005-02-22 04:56:22 +01:00
|
|
|
{
|
2006-10-04 02:30:14 +02:00
|
|
|
PrintfTarget target;
|
2005-12-05 03:39:38 +01:00
|
|
|
|
|
|
|
if (str == NULL || count == 0)
|
|
|
|
return 0;
|
|
|
|
target.bufstart = target.bufptr = str;
|
|
|
|
target.bufend = str + count - 1;
|
|
|
|
target.stream = NULL;
|
|
|
|
/* target.nchars is unused in this case */
|
Add error-throwing wrappers for the printf family of functions.
All known standard library implementations of these functions can fail
with ENOMEM. A caller neglecting to check for failure would experience
missing output, information exposure, or a crash. Check return values
within wrappers and code, currently just snprintf.c, that bypasses the
wrappers. The wrappers do not return after an error, so their callers
need not check. Back-patch to 9.0 (all supported versions).
Popular free software standard library implementations do take pains to
bypass malloc() in simple cases, but they risk ENOMEM for floating point
numbers, positional arguments, large field widths, and large precisions.
No specification demands such caution, so this commit regards every call
to a printf family function as a potential threat.
Injecting the wrappers implicitly is a compromise between patch scope
and design goals. I would prefer to edit each call site to name a
wrapper explicitly. libpq and the ECPG libraries would, ideally, convey
errors to the caller rather than abort(). All that would be painfully
invasive for a back-patched security fix, hence this compromise.
Security: CVE-2015-3166
2015-05-18 16:02:31 +02:00
|
|
|
target.failed = false;
|
|
|
|
dopr(&target, fmt, args);
|
2005-12-05 03:39:38 +01:00
|
|
|
*(target.bufptr) = '\0';
|
Add error-throwing wrappers for the printf family of functions.
All known standard library implementations of these functions can fail
with ENOMEM. A caller neglecting to check for failure would experience
missing output, information exposure, or a crash. Check return values
within wrappers and code, currently just snprintf.c, that bypasses the
wrappers. The wrappers do not return after an error, so their callers
need not check. Back-patch to 9.0 (all supported versions).
Popular free software standard library implementations do take pains to
bypass malloc() in simple cases, but they risk ENOMEM for floating point
numbers, positional arguments, large field widths, and large precisions.
No specification demands such caution, so this commit regards every call
to a printf family function as a potential threat.
Injecting the wrappers implicitly is a compromise between patch scope
and design goals. I would prefer to edit each call site to name a
wrapper explicitly. libpq and the ECPG libraries would, ideally, convey
errors to the caller rather than abort(). All that would be painfully
invasive for a back-patched security fix, hence this compromise.
Security: CVE-2015-3166
2015-05-18 16:02:31 +02:00
|
|
|
return target.failed ? -1 : (target.bufptr - target.bufstart);
|
2005-02-22 04:56:22 +01:00
|
|
|
}
|
|
|
|
|
1998-08-01 21:30:29 +02:00
|
|
|
int
|
2005-03-11 18:20:35 +01:00
|
|
|
pg_snprintf(char *str, size_t count, const char *fmt,...)
|
1998-09-04 16:34:23 +02:00
|
|
|
{
|
1998-10-07 19:12:52 +02:00
|
|
|
int len;
|
1999-05-25 18:15:34 +02:00
|
|
|
va_list args;
|
1998-10-07 19:12:52 +02:00
|
|
|
|
1998-12-18 08:03:06 +01:00
|
|
|
va_start(args, fmt);
|
2005-03-11 18:20:35 +01:00
|
|
|
len = pg_vsnprintf(str, count, fmt, args);
|
1998-12-18 08:03:06 +01:00
|
|
|
va_end(args);
|
1998-09-04 16:34:23 +02:00
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
Revert error-throwing wrappers for the printf family of functions.
This reverts commit 16304a013432931e61e623c8d85e9fe24709d9ba, except
for its changes in src/port/snprintf.c; as well as commit
cac18a76bb6b08f1ecc2a85e46c9d2ab82dd9d23 which is no longer needed.
Fujii Masao reported that the previous commit caused failures in psql on
OS X, since if one exits the pager program early while viewing a query
result, psql sees an EPIPE error from fprintf --- and the wrapper function
thought that was reason to panic. (It's a bit surprising that the same
does not happen on Linux.) Further discussion among the security list
concluded that the risk of other such failures was far too great, and
that the one-size-fits-all approach to error handling embodied in the
previous patch is unlikely to be workable.
This leaves us again exposed to the possibility of the type of failure
envisioned in CVE-2015-3166. However, that failure mode is strictly
hypothetical at this point: there is no concrete reason to believe that
an attacker could trigger information disclosure through the supposed
mechanism. In the first place, the attack surface is fairly limited,
since so much of what the backend does with format strings goes through
stringinfo.c or psprintf(), and those already had adequate defenses.
In the second place, even granting that an unprivileged attacker could
control the occurrence of ENOMEM with some precision, it's a stretch to
believe that he could induce it just where the target buffer contains some
valuable information. So we concluded that the risk of non-hypothetical
problems induced by the patch greatly outweighs the security risks.
We will therefore revert, and instead undertake closer analysis to
identify specific calls that may need hardening, rather than attempt a
universal solution.
We have kept the portion of the previous patch that improved snprintf.c's
handling of errors when it calls the platform's sprintf(). That seems to
be an unalloyed improvement.
Security: CVE-2015-3166
2015-05-20 00:14:52 +02:00
|
|
|
static int
|
2005-12-05 03:39:38 +01:00
|
|
|
pg_vsprintf(char *str, const char *fmt, va_list args)
|
|
|
|
{
|
2006-10-04 02:30:14 +02:00
|
|
|
PrintfTarget target;
|
2005-12-05 03:39:38 +01:00
|
|
|
|
|
|
|
if (str == NULL)
|
|
|
|
return 0;
|
|
|
|
target.bufstart = target.bufptr = str;
|
|
|
|
target.bufend = NULL;
|
|
|
|
target.stream = NULL;
|
|
|
|
/* target.nchars is unused in this case */
|
Add error-throwing wrappers for the printf family of functions.
All known standard library implementations of these functions can fail
with ENOMEM. A caller neglecting to check for failure would experience
missing output, information exposure, or a crash. Check return values
within wrappers and code, currently just snprintf.c, that bypasses the
wrappers. The wrappers do not return after an error, so their callers
need not check. Back-patch to 9.0 (all supported versions).
Popular free software standard library implementations do take pains to
bypass malloc() in simple cases, but they risk ENOMEM for floating point
numbers, positional arguments, large field widths, and large precisions.
No specification demands such caution, so this commit regards every call
to a printf family function as a potential threat.
Injecting the wrappers implicitly is a compromise between patch scope
and design goals. I would prefer to edit each call site to name a
wrapper explicitly. libpq and the ECPG libraries would, ideally, convey
errors to the caller rather than abort(). All that would be painfully
invasive for a back-patched security fix, hence this compromise.
Security: CVE-2015-3166
2015-05-18 16:02:31 +02:00
|
|
|
target.failed = false;
|
|
|
|
dopr(&target, fmt, args);
|
2005-12-05 03:39:38 +01:00
|
|
|
*(target.bufptr) = '\0';
|
Add error-throwing wrappers for the printf family of functions.
All known standard library implementations of these functions can fail
with ENOMEM. A caller neglecting to check for failure would experience
missing output, information exposure, or a crash. Check return values
within wrappers and code, currently just snprintf.c, that bypasses the
wrappers. The wrappers do not return after an error, so their callers
need not check. Back-patch to 9.0 (all supported versions).
Popular free software standard library implementations do take pains to
bypass malloc() in simple cases, but they risk ENOMEM for floating point
numbers, positional arguments, large field widths, and large precisions.
No specification demands such caution, so this commit regards every call
to a printf family function as a potential threat.
Injecting the wrappers implicitly is a compromise between patch scope
and design goals. I would prefer to edit each call site to name a
wrapper explicitly. libpq and the ECPG libraries would, ideally, convey
errors to the caller rather than abort(). All that would be painfully
invasive for a back-patched security fix, hence this compromise.
Security: CVE-2015-3166
2015-05-18 16:02:31 +02:00
|
|
|
return target.failed ? -1 : (target.bufptr - target.bufstart);
|
2005-12-05 03:39:38 +01:00
|
|
|
}
|
|
|
|
|
2005-03-16 22:27:23 +01:00
|
|
|
int
|
|
|
|
pg_sprintf(char *str, const char *fmt,...)
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
va_list args;
|
|
|
|
|
|
|
|
va_start(args, fmt);
|
2005-12-05 03:39:38 +01:00
|
|
|
len = pg_vsprintf(str, fmt, args);
|
2005-03-16 22:27:23 +01:00
|
|
|
va_end(args);
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
2006-11-28 02:12:34 +01:00
|
|
|
int
|
2005-12-05 03:39:38 +01:00
|
|
|
pg_vfprintf(FILE *stream, const char *fmt, va_list args)
|
|
|
|
{
|
2006-10-04 02:30:14 +02:00
|
|
|
PrintfTarget target;
|
2005-12-05 03:39:38 +01:00
|
|
|
char buffer[1024]; /* size is arbitrary */
|
|
|
|
|
|
|
|
if (stream == NULL)
|
|
|
|
{
|
|
|
|
errno = EINVAL;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
target.bufstart = target.bufptr = buffer;
|
|
|
|
target.bufend = buffer + sizeof(buffer) - 1;
|
|
|
|
target.stream = stream;
|
|
|
|
target.nchars = 0;
|
Add error-throwing wrappers for the printf family of functions.
All known standard library implementations of these functions can fail
with ENOMEM. A caller neglecting to check for failure would experience
missing output, information exposure, or a crash. Check return values
within wrappers and code, currently just snprintf.c, that bypasses the
wrappers. The wrappers do not return after an error, so their callers
need not check. Back-patch to 9.0 (all supported versions).
Popular free software standard library implementations do take pains to
bypass malloc() in simple cases, but they risk ENOMEM for floating point
numbers, positional arguments, large field widths, and large precisions.
No specification demands such caution, so this commit regards every call
to a printf family function as a potential threat.
Injecting the wrappers implicitly is a compromise between patch scope
and design goals. I would prefer to edit each call site to name a
wrapper explicitly. libpq and the ECPG libraries would, ideally, convey
errors to the caller rather than abort(). All that would be painfully
invasive for a back-patched security fix, hence this compromise.
Security: CVE-2015-3166
2015-05-18 16:02:31 +02:00
|
|
|
target.failed = false;
|
|
|
|
dopr(&target, fmt, args);
|
2005-12-05 03:39:38 +01:00
|
|
|
/* dump any remaining buffer contents */
|
|
|
|
flushbuffer(&target);
|
Add error-throwing wrappers for the printf family of functions.
All known standard library implementations of these functions can fail
with ENOMEM. A caller neglecting to check for failure would experience
missing output, information exposure, or a crash. Check return values
within wrappers and code, currently just snprintf.c, that bypasses the
wrappers. The wrappers do not return after an error, so their callers
need not check. Back-patch to 9.0 (all supported versions).
Popular free software standard library implementations do take pains to
bypass malloc() in simple cases, but they risk ENOMEM for floating point
numbers, positional arguments, large field widths, and large precisions.
No specification demands such caution, so this commit regards every call
to a printf family function as a potential threat.
Injecting the wrappers implicitly is a compromise between patch scope
and design goals. I would prefer to edit each call site to name a
wrapper explicitly. libpq and the ECPG libraries would, ideally, convey
errors to the caller rather than abort(). All that would be painfully
invasive for a back-patched security fix, hence this compromise.
Security: CVE-2015-3166
2015-05-18 16:02:31 +02:00
|
|
|
return target.failed ? -1 : target.nchars;
|
2005-12-05 03:39:38 +01:00
|
|
|
}
|
|
|
|
|
2005-03-11 20:13:43 +01:00
|
|
|
int
|
|
|
|
pg_fprintf(FILE *stream, const char *fmt,...)
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
va_list args;
|
|
|
|
|
|
|
|
va_start(args, fmt);
|
2005-12-05 03:39:38 +01:00
|
|
|
len = pg_vfprintf(stream, fmt, args);
|
2005-03-11 20:13:43 +01:00
|
|
|
va_end(args);
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
1998-08-01 21:30:29 +02:00
|
|
|
int
|
2005-03-11 18:20:35 +01:00
|
|
|
pg_printf(const char *fmt,...)
|
1998-09-04 16:34:23 +02:00
|
|
|
{
|
2005-03-02 04:21:52 +01:00
|
|
|
int len;
|
2005-03-11 20:13:43 +01:00
|
|
|
va_list args;
|
2005-03-02 04:21:52 +01:00
|
|
|
|
|
|
|
va_start(args, fmt);
|
2005-12-05 03:39:38 +01:00
|
|
|
len = pg_vfprintf(stdout, fmt, args);
|
2005-03-02 04:21:52 +01:00
|
|
|
va_end(args);
|
|
|
|
return len;
|
1998-09-04 16:34:23 +02:00
|
|
|
}
|
1998-09-01 06:40:42 +02:00
|
|
|
|
Add error-throwing wrappers for the printf family of functions.
All known standard library implementations of these functions can fail
with ENOMEM. A caller neglecting to check for failure would experience
missing output, information exposure, or a crash. Check return values
within wrappers and code, currently just snprintf.c, that bypasses the
wrappers. The wrappers do not return after an error, so their callers
need not check. Back-patch to 9.0 (all supported versions).
Popular free software standard library implementations do take pains to
bypass malloc() in simple cases, but they risk ENOMEM for floating point
numbers, positional arguments, large field widths, and large precisions.
No specification demands such caution, so this commit regards every call
to a printf family function as a potential threat.
Injecting the wrappers implicitly is a compromise between patch scope
and design goals. I would prefer to edit each call site to name a
wrapper explicitly. libpq and the ECPG libraries would, ideally, convey
errors to the caller rather than abort(). All that would be painfully
invasive for a back-patched security fix, hence this compromise.
Security: CVE-2015-3166
2015-05-18 16:02:31 +02:00
|
|
|
/*
|
|
|
|
* Attempt to write the entire buffer to target->stream; discard the entire
|
|
|
|
* buffer in any case. Call this only when target->stream is defined.
|
|
|
|
*/
|
2005-12-05 03:39:38 +01:00
|
|
|
static void
|
2011-04-10 17:42:00 +02:00
|
|
|
flushbuffer(PrintfTarget *target)
|
2005-12-05 03:39:38 +01:00
|
|
|
{
|
2006-10-04 02:30:14 +02:00
|
|
|
size_t nc = target->bufptr - target->bufstart;
|
2005-12-05 03:39:38 +01:00
|
|
|
|
Add error-throwing wrappers for the printf family of functions.
All known standard library implementations of these functions can fail
with ENOMEM. A caller neglecting to check for failure would experience
missing output, information exposure, or a crash. Check return values
within wrappers and code, currently just snprintf.c, that bypasses the
wrappers. The wrappers do not return after an error, so their callers
need not check. Back-patch to 9.0 (all supported versions).
Popular free software standard library implementations do take pains to
bypass malloc() in simple cases, but they risk ENOMEM for floating point
numbers, positional arguments, large field widths, and large precisions.
No specification demands such caution, so this commit regards every call
to a printf family function as a potential threat.
Injecting the wrappers implicitly is a compromise between patch scope
and design goals. I would prefer to edit each call site to name a
wrapper explicitly. libpq and the ECPG libraries would, ideally, convey
errors to the caller rather than abort(). All that would be painfully
invasive for a back-patched security fix, hence this compromise.
Security: CVE-2015-3166
2015-05-18 16:02:31 +02:00
|
|
|
if (!target->failed && nc > 0)
|
|
|
|
{
|
|
|
|
size_t written;
|
|
|
|
|
|
|
|
written = fwrite(target->bufstart, 1, nc, target->stream);
|
|
|
|
target->nchars += written;
|
|
|
|
if (written != nc)
|
|
|
|
target->failed = true;
|
|
|
|
}
|
2005-12-05 03:39:38 +01:00
|
|
|
target->bufptr = target->bufstart;
|
|
|
|
}
|
|
|
|
|
1998-09-04 16:34:23 +02:00
|
|
|
|
2005-03-17 04:18:14 +01:00
|
|
|
static void fmtstr(char *value, int leftjust, int minlen, int maxwidth,
|
2011-04-10 17:42:00 +02:00
|
|
|
int pointflag, PrintfTarget *target);
|
|
|
|
static void fmtptr(void *value, PrintfTarget *target);
|
2005-12-05 03:39:38 +01:00
|
|
|
static void fmtint(int64 value, char type, int forcesign,
|
|
|
|
int leftjust, int minlen, int zpad, int precision, int pointflag,
|
2011-04-10 17:42:00 +02:00
|
|
|
PrintfTarget *target);
|
|
|
|
static void fmtchar(int value, int leftjust, int minlen, PrintfTarget *target);
|
2005-03-16 22:27:23 +01:00
|
|
|
static void fmtfloat(double value, char type, int forcesign,
|
2006-10-04 02:30:14 +02:00
|
|
|
int leftjust, int minlen, int zpad, int precision, int pointflag,
|
2011-04-10 17:42:00 +02:00
|
|
|
PrintfTarget *target);
|
|
|
|
static void dostr(const char *str, int slen, PrintfTarget *target);
|
|
|
|
static void dopr_outch(int c, PrintfTarget *target);
|
2005-12-05 03:39:38 +01:00
|
|
|
static int adjust_sign(int is_negative, int forcesign, int *signvalue);
|
|
|
|
static void adjust_padlen(int minlen, int vallen, int leftjust, int *padlen);
|
|
|
|
static void leading_pad(int zpad, int *signvalue, int *padlen,
|
2011-04-10 17:42:00 +02:00
|
|
|
PrintfTarget *target);
|
|
|
|
static void trailing_pad(int *padlen, PrintfTarget *target);
|
2005-12-05 03:39:38 +01:00
|
|
|
|
1998-09-04 16:34:23 +02:00
|
|
|
|
2005-03-17 04:18:14 +01:00
|
|
|
/*
|
|
|
|
* dopr(): poor man's version of doprintf
|
|
|
|
*/
|
Add error-throwing wrappers for the printf family of functions.
All known standard library implementations of these functions can fail
with ENOMEM. A caller neglecting to check for failure would experience
missing output, information exposure, or a crash. Check return values
within wrappers and code, currently just snprintf.c, that bypasses the
wrappers. The wrappers do not return after an error, so their callers
need not check. Back-patch to 9.0 (all supported versions).
Popular free software standard library implementations do take pains to
bypass malloc() in simple cases, but they risk ENOMEM for floating point
numbers, positional arguments, large field widths, and large precisions.
No specification demands such caution, so this commit regards every call
to a printf family function as a potential threat.
Injecting the wrappers implicitly is a compromise between patch scope
and design goals. I would prefer to edit each call site to name a
wrapper explicitly. libpq and the ECPG libraries would, ideally, convey
errors to the caller rather than abort(). All that would be painfully
invasive for a back-patched security fix, hence this compromise.
Security: CVE-2015-3166
2015-05-18 16:02:31 +02:00
|
|
|
static void
|
2011-04-10 17:42:00 +02:00
|
|
|
dopr(PrintfTarget *target, const char *format, va_list args)
|
1998-08-01 21:30:29 +02:00
|
|
|
{
|
2005-12-05 03:39:38 +01:00
|
|
|
const char *format_start = format;
|
1998-10-07 19:12:52 +02:00
|
|
|
int ch;
|
2005-12-05 03:39:38 +01:00
|
|
|
bool have_dollar;
|
|
|
|
bool have_non_dollar;
|
|
|
|
bool have_star;
|
|
|
|
bool afterstar;
|
|
|
|
int accum;
|
2005-03-16 22:27:23 +01:00
|
|
|
int longlongflag;
|
|
|
|
int longflag;
|
|
|
|
int pointflag;
|
2005-03-17 04:18:14 +01:00
|
|
|
int leftjust;
|
2005-12-05 03:39:38 +01:00
|
|
|
int fieldwidth;
|
|
|
|
int precision;
|
1998-10-07 19:12:52 +02:00
|
|
|
int zpad;
|
2005-03-16 22:27:23 +01:00
|
|
|
int forcesign;
|
2005-12-05 03:39:38 +01:00
|
|
|
int last_dollar;
|
|
|
|
int fmtpos;
|
|
|
|
int cvalue;
|
|
|
|
int64 numvalue;
|
|
|
|
double fvalue;
|
|
|
|
char *strvalue;
|
2005-02-22 04:56:22 +01:00
|
|
|
int i;
|
2006-10-04 02:30:14 +02:00
|
|
|
PrintfArgType argtypes[NL_ARGMAX + 1];
|
|
|
|
PrintfArgValue argvalues[NL_ARGMAX + 1];
|
1998-10-07 19:12:52 +02:00
|
|
|
|
2005-04-14 22:53:09 +02:00
|
|
|
/*
|
2005-12-05 03:39:38 +01:00
|
|
|
* Parse the format string to determine whether there are %n$ format
|
|
|
|
* specs, and identify the types and order of the format parameters.
|
2005-04-14 22:53:09 +02:00
|
|
|
*/
|
2005-12-05 03:39:38 +01:00
|
|
|
have_dollar = have_non_dollar = false;
|
|
|
|
last_dollar = 0;
|
|
|
|
MemSet(argtypes, 0, sizeof(argtypes));
|
2005-03-20 04:53:39 +01:00
|
|
|
|
2005-12-05 03:39:38 +01:00
|
|
|
while ((ch = *format++) != '\0')
|
2005-03-02 06:22:22 +01:00
|
|
|
{
|
2005-12-05 03:39:38 +01:00
|
|
|
if (ch != '%')
|
|
|
|
continue;
|
|
|
|
longflag = longlongflag = pointflag = 0;
|
|
|
|
fmtpos = accum = 0;
|
|
|
|
afterstar = false;
|
2006-10-04 02:30:14 +02:00
|
|
|
nextch1:
|
2005-12-05 03:39:38 +01:00
|
|
|
ch = *format++;
|
|
|
|
if (ch == '\0')
|
|
|
|
break; /* illegal, but we don't complain */
|
|
|
|
switch (ch)
|
|
|
|
{
|
|
|
|
case '-':
|
|
|
|
case '+':
|
|
|
|
goto nextch1;
|
|
|
|
case '0':
|
|
|
|
case '1':
|
|
|
|
case '2':
|
|
|
|
case '3':
|
|
|
|
case '4':
|
|
|
|
case '5':
|
|
|
|
case '6':
|
|
|
|
case '7':
|
|
|
|
case '8':
|
|
|
|
case '9':
|
|
|
|
accum = accum * 10 + (ch - '0');
|
|
|
|
goto nextch1;
|
|
|
|
case '.':
|
|
|
|
pointflag = 1;
|
|
|
|
accum = 0;
|
|
|
|
goto nextch1;
|
|
|
|
case '*':
|
|
|
|
if (afterstar)
|
2006-10-04 02:30:14 +02:00
|
|
|
have_non_dollar = true; /* multiple stars */
|
2005-12-05 03:39:38 +01:00
|
|
|
afterstar = true;
|
|
|
|
accum = 0;
|
|
|
|
goto nextch1;
|
|
|
|
case '$':
|
|
|
|
have_dollar = true;
|
|
|
|
if (accum <= 0 || accum > NL_ARGMAX)
|
Add error-throwing wrappers for the printf family of functions.
All known standard library implementations of these functions can fail
with ENOMEM. A caller neglecting to check for failure would experience
missing output, information exposure, or a crash. Check return values
within wrappers and code, currently just snprintf.c, that bypasses the
wrappers. The wrappers do not return after an error, so their callers
need not check. Back-patch to 9.0 (all supported versions).
Popular free software standard library implementations do take pains to
bypass malloc() in simple cases, but they risk ENOMEM for floating point
numbers, positional arguments, large field widths, and large precisions.
No specification demands such caution, so this commit regards every call
to a printf family function as a potential threat.
Injecting the wrappers implicitly is a compromise between patch scope
and design goals. I would prefer to edit each call site to name a
wrapper explicitly. libpq and the ECPG libraries would, ideally, convey
errors to the caller rather than abort(). All that would be painfully
invasive for a back-patched security fix, hence this compromise.
Security: CVE-2015-3166
2015-05-18 16:02:31 +02:00
|
|
|
goto bad_format;
|
2005-12-05 03:39:38 +01:00
|
|
|
if (afterstar)
|
|
|
|
{
|
|
|
|
if (argtypes[accum] &&
|
|
|
|
argtypes[accum] != ATYPE_INT)
|
Add error-throwing wrappers for the printf family of functions.
All known standard library implementations of these functions can fail
with ENOMEM. A caller neglecting to check for failure would experience
missing output, information exposure, or a crash. Check return values
within wrappers and code, currently just snprintf.c, that bypasses the
wrappers. The wrappers do not return after an error, so their callers
need not check. Back-patch to 9.0 (all supported versions).
Popular free software standard library implementations do take pains to
bypass malloc() in simple cases, but they risk ENOMEM for floating point
numbers, positional arguments, large field widths, and large precisions.
No specification demands such caution, so this commit regards every call
to a printf family function as a potential threat.
Injecting the wrappers implicitly is a compromise between patch scope
and design goals. I would prefer to edit each call site to name a
wrapper explicitly. libpq and the ECPG libraries would, ideally, convey
errors to the caller rather than abort(). All that would be painfully
invasive for a back-patched security fix, hence this compromise.
Security: CVE-2015-3166
2015-05-18 16:02:31 +02:00
|
|
|
goto bad_format;
|
2005-12-05 03:39:38 +01:00
|
|
|
argtypes[accum] = ATYPE_INT;
|
|
|
|
last_dollar = Max(last_dollar, accum);
|
|
|
|
afterstar = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
fmtpos = accum;
|
|
|
|
accum = 0;
|
|
|
|
goto nextch1;
|
|
|
|
case 'l':
|
|
|
|
if (longflag)
|
|
|
|
longlongflag = 1;
|
|
|
|
else
|
|
|
|
longflag = 1;
|
|
|
|
goto nextch1;
|
2014-01-23 23:18:23 +01:00
|
|
|
case 'z':
|
|
|
|
#if SIZEOF_SIZE_T == 8
|
|
|
|
#ifdef HAVE_LONG_INT_64
|
|
|
|
longflag = 1;
|
|
|
|
#elif defined(HAVE_LONG_LONG_INT_64)
|
|
|
|
longlongflag = 1;
|
|
|
|
#else
|
|
|
|
#error "Don't know how to print 64bit integers"
|
|
|
|
#endif
|
|
|
|
#else
|
|
|
|
/* assume size_t is same size as int */
|
|
|
|
#endif
|
|
|
|
goto nextch1;
|
2005-12-05 03:39:38 +01:00
|
|
|
case 'h':
|
|
|
|
case '\'':
|
|
|
|
/* ignore these */
|
|
|
|
goto nextch1;
|
|
|
|
case 'd':
|
|
|
|
case 'i':
|
|
|
|
case 'o':
|
|
|
|
case 'u':
|
|
|
|
case 'x':
|
|
|
|
case 'X':
|
|
|
|
if (fmtpos)
|
|
|
|
{
|
|
|
|
PrintfArgType atype;
|
|
|
|
|
|
|
|
if (longlongflag)
|
|
|
|
atype = ATYPE_LONGLONG;
|
|
|
|
else if (longflag)
|
|
|
|
atype = ATYPE_LONG;
|
|
|
|
else
|
|
|
|
atype = ATYPE_INT;
|
|
|
|
if (argtypes[fmtpos] &&
|
|
|
|
argtypes[fmtpos] != atype)
|
Add error-throwing wrappers for the printf family of functions.
All known standard library implementations of these functions can fail
with ENOMEM. A caller neglecting to check for failure would experience
missing output, information exposure, or a crash. Check return values
within wrappers and code, currently just snprintf.c, that bypasses the
wrappers. The wrappers do not return after an error, so their callers
need not check. Back-patch to 9.0 (all supported versions).
Popular free software standard library implementations do take pains to
bypass malloc() in simple cases, but they risk ENOMEM for floating point
numbers, positional arguments, large field widths, and large precisions.
No specification demands such caution, so this commit regards every call
to a printf family function as a potential threat.
Injecting the wrappers implicitly is a compromise between patch scope
and design goals. I would prefer to edit each call site to name a
wrapper explicitly. libpq and the ECPG libraries would, ideally, convey
errors to the caller rather than abort(). All that would be painfully
invasive for a back-patched security fix, hence this compromise.
Security: CVE-2015-3166
2015-05-18 16:02:31 +02:00
|
|
|
goto bad_format;
|
2005-12-05 03:39:38 +01:00
|
|
|
argtypes[fmtpos] = atype;
|
|
|
|
last_dollar = Max(last_dollar, fmtpos);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
have_non_dollar = true;
|
|
|
|
break;
|
|
|
|
case 'c':
|
|
|
|
if (fmtpos)
|
|
|
|
{
|
|
|
|
if (argtypes[fmtpos] &&
|
|
|
|
argtypes[fmtpos] != ATYPE_INT)
|
Add error-throwing wrappers for the printf family of functions.
All known standard library implementations of these functions can fail
with ENOMEM. A caller neglecting to check for failure would experience
missing output, information exposure, or a crash. Check return values
within wrappers and code, currently just snprintf.c, that bypasses the
wrappers. The wrappers do not return after an error, so their callers
need not check. Back-patch to 9.0 (all supported versions).
Popular free software standard library implementations do take pains to
bypass malloc() in simple cases, but they risk ENOMEM for floating point
numbers, positional arguments, large field widths, and large precisions.
No specification demands such caution, so this commit regards every call
to a printf family function as a potential threat.
Injecting the wrappers implicitly is a compromise between patch scope
and design goals. I would prefer to edit each call site to name a
wrapper explicitly. libpq and the ECPG libraries would, ideally, convey
errors to the caller rather than abort(). All that would be painfully
invasive for a back-patched security fix, hence this compromise.
Security: CVE-2015-3166
2015-05-18 16:02:31 +02:00
|
|
|
goto bad_format;
|
2005-12-05 03:39:38 +01:00
|
|
|
argtypes[fmtpos] = ATYPE_INT;
|
|
|
|
last_dollar = Max(last_dollar, fmtpos);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
have_non_dollar = true;
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
case 'p':
|
|
|
|
if (fmtpos)
|
|
|
|
{
|
|
|
|
if (argtypes[fmtpos] &&
|
|
|
|
argtypes[fmtpos] != ATYPE_CHARPTR)
|
Add error-throwing wrappers for the printf family of functions.
All known standard library implementations of these functions can fail
with ENOMEM. A caller neglecting to check for failure would experience
missing output, information exposure, or a crash. Check return values
within wrappers and code, currently just snprintf.c, that bypasses the
wrappers. The wrappers do not return after an error, so their callers
need not check. Back-patch to 9.0 (all supported versions).
Popular free software standard library implementations do take pains to
bypass malloc() in simple cases, but they risk ENOMEM for floating point
numbers, positional arguments, large field widths, and large precisions.
No specification demands such caution, so this commit regards every call
to a printf family function as a potential threat.
Injecting the wrappers implicitly is a compromise between patch scope
and design goals. I would prefer to edit each call site to name a
wrapper explicitly. libpq and the ECPG libraries would, ideally, convey
errors to the caller rather than abort(). All that would be painfully
invasive for a back-patched security fix, hence this compromise.
Security: CVE-2015-3166
2015-05-18 16:02:31 +02:00
|
|
|
goto bad_format;
|
2005-12-05 03:39:38 +01:00
|
|
|
argtypes[fmtpos] = ATYPE_CHARPTR;
|
|
|
|
last_dollar = Max(last_dollar, fmtpos);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
have_non_dollar = true;
|
|
|
|
break;
|
|
|
|
case 'e':
|
|
|
|
case 'E':
|
|
|
|
case 'f':
|
|
|
|
case 'g':
|
|
|
|
case 'G':
|
|
|
|
if (fmtpos)
|
|
|
|
{
|
|
|
|
if (argtypes[fmtpos] &&
|
|
|
|
argtypes[fmtpos] != ATYPE_DOUBLE)
|
Add error-throwing wrappers for the printf family of functions.
All known standard library implementations of these functions can fail
with ENOMEM. A caller neglecting to check for failure would experience
missing output, information exposure, or a crash. Check return values
within wrappers and code, currently just snprintf.c, that bypasses the
wrappers. The wrappers do not return after an error, so their callers
need not check. Back-patch to 9.0 (all supported versions).
Popular free software standard library implementations do take pains to
bypass malloc() in simple cases, but they risk ENOMEM for floating point
numbers, positional arguments, large field widths, and large precisions.
No specification demands such caution, so this commit regards every call
to a printf family function as a potential threat.
Injecting the wrappers implicitly is a compromise between patch scope
and design goals. I would prefer to edit each call site to name a
wrapper explicitly. libpq and the ECPG libraries would, ideally, convey
errors to the caller rather than abort(). All that would be painfully
invasive for a back-patched security fix, hence this compromise.
Security: CVE-2015-3166
2015-05-18 16:02:31 +02:00
|
|
|
goto bad_format;
|
2005-12-05 03:39:38 +01:00
|
|
|
argtypes[fmtpos] = ATYPE_DOUBLE;
|
|
|
|
last_dollar = Max(last_dollar, fmtpos);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
have_non_dollar = true;
|
|
|
|
break;
|
|
|
|
case '%':
|
|
|
|
break;
|
|
|
|
}
|
2006-10-04 02:30:14 +02:00
|
|
|
|
2005-12-05 03:39:38 +01:00
|
|
|
/*
|
|
|
|
* If we finish the spec with afterstar still set, there's a
|
|
|
|
* non-dollar star in there.
|
|
|
|
*/
|
|
|
|
if (afterstar)
|
|
|
|
have_non_dollar = true;
|
2005-03-02 06:22:22 +01:00
|
|
|
}
|
2005-12-05 03:39:38 +01:00
|
|
|
|
|
|
|
/* Per spec, you use either all dollar or all not. */
|
|
|
|
if (have_dollar && have_non_dollar)
|
Add error-throwing wrappers for the printf family of functions.
All known standard library implementations of these functions can fail
with ENOMEM. A caller neglecting to check for failure would experience
missing output, information exposure, or a crash. Check return values
within wrappers and code, currently just snprintf.c, that bypasses the
wrappers. The wrappers do not return after an error, so their callers
need not check. Back-patch to 9.0 (all supported versions).
Popular free software standard library implementations do take pains to
bypass malloc() in simple cases, but they risk ENOMEM for floating point
numbers, positional arguments, large field widths, and large precisions.
No specification demands such caution, so this commit regards every call
to a printf family function as a potential threat.
Injecting the wrappers implicitly is a compromise between patch scope
and design goals. I would prefer to edit each call site to name a
wrapper explicitly. libpq and the ECPG libraries would, ideally, convey
errors to the caller rather than abort(). All that would be painfully
invasive for a back-patched security fix, hence this compromise.
Security: CVE-2015-3166
2015-05-18 16:02:31 +02:00
|
|
|
goto bad_format;
|
2005-12-05 03:39:38 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* In dollar mode, collect the arguments in physical order.
|
|
|
|
*/
|
|
|
|
for (i = 1; i <= last_dollar; i++)
|
2005-03-02 06:22:22 +01:00
|
|
|
{
|
2005-12-05 03:39:38 +01:00
|
|
|
switch (argtypes[i])
|
|
|
|
{
|
|
|
|
case ATYPE_NONE:
|
Add error-throwing wrappers for the printf family of functions.
All known standard library implementations of these functions can fail
with ENOMEM. A caller neglecting to check for failure would experience
missing output, information exposure, or a crash. Check return values
within wrappers and code, currently just snprintf.c, that bypasses the
wrappers. The wrappers do not return after an error, so their callers
need not check. Back-patch to 9.0 (all supported versions).
Popular free software standard library implementations do take pains to
bypass malloc() in simple cases, but they risk ENOMEM for floating point
numbers, positional arguments, large field widths, and large precisions.
No specification demands such caution, so this commit regards every call
to a printf family function as a potential threat.
Injecting the wrappers implicitly is a compromise between patch scope
and design goals. I would prefer to edit each call site to name a
wrapper explicitly. libpq and the ECPG libraries would, ideally, convey
errors to the caller rather than abort(). All that would be painfully
invasive for a back-patched security fix, hence this compromise.
Security: CVE-2015-3166
2015-05-18 16:02:31 +02:00
|
|
|
goto bad_format;
|
2005-12-05 03:39:38 +01:00
|
|
|
case ATYPE_INT:
|
|
|
|
argvalues[i].i = va_arg(args, int);
|
|
|
|
break;
|
|
|
|
case ATYPE_LONG:
|
|
|
|
argvalues[i].l = va_arg(args, long);
|
|
|
|
break;
|
|
|
|
case ATYPE_LONGLONG:
|
|
|
|
argvalues[i].ll = va_arg(args, int64);
|
|
|
|
break;
|
|
|
|
case ATYPE_DOUBLE:
|
|
|
|
argvalues[i].d = va_arg(args, double);
|
|
|
|
break;
|
|
|
|
case ATYPE_CHARPTR:
|
|
|
|
argvalues[i].cptr = va_arg(args, char *);
|
|
|
|
break;
|
|
|
|
}
|
2005-03-02 06:22:22 +01:00
|
|
|
}
|
2005-03-16 16:12:18 +01:00
|
|
|
|
2005-12-05 03:39:38 +01:00
|
|
|
/*
|
|
|
|
* At last we can parse the format for real.
|
|
|
|
*/
|
|
|
|
format = format_start;
|
|
|
|
while ((ch = *format++) != '\0')
|
1998-10-07 19:12:52 +02:00
|
|
|
{
|
Add error-throwing wrappers for the printf family of functions.
All known standard library implementations of these functions can fail
with ENOMEM. A caller neglecting to check for failure would experience
missing output, information exposure, or a crash. Check return values
within wrappers and code, currently just snprintf.c, that bypasses the
wrappers. The wrappers do not return after an error, so their callers
need not check. Back-patch to 9.0 (all supported versions).
Popular free software standard library implementations do take pains to
bypass malloc() in simple cases, but they risk ENOMEM for floating point
numbers, positional arguments, large field widths, and large precisions.
No specification demands such caution, so this commit regards every call
to a printf family function as a potential threat.
Injecting the wrappers implicitly is a compromise between patch scope
and design goals. I would prefer to edit each call site to name a
wrapper explicitly. libpq and the ECPG libraries would, ideally, convey
errors to the caller rather than abort(). All that would be painfully
invasive for a back-patched security fix, hence this compromise.
Security: CVE-2015-3166
2015-05-18 16:02:31 +02:00
|
|
|
if (target->failed)
|
|
|
|
break;
|
|
|
|
|
2005-12-05 03:39:38 +01:00
|
|
|
if (ch != '%')
|
|
|
|
{
|
|
|
|
dopr_outch(ch, target);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
fieldwidth = precision = zpad = leftjust = forcesign = 0;
|
|
|
|
longflag = longlongflag = pointflag = 0;
|
|
|
|
fmtpos = accum = 0;
|
|
|
|
have_star = afterstar = false;
|
2006-10-04 02:30:14 +02:00
|
|
|
nextch2:
|
2005-12-05 03:39:38 +01:00
|
|
|
ch = *format++;
|
|
|
|
if (ch == '\0')
|
|
|
|
break; /* illegal, but we don't complain */
|
1998-10-07 19:12:52 +02:00
|
|
|
switch (ch)
|
|
|
|
{
|
2005-12-05 03:39:38 +01:00
|
|
|
case '-':
|
|
|
|
leftjust = 1;
|
|
|
|
goto nextch2;
|
|
|
|
case '+':
|
|
|
|
forcesign = 1;
|
|
|
|
goto nextch2;
|
|
|
|
case '0':
|
|
|
|
/* set zero padding if no nonzero digits yet */
|
|
|
|
if (accum == 0 && !pointflag)
|
|
|
|
zpad = '0';
|
|
|
|
/* FALL THRU */
|
|
|
|
case '1':
|
|
|
|
case '2':
|
|
|
|
case '3':
|
|
|
|
case '4':
|
|
|
|
case '5':
|
|
|
|
case '6':
|
|
|
|
case '7':
|
|
|
|
case '8':
|
|
|
|
case '9':
|
|
|
|
accum = accum * 10 + (ch - '0');
|
|
|
|
goto nextch2;
|
|
|
|
case '.':
|
|
|
|
if (have_star)
|
|
|
|
have_star = false;
|
|
|
|
else
|
|
|
|
fieldwidth = accum;
|
|
|
|
pointflag = 1;
|
|
|
|
accum = 0;
|
|
|
|
goto nextch2;
|
|
|
|
case '*':
|
|
|
|
if (have_dollar)
|
1998-10-07 19:12:52 +02:00
|
|
|
{
|
2005-12-05 03:39:38 +01:00
|
|
|
/* process value after reading n$ */
|
|
|
|
afterstar = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* fetch and process value now */
|
2006-10-04 02:30:14 +02:00
|
|
|
int starval = va_arg(args, int);
|
2005-12-05 03:39:38 +01:00
|
|
|
|
|
|
|
if (pointflag)
|
|
|
|
{
|
|
|
|
precision = starval;
|
|
|
|
if (precision < 0)
|
2008-03-18 02:49:44 +01:00
|
|
|
{
|
2005-12-05 03:39:38 +01:00
|
|
|
precision = 0;
|
2008-03-18 02:49:44 +01:00
|
|
|
pointflag = 0;
|
|
|
|
}
|
2005-12-05 03:39:38 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fieldwidth = starval;
|
|
|
|
if (fieldwidth < 0)
|
2005-03-16 07:00:58 +01:00
|
|
|
{
|
2005-12-05 03:39:38 +01:00
|
|
|
leftjust = 1;
|
|
|
|
fieldwidth = -fieldwidth;
|
2005-03-16 07:00:58 +01:00
|
|
|
}
|
2005-12-05 03:39:38 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
have_star = true;
|
|
|
|
accum = 0;
|
|
|
|
goto nextch2;
|
|
|
|
case '$':
|
|
|
|
if (afterstar)
|
|
|
|
{
|
|
|
|
/* fetch and process star value */
|
2006-10-04 02:30:14 +02:00
|
|
|
int starval = argvalues[accum].i;
|
2005-12-05 03:39:38 +01:00
|
|
|
|
|
|
|
if (pointflag)
|
|
|
|
{
|
|
|
|
precision = starval;
|
|
|
|
if (precision < 0)
|
2008-03-18 02:49:44 +01:00
|
|
|
{
|
2005-12-05 03:39:38 +01:00
|
|
|
precision = 0;
|
2008-03-18 02:49:44 +01:00
|
|
|
pointflag = 0;
|
|
|
|
}
|
2005-12-05 03:39:38 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fieldwidth = starval;
|
|
|
|
if (fieldwidth < 0)
|
2005-03-02 15:48:22 +01:00
|
|
|
{
|
2005-12-05 03:39:38 +01:00
|
|
|
leftjust = 1;
|
|
|
|
fieldwidth = -fieldwidth;
|
2005-03-02 16:07:09 +01:00
|
|
|
}
|
2005-12-05 03:39:38 +01:00
|
|
|
}
|
|
|
|
afterstar = false;
|
1998-10-07 19:12:52 +02:00
|
|
|
}
|
2005-12-05 03:39:38 +01:00
|
|
|
else
|
|
|
|
fmtpos = accum;
|
|
|
|
accum = 0;
|
|
|
|
goto nextch2;
|
|
|
|
case 'l':
|
|
|
|
if (longflag)
|
|
|
|
longlongflag = 1;
|
|
|
|
else
|
|
|
|
longflag = 1;
|
|
|
|
goto nextch2;
|
2014-01-23 23:18:23 +01:00
|
|
|
case 'z':
|
|
|
|
#if SIZEOF_SIZE_T == 8
|
|
|
|
#ifdef HAVE_LONG_INT_64
|
|
|
|
longflag = 1;
|
|
|
|
#elif defined(HAVE_LONG_LONG_INT_64)
|
|
|
|
longlongflag = 1;
|
|
|
|
#else
|
|
|
|
#error "Don't know how to print 64bit integers"
|
|
|
|
#endif
|
|
|
|
#else
|
|
|
|
/* assume size_t is same size as int */
|
|
|
|
#endif
|
|
|
|
goto nextch2;
|
2005-12-05 03:39:38 +01:00
|
|
|
case 'h':
|
|
|
|
case '\'':
|
|
|
|
/* ignore these */
|
|
|
|
goto nextch2;
|
|
|
|
case 'd':
|
|
|
|
case 'i':
|
|
|
|
if (!have_star)
|
|
|
|
{
|
|
|
|
if (pointflag)
|
|
|
|
precision = accum;
|
|
|
|
else
|
|
|
|
fieldwidth = accum;
|
|
|
|
}
|
|
|
|
if (have_dollar)
|
|
|
|
{
|
|
|
|
if (longlongflag)
|
|
|
|
numvalue = argvalues[fmtpos].ll;
|
|
|
|
else if (longflag)
|
|
|
|
numvalue = argvalues[fmtpos].l;
|
|
|
|
else
|
|
|
|
numvalue = argvalues[fmtpos].i;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (longlongflag)
|
|
|
|
numvalue = va_arg(args, int64);
|
|
|
|
else if (longflag)
|
|
|
|
numvalue = va_arg(args, long);
|
|
|
|
else
|
|
|
|
numvalue = va_arg(args, int);
|
|
|
|
}
|
|
|
|
fmtint(numvalue, ch, forcesign, leftjust, fieldwidth, zpad,
|
|
|
|
precision, pointflag, target);
|
1998-10-07 19:12:52 +02:00
|
|
|
break;
|
2005-12-05 03:39:38 +01:00
|
|
|
case 'o':
|
|
|
|
case 'u':
|
|
|
|
case 'x':
|
|
|
|
case 'X':
|
|
|
|
if (!have_star)
|
|
|
|
{
|
|
|
|
if (pointflag)
|
|
|
|
precision = accum;
|
|
|
|
else
|
|
|
|
fieldwidth = accum;
|
|
|
|
}
|
|
|
|
if (have_dollar)
|
2005-03-16 16:12:18 +01:00
|
|
|
{
|
2005-12-05 03:39:38 +01:00
|
|
|
if (longlongflag)
|
|
|
|
numvalue = (uint64) argvalues[fmtpos].ll;
|
|
|
|
else if (longflag)
|
|
|
|
numvalue = (unsigned long) argvalues[fmtpos].l;
|
2005-03-16 16:12:18 +01:00
|
|
|
else
|
2005-12-05 03:39:38 +01:00
|
|
|
numvalue = (unsigned int) argvalues[fmtpos].i;
|
2005-03-16 16:12:18 +01:00
|
|
|
}
|
2005-03-16 07:00:58 +01:00
|
|
|
else
|
2005-12-05 03:39:38 +01:00
|
|
|
{
|
|
|
|
if (longlongflag)
|
|
|
|
numvalue = (uint64) va_arg(args, int64);
|
|
|
|
else if (longflag)
|
|
|
|
numvalue = (unsigned long) va_arg(args, long);
|
|
|
|
else
|
|
|
|
numvalue = (unsigned int) va_arg(args, int);
|
|
|
|
}
|
|
|
|
fmtint(numvalue, ch, forcesign, leftjust, fieldwidth, zpad,
|
|
|
|
precision, pointflag, target);
|
2005-03-16 16:12:18 +01:00
|
|
|
break;
|
2005-12-05 03:39:38 +01:00
|
|
|
case 'c':
|
|
|
|
if (!have_star)
|
2005-03-16 16:12:18 +01:00
|
|
|
{
|
2005-12-05 03:39:38 +01:00
|
|
|
if (pointflag)
|
|
|
|
precision = accum;
|
2005-03-16 16:12:18 +01:00
|
|
|
else
|
2005-12-05 03:39:38 +01:00
|
|
|
fieldwidth = accum;
|
2005-03-16 16:12:18 +01:00
|
|
|
}
|
2005-12-05 03:39:38 +01:00
|
|
|
if (have_dollar)
|
|
|
|
cvalue = (unsigned char) argvalues[fmtpos].i;
|
2005-03-16 07:00:58 +01:00
|
|
|
else
|
2005-12-05 03:39:38 +01:00
|
|
|
cvalue = (unsigned char) va_arg(args, int);
|
|
|
|
fmtchar(cvalue, leftjust, fieldwidth, target);
|
2005-03-16 16:12:18 +01:00
|
|
|
break;
|
2005-12-05 03:39:38 +01:00
|
|
|
case 's':
|
|
|
|
if (!have_star)
|
|
|
|
{
|
|
|
|
if (pointflag)
|
|
|
|
precision = accum;
|
|
|
|
else
|
|
|
|
fieldwidth = accum;
|
|
|
|
}
|
|
|
|
if (have_dollar)
|
|
|
|
strvalue = argvalues[fmtpos].cptr;
|
|
|
|
else
|
|
|
|
strvalue = va_arg(args, char *);
|
|
|
|
fmtstr(strvalue, leftjust, fieldwidth, precision, pointflag,
|
|
|
|
target);
|
2005-03-16 16:12:18 +01:00
|
|
|
break;
|
2005-12-05 03:39:38 +01:00
|
|
|
case 'p':
|
|
|
|
/* fieldwidth/leftjust are ignored ... */
|
|
|
|
if (have_dollar)
|
|
|
|
strvalue = argvalues[fmtpos].cptr;
|
|
|
|
else
|
|
|
|
strvalue = va_arg(args, char *);
|
|
|
|
fmtptr((void *) strvalue, target);
|
2005-03-16 16:12:18 +01:00
|
|
|
break;
|
2005-12-05 03:39:38 +01:00
|
|
|
case 'e':
|
|
|
|
case 'E':
|
|
|
|
case 'f':
|
|
|
|
case 'g':
|
|
|
|
case 'G':
|
|
|
|
if (!have_star)
|
2005-03-17 04:18:14 +01:00
|
|
|
{
|
2005-12-05 03:39:38 +01:00
|
|
|
if (pointflag)
|
|
|
|
precision = accum;
|
|
|
|
else
|
|
|
|
fieldwidth = accum;
|
2005-03-17 04:18:14 +01:00
|
|
|
}
|
2005-12-05 03:39:38 +01:00
|
|
|
if (have_dollar)
|
|
|
|
fvalue = argvalues[fmtpos].d;
|
|
|
|
else
|
|
|
|
fvalue = va_arg(args, double);
|
|
|
|
fmtfloat(fvalue, ch, forcesign, leftjust,
|
|
|
|
fieldwidth, zpad,
|
|
|
|
precision, pointflag,
|
|
|
|
target);
|
2005-03-16 16:12:18 +01:00
|
|
|
break;
|
2005-12-05 03:39:38 +01:00
|
|
|
case '%':
|
|
|
|
dopr_outch('%', target);
|
2005-03-16 16:12:18 +01:00
|
|
|
break;
|
2005-03-16 07:00:58 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Add error-throwing wrappers for the printf family of functions.
All known standard library implementations of these functions can fail
with ENOMEM. A caller neglecting to check for failure would experience
missing output, information exposure, or a crash. Check return values
within wrappers and code, currently just snprintf.c, that bypasses the
wrappers. The wrappers do not return after an error, so their callers
need not check. Back-patch to 9.0 (all supported versions).
Popular free software standard library implementations do take pains to
bypass malloc() in simple cases, but they risk ENOMEM for floating point
numbers, positional arguments, large field widths, and large precisions.
No specification demands such caution, so this commit regards every call
to a printf family function as a potential threat.
Injecting the wrappers implicitly is a compromise between patch scope
and design goals. I would prefer to edit each call site to name a
wrapper explicitly. libpq and the ECPG libraries would, ideally, convey
errors to the caller rather than abort(). All that would be painfully
invasive for a back-patched security fix, hence this compromise.
Security: CVE-2015-3166
2015-05-18 16:02:31 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
bad_format:
|
|
|
|
errno = EINVAL;
|
|
|
|
target->failed = true;
|
2005-12-05 03:39:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static size_t
|
|
|
|
pg_strnlen(const char *str, size_t maxlen)
|
|
|
|
{
|
|
|
|
const char *p = str;
|
2005-03-02 06:22:22 +01:00
|
|
|
|
2005-12-05 03:39:38 +01:00
|
|
|
while (maxlen-- > 0 && *p)
|
|
|
|
p++;
|
|
|
|
return p - str;
|
1998-09-04 16:34:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2005-12-05 03:39:38 +01:00
|
|
|
fmtstr(char *value, int leftjust, int minlen, int maxwidth,
|
2011-04-10 17:42:00 +02:00
|
|
|
int pointflag, PrintfTarget *target)
|
1998-09-04 16:34:23 +02:00
|
|
|
{
|
1998-10-07 19:12:52 +02:00
|
|
|
int padlen,
|
2005-03-16 22:27:23 +01:00
|
|
|
vallen; /* amount to pad */
|
1998-09-04 16:34:23 +02:00
|
|
|
|
2005-12-05 03:39:38 +01:00
|
|
|
/*
|
|
|
|
* If a maxwidth (precision) is specified, we must not fetch more bytes
|
|
|
|
* than that.
|
|
|
|
*/
|
|
|
|
if (pointflag)
|
|
|
|
vallen = pg_strnlen(value, maxwidth);
|
|
|
|
else
|
|
|
|
vallen = strlen(value);
|
2005-03-17 04:18:14 +01:00
|
|
|
|
|
|
|
adjust_padlen(minlen, vallen, leftjust, &padlen);
|
|
|
|
|
1998-10-07 19:12:52 +02:00
|
|
|
while (padlen > 0)
|
|
|
|
{
|
2005-12-05 03:39:38 +01:00
|
|
|
dopr_outch(' ', target);
|
1998-10-07 19:12:52 +02:00
|
|
|
--padlen;
|
|
|
|
}
|
2005-03-17 04:18:14 +01:00
|
|
|
|
2005-12-05 03:39:38 +01:00
|
|
|
dostr(value, vallen, target);
|
|
|
|
|
|
|
|
trailing_pad(&padlen, target);
|
1998-09-04 16:34:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2011-04-10 17:42:00 +02:00
|
|
|
fmtptr(void *value, PrintfTarget *target)
|
1998-09-04 16:34:23 +02:00
|
|
|
{
|
2005-12-05 03:39:38 +01:00
|
|
|
int vallen;
|
|
|
|
char convert[64];
|
|
|
|
|
|
|
|
/* we rely on regular C library's sprintf to do the basic conversion */
|
|
|
|
vallen = sprintf(convert, "%p", value);
|
Add error-throwing wrappers for the printf family of functions.
All known standard library implementations of these functions can fail
with ENOMEM. A caller neglecting to check for failure would experience
missing output, information exposure, or a crash. Check return values
within wrappers and code, currently just snprintf.c, that bypasses the
wrappers. The wrappers do not return after an error, so their callers
need not check. Back-patch to 9.0 (all supported versions).
Popular free software standard library implementations do take pains to
bypass malloc() in simple cases, but they risk ENOMEM for floating point
numbers, positional arguments, large field widths, and large precisions.
No specification demands such caution, so this commit regards every call
to a printf family function as a potential threat.
Injecting the wrappers implicitly is a compromise between patch scope
and design goals. I would prefer to edit each call site to name a
wrapper explicitly. libpq and the ECPG libraries would, ideally, convey
errors to the caller rather than abort(). All that would be painfully
invasive for a back-patched security fix, hence this compromise.
Security: CVE-2015-3166
2015-05-18 16:02:31 +02:00
|
|
|
if (vallen < 0)
|
|
|
|
target->failed = true;
|
|
|
|
else
|
|
|
|
dostr(convert, vallen, target);
|
2005-12-05 03:39:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
fmtint(int64 value, char type, int forcesign, int leftjust,
|
|
|
|
int minlen, int zpad, int precision, int pointflag,
|
2011-04-10 17:42:00 +02:00
|
|
|
PrintfTarget *target)
|
2005-12-05 03:39:38 +01:00
|
|
|
{
|
|
|
|
uint64 base;
|
|
|
|
int dosign;
|
|
|
|
const char *cvt = "0123456789abcdef";
|
1998-10-07 19:12:52 +02:00
|
|
|
int signvalue = 0;
|
1999-02-06 22:51:03 +01:00
|
|
|
char convert[64];
|
2005-03-17 04:18:14 +01:00
|
|
|
int vallen = 0;
|
1998-10-07 19:12:52 +02:00
|
|
|
int padlen = 0; /* amount to pad */
|
2005-12-05 03:39:38 +01:00
|
|
|
int zeropad; /* extra leading zeroes */
|
1998-10-07 19:12:52 +02:00
|
|
|
|
2005-12-05 03:39:38 +01:00
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case 'd':
|
|
|
|
case 'i':
|
|
|
|
base = 10;
|
|
|
|
dosign = 1;
|
|
|
|
break;
|
|
|
|
case 'o':
|
|
|
|
base = 8;
|
|
|
|
dosign = 0;
|
|
|
|
break;
|
|
|
|
case 'u':
|
|
|
|
base = 10;
|
|
|
|
dosign = 0;
|
|
|
|
break;
|
|
|
|
case 'x':
|
|
|
|
base = 16;
|
|
|
|
dosign = 0;
|
|
|
|
break;
|
|
|
|
case 'X':
|
|
|
|
cvt = "0123456789ABCDEF";
|
|
|
|
base = 16;
|
|
|
|
dosign = 0;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return; /* keep compiler quiet */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Handle +/- */
|
2005-03-17 04:18:14 +01:00
|
|
|
if (dosign && adjust_sign((value < 0), forcesign, &signvalue))
|
2005-10-15 04:49:52 +02:00
|
|
|
value = -value;
|
2005-12-05 03:39:38 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* SUS: the result of converting 0 with an explicit precision of 0 is no
|
|
|
|
* characters
|
|
|
|
*/
|
|
|
|
if (value == 0 && pointflag && precision == 0)
|
|
|
|
vallen = 0;
|
|
|
|
else
|
1998-10-07 19:12:52 +02:00
|
|
|
{
|
2005-12-05 03:39:38 +01:00
|
|
|
/* make integer string */
|
2006-10-04 02:30:14 +02:00
|
|
|
uint64 uvalue = (uint64) value;
|
2005-12-05 03:39:38 +01:00
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
convert[vallen++] = cvt[uvalue % base];
|
|
|
|
uvalue = uvalue / base;
|
|
|
|
} while (uvalue);
|
1998-10-07 19:12:52 +02:00
|
|
|
}
|
2005-03-17 04:18:14 +01:00
|
|
|
|
2005-12-05 03:39:38 +01:00
|
|
|
zeropad = Max(0, precision - vallen);
|
1999-02-06 22:51:03 +01:00
|
|
|
|
2005-12-05 03:39:38 +01:00
|
|
|
adjust_padlen(minlen, vallen + zeropad, leftjust, &padlen);
|
|
|
|
|
|
|
|
leading_pad(zpad, &signvalue, &padlen, target);
|
2005-03-17 04:18:14 +01:00
|
|
|
|
2005-12-05 03:39:38 +01:00
|
|
|
while (zeropad-- > 0)
|
|
|
|
dopr_outch('0', target);
|
2005-10-15 04:49:52 +02:00
|
|
|
|
2005-03-17 04:18:14 +01:00
|
|
|
while (vallen > 0)
|
2005-12-05 03:39:38 +01:00
|
|
|
dopr_outch(convert[--vallen], target);
|
2005-03-17 04:18:14 +01:00
|
|
|
|
2005-12-05 03:39:38 +01:00
|
|
|
trailing_pad(&padlen, target);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2011-04-10 17:42:00 +02:00
|
|
|
fmtchar(int value, int leftjust, int minlen, PrintfTarget *target)
|
2005-12-05 03:39:38 +01:00
|
|
|
{
|
|
|
|
int padlen = 0; /* amount to pad */
|
|
|
|
|
|
|
|
adjust_padlen(minlen, 1, leftjust, &padlen);
|
|
|
|
|
|
|
|
while (padlen > 0)
|
|
|
|
{
|
|
|
|
dopr_outch(' ', target);
|
|
|
|
--padlen;
|
|
|
|
}
|
|
|
|
|
|
|
|
dopr_outch(value, target);
|
|
|
|
|
|
|
|
trailing_pad(&padlen, target);
|
1998-09-04 16:34:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2005-03-17 04:18:14 +01:00
|
|
|
fmtfloat(double value, char type, int forcesign, int leftjust,
|
2005-12-05 03:39:38 +01:00
|
|
|
int minlen, int zpad, int precision, int pointflag,
|
2011-04-10 17:42:00 +02:00
|
|
|
PrintfTarget *target)
|
1999-02-06 22:51:03 +01:00
|
|
|
{
|
2005-03-16 22:27:23 +01:00
|
|
|
int signvalue = 0;
|
2015-02-02 16:00:45 +01:00
|
|
|
int prec;
|
2005-03-17 04:18:14 +01:00
|
|
|
int vallen;
|
1999-02-06 22:51:03 +01:00
|
|
|
char fmt[32];
|
2015-02-02 16:00:45 +01:00
|
|
|
char convert[1024];
|
|
|
|
int zeropadlen = 0; /* amount to pad with zeroes */
|
|
|
|
int padlen = 0; /* amount to pad with spaces */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We rely on the regular C library's sprintf to do the basic conversion,
|
|
|
|
* then handle padding considerations here.
|
|
|
|
*
|
|
|
|
* The dynamic range of "double" is about 1E+-308 for IEEE math, and not
|
|
|
|
* too wildly more than that with other hardware. In "f" format, sprintf
|
|
|
|
* could therefore generate at most 308 characters to the left of the
|
|
|
|
* decimal point; while we need to allow the precision to get as high as
|
|
|
|
* 308+17 to ensure that we don't truncate significant digits from very
|
|
|
|
* small values. To handle both these extremes, we use a buffer of 1024
|
|
|
|
* bytes and limit requested precision to 350 digits; this should prevent
|
|
|
|
* buffer overrun even with non-IEEE math. If the original precision
|
|
|
|
* request was more than 350, separately pad with zeroes.
|
|
|
|
*/
|
|
|
|
if (precision < 0) /* cover possible overflow of "accum" */
|
|
|
|
precision = 0;
|
|
|
|
prec = Min(precision, 350);
|
1999-02-06 22:51:03 +01:00
|
|
|
|
|
|
|
if (pointflag)
|
2015-02-02 16:00:45 +01:00
|
|
|
{
|
Add error-throwing wrappers for the printf family of functions.
All known standard library implementations of these functions can fail
with ENOMEM. A caller neglecting to check for failure would experience
missing output, information exposure, or a crash. Check return values
within wrappers and code, currently just snprintf.c, that bypasses the
wrappers. The wrappers do not return after an error, so their callers
need not check. Back-patch to 9.0 (all supported versions).
Popular free software standard library implementations do take pains to
bypass malloc() in simple cases, but they risk ENOMEM for floating point
numbers, positional arguments, large field widths, and large precisions.
No specification demands such caution, so this commit regards every call
to a printf family function as a potential threat.
Injecting the wrappers implicitly is a compromise between patch scope
and design goals. I would prefer to edit each call site to name a
wrapper explicitly. libpq and the ECPG libraries would, ideally, convey
errors to the caller rather than abort(). All that would be painfully
invasive for a back-patched security fix, hence this compromise.
Security: CVE-2015-3166
2015-05-18 16:02:31 +02:00
|
|
|
if (sprintf(fmt, "%%.%d%c", prec, type) < 0)
|
|
|
|
goto fail;
|
2015-02-02 16:00:45 +01:00
|
|
|
zeropadlen = precision - prec;
|
|
|
|
}
|
Add error-throwing wrappers for the printf family of functions.
All known standard library implementations of these functions can fail
with ENOMEM. A caller neglecting to check for failure would experience
missing output, information exposure, or a crash. Check return values
within wrappers and code, currently just snprintf.c, that bypasses the
wrappers. The wrappers do not return after an error, so their callers
need not check. Back-patch to 9.0 (all supported versions).
Popular free software standard library implementations do take pains to
bypass malloc() in simple cases, but they risk ENOMEM for floating point
numbers, positional arguments, large field widths, and large precisions.
No specification demands such caution, so this commit regards every call
to a printf family function as a potential threat.
Injecting the wrappers implicitly is a compromise between patch scope
and design goals. I would prefer to edit each call site to name a
wrapper explicitly. libpq and the ECPG libraries would, ideally, convey
errors to the caller rather than abort(). All that would be painfully
invasive for a back-patched security fix, hence this compromise.
Security: CVE-2015-3166
2015-05-18 16:02:31 +02:00
|
|
|
else if (sprintf(fmt, "%%%c", type) < 0)
|
|
|
|
goto fail;
|
2005-03-16 22:27:23 +01:00
|
|
|
|
2015-02-02 16:00:45 +01:00
|
|
|
if (!isnan(value) && adjust_sign((value < 0), forcesign, &signvalue))
|
2005-10-15 04:49:52 +02:00
|
|
|
value = -value;
|
2005-03-16 22:27:23 +01:00
|
|
|
|
2005-03-17 04:18:14 +01:00
|
|
|
vallen = sprintf(convert, fmt, value);
|
Add error-throwing wrappers for the printf family of functions.
All known standard library implementations of these functions can fail
with ENOMEM. A caller neglecting to check for failure would experience
missing output, information exposure, or a crash. Check return values
within wrappers and code, currently just snprintf.c, that bypasses the
wrappers. The wrappers do not return after an error, so their callers
need not check. Back-patch to 9.0 (all supported versions).
Popular free software standard library implementations do take pains to
bypass malloc() in simple cases, but they risk ENOMEM for floating point
numbers, positional arguments, large field widths, and large precisions.
No specification demands such caution, so this commit regards every call
to a printf family function as a potential threat.
Injecting the wrappers implicitly is a compromise between patch scope
and design goals. I would prefer to edit each call site to name a
wrapper explicitly. libpq and the ECPG libraries would, ideally, convey
errors to the caller rather than abort(). All that would be painfully
invasive for a back-patched security fix, hence this compromise.
Security: CVE-2015-3166
2015-05-18 16:02:31 +02:00
|
|
|
if (vallen < 0)
|
|
|
|
goto fail;
|
1999-02-06 22:51:03 +01:00
|
|
|
|
2015-02-02 16:00:45 +01:00
|
|
|
/* If it's infinity or NaN, forget about doing any zero-padding */
|
|
|
|
if (zeropadlen > 0 && !isdigit((unsigned char) convert[vallen - 1]))
|
|
|
|
zeropadlen = 0;
|
|
|
|
|
|
|
|
adjust_padlen(minlen, vallen + zeropadlen, leftjust, &padlen);
|
2005-03-17 04:18:14 +01:00
|
|
|
|
2005-12-05 03:39:38 +01:00
|
|
|
leading_pad(zpad, &signvalue, &padlen, target);
|
1999-02-06 22:51:03 +01:00
|
|
|
|
2015-02-02 16:00:45 +01:00
|
|
|
if (zeropadlen > 0)
|
|
|
|
{
|
|
|
|
/* If 'e' or 'E' format, inject zeroes before the exponent */
|
|
|
|
char *epos = strrchr(convert, 'e');
|
|
|
|
|
|
|
|
if (!epos)
|
|
|
|
epos = strrchr(convert, 'E');
|
|
|
|
if (epos)
|
|
|
|
{
|
|
|
|
/* pad after exponent */
|
|
|
|
dostr(convert, epos - convert, target);
|
|
|
|
while (zeropadlen-- > 0)
|
|
|
|
dopr_outch('0', target);
|
|
|
|
dostr(epos, vallen - (epos - convert), target);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* no exponent, pad after the digits */
|
|
|
|
dostr(convert, vallen, target);
|
|
|
|
while (zeropadlen-- > 0)
|
|
|
|
dopr_outch('0', target);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* no zero padding, just emit the number as-is */
|
|
|
|
dostr(convert, vallen, target);
|
|
|
|
}
|
2005-03-17 04:18:14 +01:00
|
|
|
|
2005-12-05 03:39:38 +01:00
|
|
|
trailing_pad(&padlen, target);
|
Add error-throwing wrappers for the printf family of functions.
All known standard library implementations of these functions can fail
with ENOMEM. A caller neglecting to check for failure would experience
missing output, information exposure, or a crash. Check return values
within wrappers and code, currently just snprintf.c, that bypasses the
wrappers. The wrappers do not return after an error, so their callers
need not check. Back-patch to 9.0 (all supported versions).
Popular free software standard library implementations do take pains to
bypass malloc() in simple cases, but they risk ENOMEM for floating point
numbers, positional arguments, large field widths, and large precisions.
No specification demands such caution, so this commit regards every call
to a printf family function as a potential threat.
Injecting the wrappers implicitly is a compromise between patch scope
and design goals. I would prefer to edit each call site to name a
wrapper explicitly. libpq and the ECPG libraries would, ideally, convey
errors to the caller rather than abort(). All that would be painfully
invasive for a back-patched security fix, hence this compromise.
Security: CVE-2015-3166
2015-05-18 16:02:31 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
fail:
|
|
|
|
target->failed = true;
|
1999-02-06 22:51:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2011-04-10 17:42:00 +02:00
|
|
|
dostr(const char *str, int slen, PrintfTarget *target)
|
1998-09-04 16:34:23 +02:00
|
|
|
{
|
2005-12-05 03:39:38 +01:00
|
|
|
while (slen > 0)
|
|
|
|
{
|
2006-10-04 02:30:14 +02:00
|
|
|
int avail;
|
2005-12-05 03:39:38 +01:00
|
|
|
|
|
|
|
if (target->bufend != NULL)
|
|
|
|
avail = target->bufend - target->bufptr;
|
2006-10-04 02:30:14 +02:00
|
|
|
else
|
2005-12-05 03:39:38 +01:00
|
|
|
avail = slen;
|
|
|
|
if (avail <= 0)
|
|
|
|
{
|
|
|
|
/* buffer full, can we dump to stream? */
|
|
|
|
if (target->stream == NULL)
|
2006-10-04 02:30:14 +02:00
|
|
|
return; /* no, lose the data */
|
2005-12-05 03:39:38 +01:00
|
|
|
flushbuffer(target);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
avail = Min(avail, slen);
|
|
|
|
memmove(target->bufptr, str, avail);
|
|
|
|
target->bufptr += avail;
|
|
|
|
str += avail;
|
|
|
|
slen -= avail;
|
|
|
|
}
|
1998-09-04 16:34:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2011-04-10 17:42:00 +02:00
|
|
|
dopr_outch(int c, PrintfTarget *target)
|
1998-09-04 16:34:23 +02:00
|
|
|
{
|
2005-12-05 03:39:38 +01:00
|
|
|
if (target->bufend != NULL && target->bufptr >= target->bufend)
|
1998-10-07 19:12:52 +02:00
|
|
|
{
|
2005-12-05 03:39:38 +01:00
|
|
|
/* buffer full, can we dump to stream? */
|
|
|
|
if (target->stream == NULL)
|
|
|
|
return; /* no, lose the data */
|
|
|
|
flushbuffer(target);
|
1998-10-07 19:12:52 +02:00
|
|
|
}
|
2005-12-05 03:39:38 +01:00
|
|
|
*(target->bufptr++) = c;
|
1998-08-01 21:30:29 +02:00
|
|
|
}
|
2005-03-17 04:18:14 +01:00
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
adjust_sign(int is_negative, int forcesign, int *signvalue)
|
|
|
|
{
|
|
|
|
if (is_negative)
|
|
|
|
{
|
|
|
|
*signvalue = '-';
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if (forcesign)
|
|
|
|
*signvalue = '+';
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
adjust_padlen(int minlen, int vallen, int leftjust, int *padlen)
|
|
|
|
{
|
|
|
|
*padlen = minlen - vallen;
|
|
|
|
if (*padlen < 0)
|
|
|
|
*padlen = 0;
|
|
|
|
if (leftjust)
|
2005-12-05 03:39:38 +01:00
|
|
|
*padlen = -(*padlen);
|
2005-03-17 04:18:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2011-04-10 17:42:00 +02:00
|
|
|
leading_pad(int zpad, int *signvalue, int *padlen, PrintfTarget *target)
|
2005-03-17 04:18:14 +01:00
|
|
|
{
|
|
|
|
if (*padlen > 0 && zpad)
|
|
|
|
{
|
|
|
|
if (*signvalue)
|
|
|
|
{
|
2005-12-05 03:39:38 +01:00
|
|
|
dopr_outch(*signvalue, target);
|
|
|
|
--(*padlen);
|
2005-03-17 04:18:14 +01:00
|
|
|
*signvalue = 0;
|
|
|
|
}
|
|
|
|
while (*padlen > 0)
|
|
|
|
{
|
2005-12-05 03:39:38 +01:00
|
|
|
dopr_outch(zpad, target);
|
|
|
|
--(*padlen);
|
2005-03-17 04:18:14 +01:00
|
|
|
}
|
|
|
|
}
|
2005-12-05 03:39:38 +01:00
|
|
|
while (*padlen > (*signvalue != 0))
|
2005-03-17 04:18:14 +01:00
|
|
|
{
|
2005-12-05 03:39:38 +01:00
|
|
|
dopr_outch(' ', target);
|
|
|
|
--(*padlen);
|
2005-03-17 04:18:14 +01:00
|
|
|
}
|
|
|
|
if (*signvalue)
|
|
|
|
{
|
2005-12-05 03:39:38 +01:00
|
|
|
dopr_outch(*signvalue, target);
|
2005-03-17 04:18:14 +01:00
|
|
|
if (*padlen > 0)
|
2005-12-05 03:39:38 +01:00
|
|
|
--(*padlen);
|
|
|
|
else if (*padlen < 0)
|
|
|
|
++(*padlen);
|
2005-03-17 04:18:14 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2011-04-10 17:42:00 +02:00
|
|
|
trailing_pad(int *padlen, PrintfTarget *target)
|
2005-03-17 04:18:14 +01:00
|
|
|
{
|
|
|
|
while (*padlen < 0)
|
|
|
|
{
|
2005-12-05 03:39:38 +01:00
|
|
|
dopr_outch(' ', target);
|
|
|
|
++(*padlen);
|
2005-03-17 04:18:14 +01:00
|
|
|
}
|
|
|
|
}
|