mirror of https://github.com/python/cpython
Marc-Andre Lemburg <mal@lemburg.com>:
New buffer overflow checks for formatting strings. By Trent Mick.
This commit is contained in:
parent
587794b386
commit
f28dd83b86
|
@ -124,8 +124,13 @@ PyObject *
|
||||||
PyString_FromString(str)
|
PyString_FromString(str)
|
||||||
const char *str;
|
const char *str;
|
||||||
{
|
{
|
||||||
register unsigned int size = strlen(str);
|
register size_t size = strlen(str);
|
||||||
register PyStringObject *op;
|
register PyStringObject *op;
|
||||||
|
if (size > INT_MAX) {
|
||||||
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
|
"string is too long for a Python string");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
#ifndef DONT_SHARE_SHORT_STRINGS
|
#ifndef DONT_SHARE_SHORT_STRINGS
|
||||||
if (size == 0 && (op = nullstring) != NULL) {
|
if (size == 0 && (op = nullstring) != NULL) {
|
||||||
#ifdef COUNT_ALLOCS
|
#ifdef COUNT_ALLOCS
|
||||||
|
@ -237,9 +242,13 @@ static PyObject *
|
||||||
string_repr(op)
|
string_repr(op)
|
||||||
register PyStringObject *op;
|
register PyStringObject *op;
|
||||||
{
|
{
|
||||||
/* XXX overflow? */
|
size_t newsize = 2 + 4 * op->ob_size * sizeof(char);
|
||||||
int newsize = 2 + 4 * op->ob_size * sizeof(char);
|
PyObject *v;
|
||||||
PyObject *v = PyString_FromStringAndSize((char *)NULL, newsize);
|
if (newsize > INT_MAX) {
|
||||||
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
|
"string is too large to make repr");
|
||||||
|
}
|
||||||
|
v = PyString_FromStringAndSize((char *)NULL, newsize);
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -2335,36 +2344,52 @@ getnextarg(args, arglen, p_argidx)
|
||||||
#define F_ZERO (1<<4)
|
#define F_ZERO (1<<4)
|
||||||
|
|
||||||
static int
|
static int
|
||||||
formatfloat(buf, flags, prec, type, v)
|
formatfloat(buf, buflen, flags, prec, type, v)
|
||||||
char *buf;
|
char *buf;
|
||||||
|
size_t buflen;
|
||||||
int flags;
|
int flags;
|
||||||
int prec;
|
int prec;
|
||||||
int type;
|
int type;
|
||||||
PyObject *v;
|
PyObject *v;
|
||||||
{
|
{
|
||||||
|
/* fmt = '%#.' + `prec` + `type`
|
||||||
|
worst case length = 3 + 10 (len of INT_MAX) + 1 = 14 (use 20)*/
|
||||||
char fmt[20];
|
char fmt[20];
|
||||||
double x;
|
double x;
|
||||||
if (!PyArg_Parse(v, "d;float argument required", &x))
|
if (!PyArg_Parse(v, "d;float argument required", &x))
|
||||||
return -1;
|
return -1;
|
||||||
if (prec < 0)
|
if (prec < 0)
|
||||||
prec = 6;
|
prec = 6;
|
||||||
if (prec > 50)
|
|
||||||
prec = 50; /* Arbitrary limitation */
|
|
||||||
if (type == 'f' && fabs(x)/1e25 >= 1e25)
|
if (type == 'f' && fabs(x)/1e25 >= 1e25)
|
||||||
type = 'g';
|
type = 'g';
|
||||||
sprintf(fmt, "%%%s.%d%c", (flags&F_ALT) ? "#" : "", prec, type);
|
sprintf(fmt, "%%%s.%d%c", (flags&F_ALT) ? "#" : "", prec, type);
|
||||||
|
/* worst case length calc to ensure no buffer overrun:
|
||||||
|
fmt = %#.<prec>g
|
||||||
|
buf = '-' + [0-9]*prec + '.' + 'e+' + (longest exp
|
||||||
|
for any double rep.)
|
||||||
|
len = 1 + prec + 1 + 2 + 5 = 9 + prec
|
||||||
|
If prec=0 the effective precision is 1 (the leading digit is
|
||||||
|
always given), therefore increase by one to 10+prec. */
|
||||||
|
if (buflen <= (size_t)10 + (size_t)prec) {
|
||||||
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
|
"formatted float is too long (precision too long?)");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
sprintf(buf, fmt, x);
|
sprintf(buf, fmt, x);
|
||||||
return strlen(buf);
|
return strlen(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
formatint(buf, flags, prec, type, v)
|
formatint(buf, buflen, flags, prec, type, v)
|
||||||
char *buf;
|
char *buf;
|
||||||
|
size_t buflen;
|
||||||
int flags;
|
int flags;
|
||||||
int prec;
|
int prec;
|
||||||
int type;
|
int type;
|
||||||
PyObject *v;
|
PyObject *v;
|
||||||
{
|
{
|
||||||
|
/* fmt = '%#.' + `prec` + 'l' + `type`
|
||||||
|
worst case length = 3 + 10 (len of INT_MAX) + 1 + 1 = 15 (use 20)*/
|
||||||
char fmt[20];
|
char fmt[20];
|
||||||
long x;
|
long x;
|
||||||
if (!PyArg_Parse(v, "l;int argument required", &x))
|
if (!PyArg_Parse(v, "l;int argument required", &x))
|
||||||
|
@ -2372,15 +2397,24 @@ formatint(buf, flags, prec, type, v)
|
||||||
if (prec < 0)
|
if (prec < 0)
|
||||||
prec = 1;
|
prec = 1;
|
||||||
sprintf(fmt, "%%%s.%dl%c", (flags&F_ALT) ? "#" : "", prec, type);
|
sprintf(fmt, "%%%s.%dl%c", (flags&F_ALT) ? "#" : "", prec, type);
|
||||||
|
/* buf = '+'/'-'/'0'/'0x' + '[0-9]'*max(prec,len(x in octal))
|
||||||
|
worst case buf = '0x' + [0-9]*prec, where prec >= 11 */
|
||||||
|
if (buflen <= 13 || buflen <= (size_t)2+(size_t)prec) {
|
||||||
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
|
"formatted integer is too long (precision too long?)");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
sprintf(buf, fmt, x);
|
sprintf(buf, fmt, x);
|
||||||
return strlen(buf);
|
return strlen(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
formatchar(buf, v)
|
formatchar(buf, buflen, v)
|
||||||
char *buf;
|
char *buf;
|
||||||
|
size_t buflen;
|
||||||
PyObject *v;
|
PyObject *v;
|
||||||
{
|
{
|
||||||
|
/* presume that the buffer is at least 2 characters long */
|
||||||
if (PyString_Check(v)) {
|
if (PyString_Check(v)) {
|
||||||
if (!PyArg_Parse(v, "c;%c requires int or char", &buf[0]))
|
if (!PyArg_Parse(v, "c;%c requires int or char", &buf[0]))
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -2394,7 +2428,15 @@ formatchar(buf, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* fmt%(v1,v2,...) is roughly equivalent to sprintf(fmt, v1, v2, ...) */
|
/* fmt%(v1,v2,...) is roughly equivalent to sprintf(fmt, v1, v2, ...)
|
||||||
|
|
||||||
|
FORMATBUFLEN is the length of the buffer in which the floats, ints, &
|
||||||
|
chars are formatted. XXX This is a magic number. Each formatting
|
||||||
|
routine does bounds checking to ensure no overflow, but a better
|
||||||
|
solution may be to malloc a buffer of appropriate size for each
|
||||||
|
format. For now, the current solution is sufficient.
|
||||||
|
*/
|
||||||
|
#define FORMATBUFLEN (size_t)120
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
PyString_Format(format, args)
|
PyString_Format(format, args)
|
||||||
|
@ -2451,10 +2493,10 @@ PyString_Format(format, args)
|
||||||
int fill;
|
int fill;
|
||||||
PyObject *v = NULL;
|
PyObject *v = NULL;
|
||||||
PyObject *temp = NULL;
|
PyObject *temp = NULL;
|
||||||
char *buf;
|
char *pbuf;
|
||||||
int sign;
|
int sign;
|
||||||
int len;
|
int len;
|
||||||
char tmpbuf[120]; /* For format{float,int,char}() */
|
char formatbuf[FORMATBUFLEN]; /* For format{float,int,char}() */
|
||||||
char *fmt_start = fmt;
|
char *fmt_start = fmt;
|
||||||
|
|
||||||
fmt++;
|
fmt++;
|
||||||
|
@ -2602,7 +2644,7 @@ PyString_Format(format, args)
|
||||||
fill = ' ';
|
fill = ' ';
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '%':
|
case '%':
|
||||||
buf = "%";
|
pbuf = "%";
|
||||||
len = 1;
|
len = 1;
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
|
@ -2622,7 +2664,7 @@ PyString_Format(format, args)
|
||||||
"%s argument has non-string str()");
|
"%s argument has non-string str()");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
buf = PyString_AsString(temp);
|
pbuf = PyString_AsString(temp);
|
||||||
len = PyString_Size(temp);
|
len = PyString_Size(temp);
|
||||||
if (prec >= 0 && len > prec)
|
if (prec >= 0 && len > prec)
|
||||||
len = prec;
|
len = prec;
|
||||||
|
@ -2635,8 +2677,8 @@ PyString_Format(format, args)
|
||||||
case 'X':
|
case 'X':
|
||||||
if (c == 'i')
|
if (c == 'i')
|
||||||
c = 'd';
|
c = 'd';
|
||||||
buf = tmpbuf;
|
pbuf = formatbuf;
|
||||||
len = formatint(buf, flags, prec, c, v);
|
len = formatint(pbuf, sizeof(formatbuf), flags, prec, c, v);
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
goto error;
|
goto error;
|
||||||
sign = (c == 'd');
|
sign = (c == 'd');
|
||||||
|
@ -2644,9 +2686,9 @@ PyString_Format(format, args)
|
||||||
fill = '0';
|
fill = '0';
|
||||||
if ((flags&F_ALT) &&
|
if ((flags&F_ALT) &&
|
||||||
(c == 'x' || c == 'X') &&
|
(c == 'x' || c == 'X') &&
|
||||||
buf[0] == '0' && buf[1] == c) {
|
pbuf[0] == '0' && pbuf[1] == c) {
|
||||||
*res++ = *buf++;
|
*res++ = *pbuf++;
|
||||||
*res++ = *buf++;
|
*res++ = *pbuf++;
|
||||||
rescnt -= 2;
|
rescnt -= 2;
|
||||||
len -= 2;
|
len -= 2;
|
||||||
width -= 2;
|
width -= 2;
|
||||||
|
@ -2660,8 +2702,8 @@ PyString_Format(format, args)
|
||||||
case 'f':
|
case 'f':
|
||||||
case 'g':
|
case 'g':
|
||||||
case 'G':
|
case 'G':
|
||||||
buf = tmpbuf;
|
pbuf = formatbuf;
|
||||||
len = formatfloat(buf, flags, prec, c, v);
|
len = formatfloat(pbuf, sizeof(formatbuf), flags, prec, c, v);
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
goto error;
|
goto error;
|
||||||
sign = 1;
|
sign = 1;
|
||||||
|
@ -2669,8 +2711,8 @@ PyString_Format(format, args)
|
||||||
fill = '0';
|
fill = '0';
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
buf = tmpbuf;
|
pbuf = formatbuf;
|
||||||
len = formatchar(buf, v);
|
len = formatchar(pbuf, sizeof(formatbuf), v);
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
goto error;
|
goto error;
|
||||||
break;
|
break;
|
||||||
|
@ -2681,8 +2723,8 @@ PyString_Format(format, args)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (sign) {
|
if (sign) {
|
||||||
if (*buf == '-' || *buf == '+') {
|
if (*pbuf == '-' || *pbuf == '+') {
|
||||||
sign = *buf++;
|
sign = *pbuf++;
|
||||||
len--;
|
len--;
|
||||||
}
|
}
|
||||||
else if (flags & F_SIGN)
|
else if (flags & F_SIGN)
|
||||||
|
@ -2718,7 +2760,7 @@ PyString_Format(format, args)
|
||||||
}
|
}
|
||||||
if (sign && fill == ' ')
|
if (sign && fill == ' ')
|
||||||
*res++ = sign;
|
*res++ = sign;
|
||||||
memcpy(res, buf, len);
|
memcpy(res, pbuf, len);
|
||||||
res += len;
|
res += len;
|
||||||
rescnt -= len;
|
rescnt -= len;
|
||||||
while (--width >= len) {
|
while (--width >= len) {
|
||||||
|
|
|
@ -66,7 +66,7 @@ Unicode Integration Proposal (see file Misc/unicode.txt).
|
||||||
|
|
||||||
#include "mymath.h"
|
#include "mymath.h"
|
||||||
#include "unicodeobject.h"
|
#include "unicodeobject.h"
|
||||||
#include "ucnhash.h"
|
#include <ucnhash.h>
|
||||||
|
|
||||||
#if defined(HAVE_LIMITS_H)
|
#if defined(HAVE_LIMITS_H)
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
@ -1244,14 +1244,14 @@ PyObject *PyUnicode_DecodeUnicodeEscape(const char *s,
|
||||||
goto onError;
|
goto onError;
|
||||||
ucnFallthrough:
|
ucnFallthrough:
|
||||||
/* fall through on purpose */
|
/* fall through on purpose */
|
||||||
default:
|
default:
|
||||||
*p++ = '\\';
|
*p++ = '\\';
|
||||||
*p++ = (unsigned char)s[-1];
|
*p++ = (unsigned char)s[-1];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_PyUnicode_Resize(v, (int)(p - buf)))
|
if (_PyUnicode_Resize(v, (int)(p - buf)))
|
||||||
goto onError;
|
goto onError;
|
||||||
return (PyObject *)v;
|
return (PyObject *)v;
|
||||||
|
|
||||||
onError:
|
onError:
|
||||||
|
@ -4373,11 +4373,14 @@ int usprintf(va_alist) va_dcl
|
||||||
|
|
||||||
static int
|
static int
|
||||||
formatfloat(Py_UNICODE *buf,
|
formatfloat(Py_UNICODE *buf,
|
||||||
|
size_t buflen,
|
||||||
int flags,
|
int flags,
|
||||||
int prec,
|
int prec,
|
||||||
int type,
|
int type,
|
||||||
PyObject *v)
|
PyObject *v)
|
||||||
{
|
{
|
||||||
|
/* fmt = '%#.' + `prec` + `type`
|
||||||
|
worst case length = 3 + 10 (len of INT_MAX) + 1 = 14 (use 20)*/
|
||||||
char fmt[20];
|
char fmt[20];
|
||||||
double x;
|
double x;
|
||||||
|
|
||||||
|
@ -4386,21 +4389,34 @@ formatfloat(Py_UNICODE *buf,
|
||||||
return -1;
|
return -1;
|
||||||
if (prec < 0)
|
if (prec < 0)
|
||||||
prec = 6;
|
prec = 6;
|
||||||
if (prec > 50)
|
|
||||||
prec = 50; /* Arbitrary limitation */
|
|
||||||
if (type == 'f' && (fabs(x) / 1e25) >= 1e25)
|
if (type == 'f' && (fabs(x) / 1e25) >= 1e25)
|
||||||
type = 'g';
|
type = 'g';
|
||||||
sprintf(fmt, "%%%s.%d%c", (flags & F_ALT) ? "#" : "", prec, type);
|
sprintf(fmt, "%%%s.%d%c", (flags & F_ALT) ? "#" : "", prec, type);
|
||||||
|
/* worst case length calc to ensure no buffer overrun:
|
||||||
|
fmt = %#.<prec>g
|
||||||
|
buf = '-' + [0-9]*prec + '.' + 'e+' + (longest exp
|
||||||
|
for any double rep.)
|
||||||
|
len = 1 + prec + 1 + 2 + 5 = 9 + prec
|
||||||
|
If prec=0 the effective precision is 1 (the leading digit is
|
||||||
|
always given), therefore increase by one to 10+prec. */
|
||||||
|
if (buflen <= (size_t)10 + (size_t)prec) {
|
||||||
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
|
"formatted float is too long (precision too long?)");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return usprintf(buf, fmt, x);
|
return usprintf(buf, fmt, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
formatint(Py_UNICODE *buf,
|
formatint(Py_UNICODE *buf,
|
||||||
|
size_t buflen,
|
||||||
int flags,
|
int flags,
|
||||||
int prec,
|
int prec,
|
||||||
int type,
|
int type,
|
||||||
PyObject *v)
|
PyObject *v)
|
||||||
{
|
{
|
||||||
|
/* fmt = '%#.' + `prec` + 'l' + `type`
|
||||||
|
worst case length = 3 + 10 (len of INT_MAX) + 1 + 1 = 15 (use 20)*/
|
||||||
char fmt[20];
|
char fmt[20];
|
||||||
long x;
|
long x;
|
||||||
|
|
||||||
|
@ -4409,14 +4425,23 @@ formatint(Py_UNICODE *buf,
|
||||||
return -1;
|
return -1;
|
||||||
if (prec < 0)
|
if (prec < 0)
|
||||||
prec = 1;
|
prec = 1;
|
||||||
|
/* buf = '+'/'-'/'0'/'0x' + '[0-9]'*max(prec,len(x in octal))
|
||||||
|
worst case buf = '0x' + [0-9]*prec, where prec >= 11 */
|
||||||
|
if (buflen <= 13 || buflen <= (size_t)2+(size_t)prec) {
|
||||||
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
|
"formatted integer is too long (precision too long?)");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
sprintf(fmt, "%%%s.%dl%c", (flags & F_ALT) ? "#" : "", prec, type);
|
sprintf(fmt, "%%%s.%dl%c", (flags & F_ALT) ? "#" : "", prec, type);
|
||||||
return usprintf(buf, fmt, x);
|
return usprintf(buf, fmt, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
formatchar(Py_UNICODE *buf,
|
formatchar(Py_UNICODE *buf,
|
||||||
PyObject *v)
|
size_t buflen,
|
||||||
|
PyObject *v)
|
||||||
{
|
{
|
||||||
|
/* presume that the buffer is at least 2 characters long */
|
||||||
if (PyUnicode_Check(v)) {
|
if (PyUnicode_Check(v)) {
|
||||||
if (PyUnicode_GET_SIZE(v) != 1)
|
if (PyUnicode_GET_SIZE(v) != 1)
|
||||||
goto onError;
|
goto onError;
|
||||||
|
@ -4446,6 +4471,16 @@ formatchar(Py_UNICODE *buf,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* fmt%(v1,v2,...) is roughly equivalent to sprintf(fmt, v1, v2, ...)
|
||||||
|
|
||||||
|
FORMATBUFLEN is the length of the buffer in which the floats, ints, &
|
||||||
|
chars are formatted. XXX This is a magic number. Each formatting
|
||||||
|
routine does bounds checking to ensure no overflow, but a better
|
||||||
|
solution may be to malloc a buffer of appropriate size for each
|
||||||
|
format. For now, the current solution is sufficient.
|
||||||
|
*/
|
||||||
|
#define FORMATBUFLEN (size_t)120
|
||||||
|
|
||||||
PyObject *PyUnicode_Format(PyObject *format,
|
PyObject *PyUnicode_Format(PyObject *format,
|
||||||
PyObject *args)
|
PyObject *args)
|
||||||
{
|
{
|
||||||
|
@ -4505,10 +4540,10 @@ PyObject *PyUnicode_Format(PyObject *format,
|
||||||
Py_UNICODE fill;
|
Py_UNICODE fill;
|
||||||
PyObject *v = NULL;
|
PyObject *v = NULL;
|
||||||
PyObject *temp = NULL;
|
PyObject *temp = NULL;
|
||||||
Py_UNICODE *buf;
|
Py_UNICODE *pbuf;
|
||||||
Py_UNICODE sign;
|
Py_UNICODE sign;
|
||||||
int len;
|
int len;
|
||||||
Py_UNICODE tmpbuf[120]; /* For format{float,int,char}() */
|
Py_UNICODE formatbuf[FORMATBUFLEN]; /* For format{float,int,char}() */
|
||||||
|
|
||||||
fmt++;
|
fmt++;
|
||||||
if (*fmt == '(') {
|
if (*fmt == '(') {
|
||||||
|
@ -4658,8 +4693,9 @@ PyObject *PyUnicode_Format(PyObject *format,
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
|
||||||
case '%':
|
case '%':
|
||||||
buf = tmpbuf;
|
pbuf = formatbuf;
|
||||||
buf[0] = '%';
|
/* presume that buffer length is at least 1 */
|
||||||
|
pbuf[0] = '%';
|
||||||
len = 1;
|
len = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -4695,7 +4731,7 @@ PyObject *PyUnicode_Format(PyObject *format,
|
||||||
if (temp == NULL)
|
if (temp == NULL)
|
||||||
goto onError;
|
goto onError;
|
||||||
}
|
}
|
||||||
buf = PyUnicode_AS_UNICODE(temp);
|
pbuf = PyUnicode_AS_UNICODE(temp);
|
||||||
len = PyUnicode_GET_SIZE(temp);
|
len = PyUnicode_GET_SIZE(temp);
|
||||||
if (prec >= 0 && len > prec)
|
if (prec >= 0 && len > prec)
|
||||||
len = prec;
|
len = prec;
|
||||||
|
@ -4709,8 +4745,9 @@ PyObject *PyUnicode_Format(PyObject *format,
|
||||||
case 'X':
|
case 'X':
|
||||||
if (c == 'i')
|
if (c == 'i')
|
||||||
c = 'd';
|
c = 'd';
|
||||||
buf = tmpbuf;
|
pbuf = formatbuf;
|
||||||
len = formatint(buf, flags, prec, c, v);
|
len = formatint(pbuf, sizeof(formatbuf)/sizeof(Py_UNICODE),
|
||||||
|
flags, prec, c, v);
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
goto onError;
|
goto onError;
|
||||||
sign = (c == 'd');
|
sign = (c == 'd');
|
||||||
|
@ -4718,9 +4755,9 @@ PyObject *PyUnicode_Format(PyObject *format,
|
||||||
fill = '0';
|
fill = '0';
|
||||||
if ((flags&F_ALT) &&
|
if ((flags&F_ALT) &&
|
||||||
(c == 'x' || c == 'X') &&
|
(c == 'x' || c == 'X') &&
|
||||||
buf[0] == '0' && buf[1] == c) {
|
pbuf[0] == '0' && pbuf[1] == c) {
|
||||||
*res++ = *buf++;
|
*res++ = *pbuf++;
|
||||||
*res++ = *buf++;
|
*res++ = *pbuf++;
|
||||||
rescnt -= 2;
|
rescnt -= 2;
|
||||||
len -= 2;
|
len -= 2;
|
||||||
width -= 2;
|
width -= 2;
|
||||||
|
@ -4735,8 +4772,9 @@ PyObject *PyUnicode_Format(PyObject *format,
|
||||||
case 'f':
|
case 'f':
|
||||||
case 'g':
|
case 'g':
|
||||||
case 'G':
|
case 'G':
|
||||||
buf = tmpbuf;
|
pbuf = formatbuf;
|
||||||
len = formatfloat(buf, flags, prec, c, v);
|
len = formatfloat(pbuf, sizeof(formatbuf)/sizeof(Py_UNICODE),
|
||||||
|
flags, prec, c, v);
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
goto onError;
|
goto onError;
|
||||||
sign = 1;
|
sign = 1;
|
||||||
|
@ -4745,8 +4783,8 @@ PyObject *PyUnicode_Format(PyObject *format,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'c':
|
case 'c':
|
||||||
buf = tmpbuf;
|
pbuf = formatbuf;
|
||||||
len = formatchar(buf, v);
|
len = formatchar(pbuf, sizeof(formatbuf)/sizeof(Py_UNICODE), v);
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
goto onError;
|
goto onError;
|
||||||
break;
|
break;
|
||||||
|
@ -4758,8 +4796,8 @@ PyObject *PyUnicode_Format(PyObject *format,
|
||||||
goto onError;
|
goto onError;
|
||||||
}
|
}
|
||||||
if (sign) {
|
if (sign) {
|
||||||
if (*buf == '-' || *buf == '+') {
|
if (*pbuf == '-' || *pbuf == '+') {
|
||||||
sign = *buf++;
|
sign = *pbuf++;
|
||||||
len--;
|
len--;
|
||||||
}
|
}
|
||||||
else if (flags & F_SIGN)
|
else if (flags & F_SIGN)
|
||||||
|
@ -4795,7 +4833,7 @@ PyObject *PyUnicode_Format(PyObject *format,
|
||||||
}
|
}
|
||||||
if (sign && fill == ' ')
|
if (sign && fill == ' ')
|
||||||
*res++ = sign;
|
*res++ = sign;
|
||||||
memcpy(res, buf, len * sizeof(Py_UNICODE));
|
memcpy(res, pbuf, len * sizeof(Py_UNICODE));
|
||||||
res += len;
|
res += len;
|
||||||
rescnt -= len;
|
rescnt -= len;
|
||||||
while (--width >= len) {
|
while (--width >= len) {
|
||||||
|
|
Loading…
Reference in New Issue