mirror of
https://github.com/python/cpython.git
synced 2025-11-12 03:22:06 +00:00
fix nasty bug in resizing (formatstring)
This commit is contained in:
parent
e59214ed91
commit
013142a95f
1 changed files with 98 additions and 18 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
/***********************************************************
|
/***********************************************************
|
||||||
Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
|
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
|
||||||
Amsterdam, The Netherlands.
|
Amsterdam, The Netherlands.
|
||||||
|
|
||||||
All Rights Reserved
|
All Rights Reserved
|
||||||
|
|
@ -26,6 +26,8 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
#include "allobjects.h"
|
#include "allobjects.h"
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
#ifdef COUNT_ALLOCS
|
#ifdef COUNT_ALLOCS
|
||||||
int null_strings, one_strings;
|
int null_strings, one_strings;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -428,11 +430,11 @@ string_hash(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
static sequence_methods string_as_sequence = {
|
static sequence_methods string_as_sequence = {
|
||||||
string_length, /*sq_length*/
|
(inquiry)string_length, /*sq_length*/
|
||||||
string_concat, /*sq_concat*/
|
(binaryfunc)string_concat, /*sq_concat*/
|
||||||
string_repeat, /*sq_repeat*/
|
(intargfunc)string_repeat, /*sq_repeat*/
|
||||||
string_item, /*sq_item*/
|
(intargfunc)string_item, /*sq_item*/
|
||||||
string_slice, /*sq_slice*/
|
(intintargfunc)string_slice, /*sq_slice*/
|
||||||
0, /*sq_ass_item*/
|
0, /*sq_ass_item*/
|
||||||
0, /*sq_ass_slice*/
|
0, /*sq_ass_slice*/
|
||||||
};
|
};
|
||||||
|
|
@ -443,16 +445,16 @@ typeobject Stringtype = {
|
||||||
"string",
|
"string",
|
||||||
sizeof(stringobject),
|
sizeof(stringobject),
|
||||||
sizeof(char),
|
sizeof(char),
|
||||||
string_dealloc, /*tp_dealloc*/
|
(destructor)string_dealloc, /*tp_dealloc*/
|
||||||
string_print, /*tp_print*/
|
(printfunc)string_print, /*tp_print*/
|
||||||
0, /*tp_getattr*/
|
0, /*tp_getattr*/
|
||||||
0, /*tp_setattr*/
|
0, /*tp_setattr*/
|
||||||
string_compare, /*tp_compare*/
|
(cmpfunc)string_compare, /*tp_compare*/
|
||||||
string_repr, /*tp_repr*/
|
(reprfunc)string_repr, /*tp_repr*/
|
||||||
0, /*tp_as_number*/
|
0, /*tp_as_number*/
|
||||||
&string_as_sequence, /*tp_as_sequence*/
|
&string_as_sequence, /*tp_as_sequence*/
|
||||||
0, /*tp_as_mapping*/
|
0, /*tp_as_mapping*/
|
||||||
string_hash, /*tp_hash*/
|
(hashfunc)string_hash, /*tp_hash*/
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -461,13 +463,28 @@ joinstring(pv, w)
|
||||||
register object *w;
|
register object *w;
|
||||||
{
|
{
|
||||||
register object *v;
|
register object *v;
|
||||||
if (*pv == NULL || w == NULL || !is_stringobject(*pv))
|
if (*pv == NULL)
|
||||||
return;
|
return;
|
||||||
|
if (w == NULL || !is_stringobject(*pv)) {
|
||||||
|
DECREF(*pv);
|
||||||
|
*pv = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
v = string_concat((stringobject *) *pv, w);
|
v = string_concat((stringobject *) *pv, w);
|
||||||
DECREF(*pv);
|
DECREF(*pv);
|
||||||
*pv = v;
|
*pv = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
joinstring_decref(pv, w)
|
||||||
|
register object **pv;
|
||||||
|
register object *w;
|
||||||
|
{
|
||||||
|
joinstring(pv, w);
|
||||||
|
XDECREF(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* The following function breaks the notion that strings are immutable:
|
/* The following function breaks the notion that strings are immutable:
|
||||||
it changes the size of a string. We get away with this only if there
|
it changes the size of a string. We get away with this only if there
|
||||||
is only one module referencing the object. You can also think of it
|
is only one module referencing the object. You can also think of it
|
||||||
|
|
@ -596,6 +613,27 @@ formatchar(v)
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* XXX this could be moved to object.c */
|
||||||
|
static object *
|
||||||
|
get_mapping_item(mo, ko)
|
||||||
|
object *mo;
|
||||||
|
object *ko;
|
||||||
|
{
|
||||||
|
mapping_methods *mm = mo->ob_type->tp_as_mapping;
|
||||||
|
object *val;
|
||||||
|
|
||||||
|
if (!mm || !mm->mp_subscript) {
|
||||||
|
err_setstr(TypeError, "subscript not implemented");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
val = (*mm->mp_subscript)(mo, ko);
|
||||||
|
XDECREF(val); /* still in mapping */
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* fmt%(v1,v2,...) is roughly equivalent to sprintf(fmt, v1, v2, ...) */
|
/* fmt%(v1,v2,...) is roughly equivalent to sprintf(fmt, v1, v2, ...) */
|
||||||
|
|
||||||
object *
|
object *
|
||||||
|
|
@ -606,6 +644,7 @@ formatstring(format, args)
|
||||||
char *fmt, *res;
|
char *fmt, *res;
|
||||||
int fmtcnt, rescnt, reslen, arglen, argidx;
|
int fmtcnt, rescnt, reslen, arglen, argidx;
|
||||||
object *result;
|
object *result;
|
||||||
|
object *dict = NULL;
|
||||||
if (format == NULL || !is_stringobject(format) || args == NULL) {
|
if (format == NULL || !is_stringobject(format) || args == NULL) {
|
||||||
err_badcall();
|
err_badcall();
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -625,6 +664,8 @@ formatstring(format, args)
|
||||||
arglen = -1;
|
arglen = -1;
|
||||||
argidx = -2;
|
argidx = -2;
|
||||||
}
|
}
|
||||||
|
if (args->ob_type->tp_as_mapping)
|
||||||
|
dict = args;
|
||||||
while (--fmtcnt >= 0) {
|
while (--fmtcnt >= 0) {
|
||||||
if (*fmt != '%') {
|
if (*fmt != '%') {
|
||||||
if (--rescnt < 0) {
|
if (--rescnt < 0) {
|
||||||
|
|
@ -633,6 +674,7 @@ formatstring(format, args)
|
||||||
if (resizestring(&result, reslen) < 0)
|
if (resizestring(&result, reslen) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
res = getstringvalue(result) + reslen - rescnt;
|
res = getstringvalue(result) + reslen - rescnt;
|
||||||
|
--rescnt;
|
||||||
}
|
}
|
||||||
*res++ = *fmt++;
|
*res++ = *fmt++;
|
||||||
}
|
}
|
||||||
|
|
@ -646,9 +688,43 @@ formatstring(format, args)
|
||||||
int c = '\0';
|
int c = '\0';
|
||||||
int fill;
|
int fill;
|
||||||
object *v;
|
object *v;
|
||||||
|
object *temp = NULL;
|
||||||
char *buf;
|
char *buf;
|
||||||
int sign;
|
int sign;
|
||||||
int len;
|
int len;
|
||||||
|
if (*fmt == '(') {
|
||||||
|
char *keystart;
|
||||||
|
int keylen;
|
||||||
|
object *key;
|
||||||
|
|
||||||
|
if (dict == NULL) {
|
||||||
|
err_setstr(TypeError,
|
||||||
|
"format requires a mapping");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
++fmt;
|
||||||
|
--fmtcnt;
|
||||||
|
keystart = fmt;
|
||||||
|
while (--fmtcnt >= 0 && *fmt != ')')
|
||||||
|
fmt++;
|
||||||
|
keylen = fmt - keystart;
|
||||||
|
++fmt;
|
||||||
|
if (fmtcnt < 0) {
|
||||||
|
err_setstr(ValueError,
|
||||||
|
"incomplete format key");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
key = newsizedstringobject(keystart, keylen);
|
||||||
|
if (key == NULL)
|
||||||
|
goto error;
|
||||||
|
args = get_mapping_item(dict, key);
|
||||||
|
DECREF(key);
|
||||||
|
if (args == NULL) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
arglen = -1;
|
||||||
|
argidx = -2;
|
||||||
|
}
|
||||||
while (--fmtcnt >= 0) {
|
while (--fmtcnt >= 0) {
|
||||||
switch (c = *fmt++) {
|
switch (c = *fmt++) {
|
||||||
case '-': flags |= F_LJUST; continue;
|
case '-': flags |= F_LJUST; continue;
|
||||||
|
|
@ -745,13 +821,11 @@ formatstring(format, args)
|
||||||
len = 1;
|
len = 1;
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
if (!is_stringobject(v)) {
|
temp = strobject(v);
|
||||||
err_setstr(TypeError,
|
if (temp == NULL)
|
||||||
"%s wants string");
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
buf = getstringvalue(temp);
|
||||||
buf = getstringvalue(v);
|
len = getstringsize(temp);
|
||||||
len = getstringsize(v);
|
|
||||||
if (prec >= 0 && len > prec)
|
if (prec >= 0 && len > prec)
|
||||||
len = prec;
|
len = prec;
|
||||||
break;
|
break;
|
||||||
|
|
@ -839,6 +913,12 @@ formatstring(format, args)
|
||||||
--rescnt;
|
--rescnt;
|
||||||
*res++ = ' ';
|
*res++ = ' ';
|
||||||
}
|
}
|
||||||
|
if (dict && (argidx < arglen)) {
|
||||||
|
err_setstr(TypeError,
|
||||||
|
"not all arguments converted");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
XDECREF(temp);
|
||||||
} /* '%' */
|
} /* '%' */
|
||||||
} /* until end */
|
} /* until end */
|
||||||
if (argidx < arglen) {
|
if (argidx < arglen) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue