Skip to content

Commit 9e05c50

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 56b970f commit 9e05c50

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
@@ -906,27 +908,80 @@ fmtfloat(double value, char type, int forcesign, int leftjust,
906908
PrintfTarget * target)
907909
{
908910
int signvalue = 0;
911+
int prec;
909912
int vallen;
910913
char fmt[32];
911-
char convert[512];
912-
int padlen = 0; /* amount to pad */
914+
char convert[1024];
915+
int zeropadlen = 0; /* amount to pad with zeroes */
916+
int padlen = 0; /* amount to pad with spaces */
917+
918+
/*
919+
* We rely on the regular C library's sprintf to do the basic conversion,
920+
* then handle padding considerations here.
921+
*
922+
* The dynamic range of "double" is about 1E+-308 for IEEE math, and not
923+
* too wildly more than that with other hardware. In "f" format, sprintf
924+
* could therefore generate at most 308 characters to the left of the
925+
* decimal point; while we need to allow the precision to get as high as
926+
* 308+17 to ensure that we don't truncate significant digits from very
927+
* small values. To handle both these extremes, we use a buffer of 1024
928+
* bytes and limit requested precision to 350 digits; this should prevent
929+
* buffer overrun even with non-IEEE math. If the original precision
930+
* request was more than 350, separately pad with zeroes.
931+
*/
932+
if (precision < 0) /* cover possible overflow of "accum" */
933+
precision = 0;
934+
prec = Min(precision, 350);
913935

914-
/* we rely on regular C library's sprintf to do the basic conversion */
915936
if (pointflag)
916-
sprintf(fmt, "%%.%d%c", precision, type);
937+
{
938+
sprintf(fmt, "%%.%d%c", prec, type);
939+
zeropadlen = precision - prec;
940+
}
917941
else
918942
sprintf(fmt, "%%%c", type);
919943

920-
if (adjust_sign((value < 0), forcesign, &signvalue))
944+
if (!isnan(value) && adjust_sign((value < 0), forcesign, &signvalue))
921945
value = -value;
922946

923947
vallen = sprintf(convert, fmt, value);
924948

925-
adjust_padlen(minlen, vallen, leftjust, &padlen);
949+
/* If it's infinity or NaN, forget about doing any zero-padding */
950+
if (zeropadlen > 0 && !isdigit((unsigned char) convert[vallen - 1]))
951+
zeropadlen = 0;
952+
953+
adjust_padlen(minlen, vallen + zeropadlen, leftjust, &padlen);
926954

927955
leading_pad(zpad, &signvalue, &padlen, target);
928956

929-
dostr(convert, vallen, target);
957+
if (zeropadlen > 0)
958+
{
959+
/* If 'e' or 'E' format, inject zeroes before the exponent */
960+
char *epos = strrchr(convert, 'e');
961+
962+
if (!epos)
963+
epos = strrchr(convert, 'E');
964+
if (epos)
965+
{
966+
/* pad after exponent */
967+
dostr(convert, epos - convert, target);
968+
while (zeropadlen-- > 0)
969+
dopr_outch('0', target);
970+
dostr(epos, vallen - (epos - convert), target);
971+
}
972+
else
973+
{
974+
/* no exponent, pad after the digits */
975+
dostr(convert, vallen, target);
976+
while (zeropadlen-- > 0)
977+
dopr_outch('0', target);
978+
}
979+
}
980+
else
981+
{
982+
/* no zero padding, just emit the number as-is */
983+
dostr(convert, vallen, target);
984+
}
930985

931986
trailing_pad(&padlen, target);
932987
}

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