Skip to content

Commit 29725b3

Browse files
committed
port/snprintf(): fix overflow and do padding
Prevent port/snprintf() from overflowing its local fixed-size buffer and pad to the desired number of digits with zeros, even if the precision is beyond the ability of the native sprintf(). port/snprintf() is only used on systems that lack a native snprintf(). Reported by Bruce Momjian. Patch by Tom Lane. Backpatch to all supported versions. Security: CVE-2015-0242
1 parent 9241c84 commit 29725b3

File tree

1 file changed

+62
-7
lines changed

1 file changed

+62
-7
lines changed

src/port/snprintf.c

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@
3232

3333
#include "c.h"
3434

35+
#include <ctype.h>
3536
#include <limits.h>
37+
#include <math.h>
3638
#ifndef WIN32
3739
#include <sys/ioctl.h>
3840
#endif
@@ -932,27 +934,80 @@ fmtfloat(double value, char type, int forcesign, int leftjust,
932934
PrintfTarget *target)
933935
{
934936
int signvalue = 0;
937+
int prec;
935938
int vallen;
936939
char fmt[32];
937-
char convert[512];
938-
int padlen = 0; /* amount to pad */
940+
char convert[1024];
941+
int zeropadlen = 0; /* amount to pad with zeroes */
942+
int padlen = 0; /* amount to pad with spaces */
943+
944+
/*
945+
* We rely on the regular C library's sprintf to do the basic conversion,
946+
* then handle padding considerations here.
947+
*
948+
* The dynamic range of "double" is about 1E+-308 for IEEE math, and not
949+
* too wildly more than that with other hardware. In "f" format, sprintf
950+
* could therefore generate at most 308 characters to the left of the
951+
* decimal point; while we need to allow the precision to get as high as
952+
* 308+17 to ensure that we don't truncate significant digits from very
953+
* small values. To handle both these extremes, we use a buffer of 1024
954+
* bytes and limit requested precision to 350 digits; this should prevent
955+
* buffer overrun even with non-IEEE math. If the original precision
956+
* request was more than 350, separately pad with zeroes.
957+
*/
958+
if (precision < 0) /* cover possible overflow of "accum" */
959+
precision = 0;
960+
prec = Min(precision, 350);
939961

940-
/* we rely on regular C library's sprintf to do the basic conversion */
941962
if (pointflag)
942-
sprintf(fmt, "%%.%d%c", precision, type);
963+
{
964+
sprintf(fmt, "%%.%d%c", prec, type);
965+
zeropadlen = precision - prec;
966+
}
943967
else
944968
sprintf(fmt, "%%%c", type);
945969

946-
if (adjust_sign((value < 0), forcesign, &signvalue))
970+
if (!isnan(value) && adjust_sign((value < 0), forcesign, &signvalue))
947971
value = -value;
948972

949973
vallen = sprintf(convert, fmt, value);
950974

951-
adjust_padlen(minlen, vallen, leftjust, &padlen);
975+
/* If it's infinity or NaN, forget about doing any zero-padding */
976+
if (zeropadlen > 0 && !isdigit((unsigned char) convert[vallen - 1]))
977+
zeropadlen = 0;
978+
979+
adjust_padlen(minlen, vallen + zeropadlen, leftjust, &padlen);
952980

953981
leading_pad(zpad, &signvalue, &padlen, target);
954982

955-
dostr(convert, vallen, target);
983+
if (zeropadlen > 0)
984+
{
985+
/* If 'e' or 'E' format, inject zeroes before the exponent */
986+
char *epos = strrchr(convert, 'e');
987+
988+
if (!epos)
989+
epos = strrchr(convert, 'E');
990+
if (epos)
991+
{
992+
/* pad after exponent */
993+
dostr(convert, epos - convert, target);
994+
while (zeropadlen-- > 0)
995+
dopr_outch('0', target);
996+
dostr(epos, vallen - (epos - convert), target);
997+
}
998+
else
999+
{
1000+
/* no exponent, pad after the digits */
1001+
dostr(convert, vallen, target);
1002+
while (zeropadlen-- > 0)
1003+
dopr_outch('0', target);
1004+
}
1005+
}
1006+
else
1007+
{
1008+
/* no zero padding, just emit the number as-is */
1009+
dostr(convert, vallen, target);
1010+
}
9561011

9571012
trailing_pad(&padlen, target);
9581013
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy