Remove all precision and width limits from formatting fields in the

sqlite3_mprintf() family of functions. Malloc for space as necessary.
The prevents a stack overflow on very large numbers using %f.

FossilOrigin-Name: 1f843fb383583ee7ef51c13b8a820744e450101a
This commit is contained in:
drh 2011-10-11 17:54:54 +00:00
parent 67855877ff
commit 59eedf7925
4 changed files with 41 additions and 39 deletions

View File

@ -1,5 +1,5 @@
C Fix\srequirements\smarks\sassociate\swith\sSTAT3.
D 2011-10-11T12:39:19.194
C Remove\sall\sprecision\sand\swidth\slimits\sfrom\sformatting\sfields\sin\sthe\nsqlite3_mprintf()\sfamily\sof\sfunctions.\sMalloc\sfor\sspace\sas\snecessary.\nThe\sprevents\sa\sstack\soverflow\son\svery\slarge\snumbers\susing\s%f.
D 2011-10-11T17:54:54.587
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in a162fe39e249b8ed4a65ee947c30152786cfe897
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@ -175,7 +175,7 @@ F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050
F src/pcache1.c 24f5e85a78514584b46190260ba7ab0a66312197
F src/pragma.c 68d7db4fc9de8bcfae94c1d43120531ec252b9c0
F src/prepare.c e64261559a3187698a3e7e6c8b001a4f4f98dab4
F src/printf.c 585a36b6a963df832cfb69505afa3a34ed5ef8a1
F src/printf.c 1cd24df913bafc0cb69dc7ae68af85cc480925aa
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
F src/resolve.c 36368f44569208fa074e61f4dd0b6c4fb60ca2b4
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
@ -624,7 +624,7 @@ F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
F test/permutations.test ad17319066a90e2db71823c3ff104795ffc71b31
F test/pragma.test c8108e01da04f16e67e5754e610bc62c1b993f6c
F test/pragma2.test 3a55f82b954242c642f8342b17dffc8b47472947
F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
F test/quick.test 1681febc928d686362d50057c642f77a02c62e57
@ -966,7 +966,7 @@ F tool/symbols.sh caaf6ccc7300fd43353318b44524853e222557d5
F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
P e5169f9a5b7e20b8adaf6ebb7868a64e44fd7321
R fa1bfea306973bc99ccb0d80c9355cfe
P 9325c1a8c413dfbf0381190d8347f0a446ae5f5b
R e5d1b1fb843cbf71cdab9d042be23020
U drh
Z 7aa6c1f7c4e6214ddb2d3b34feac8ca1
Z 4feb18f759ff84be86477c96fb244530

View File

@ -1 +1 @@
9325c1a8c413dfbf0381190d8347f0a446ae5f5b
1f843fb383583ee7ef51c13b8a820744e450101a

View File

@ -190,11 +190,7 @@ static void appendSpace(StrAccum *pAccum, int N){
** SQLITE_PRINT_BUF_SIZE to be less than 350.
*/
#ifndef SQLITE_PRINT_BUF_SIZE
# if defined(SQLITE_SMALL_STACK)
# define SQLITE_PRINT_BUF_SIZE 50
# else
# define SQLITE_PRINT_BUF_SIZE 350
# endif
# define SQLITE_PRINT_BUF_SIZE 70
#endif
#define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */
@ -250,6 +246,8 @@ void sqlite3VXPrintf(
LONGDOUBLE_TYPE realvalue; /* Value for real types */
const et_info *infop; /* Pointer to the appropriate info structure */
char buf[etBUFSIZE]; /* Conversion buffer */
char *zOut; /* Rendering buffer */
int nOut; /* Size of the rendering buffer */
char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
etByte xtype = 0; /* Conversion paradigm */
char *zExtra; /* Extra memory used for etTCLESCAPE conversions */
@ -258,7 +256,6 @@ void sqlite3VXPrintf(
double rounder; /* Used for rounding floating point values */
etByte flag_dp; /* True if decimal point should be shown */
etByte flag_rtz; /* True if trailing zeros should be removed */
etByte flag_exp; /* True to force display of the exponent */
int nsd; /* Number of significant digits returned */
#endif
@ -307,9 +304,6 @@ void sqlite3VXPrintf(
c = *++fmt;
}
}
if( width > etBUFSIZE-10 ){
width = etBUFSIZE-10;
}
/* Get the precision */
if( c=='.' ){
precision = 0;
@ -356,12 +350,6 @@ void sqlite3VXPrintf(
}
zExtra = 0;
/* Limit the precision to prevent overflowing buf[] during conversion */
if( precision>etBUFSIZE-40 && (infop->flags & FLAG_STRING)==0 ){
precision = etBUFSIZE-40;
}
/*
** At this point, variables are initialized as follows:
**
@ -426,16 +414,26 @@ void sqlite3VXPrintf(
if( flag_zeropad && precision<width-(prefix!=0) ){
precision = width-(prefix!=0);
}
bufpt = &buf[etBUFSIZE-1];
if( precision<etBUFSIZE-10 ){
nOut = etBUFSIZE;
zOut = buf;
}else{
nOut = precision + 10;
zOut = zExtra = sqlite3Malloc( nOut );
if( zOut==0 ){
pAccum->mallocFailed = 1;
return;
}
}
bufpt = &zOut[nOut-1];
if( xtype==etORDINAL ){
static const char zOrd[] = "thstndrd";
int x = (int)(longvalue % 10);
if( x>=4 || (longvalue/10)%10==1 ){
x = 0;
}
buf[etBUFSIZE-3] = zOrd[x*2];
buf[etBUFSIZE-2] = zOrd[x*2+1];
bufpt -= 2;
*(--bufpt) = zOrd[x*2+1];
*(--bufpt) = zOrd[x*2];
}
{
register const char *cset; /* Use registers for speed */
@ -447,7 +445,7 @@ void sqlite3VXPrintf(
longvalue = longvalue/base;
}while( longvalue>0 );
}
length = (int)(&buf[etBUFSIZE-1]-bufpt);
length = (int)(&zOut[nOut-1]-bufpt);
for(idx=precision-length; idx>0; idx--){
*(--bufpt) = '0'; /* Zero pad */
}
@ -458,7 +456,7 @@ void sqlite3VXPrintf(
pre = &aPrefix[infop->prefix];
for(; (x=(*pre))!=0; pre++) *(--bufpt) = x;
}
length = (int)(&buf[etBUFSIZE-1]-bufpt);
length = (int)(&zOut[nOut-1]-bufpt);
break;
case etFLOAT:
case etEXP:
@ -468,7 +466,6 @@ void sqlite3VXPrintf(
length = 0;
#else
if( precision<0 ) precision = 6; /* Set default precision */
if( precision>etBUFSIZE/2-10 ) precision = etBUFSIZE/2-10;
if( realvalue<0.0 ){
realvalue = -realvalue;
prefix = '-';
@ -516,7 +513,6 @@ void sqlite3VXPrintf(
** If the field type is etGENERIC, then convert to either etEXP
** or etFLOAT, as appropriate.
*/
flag_exp = xtype==etEXP;
if( xtype!=etFLOAT ){
realvalue += rounder;
if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; }
@ -537,6 +533,14 @@ void sqlite3VXPrintf(
}else{
e2 = exp;
}
if( e2+precision+width > etBUFSIZE - 15 ){
bufpt = zExtra = sqlite3Malloc( e2+precision+width+15 );
if( bufpt==0 ){
pAccum->mallocFailed = 1;
return;
}
}
zOut = bufpt;
nsd = 0;
flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2;
/* The sign in front of the number */
@ -568,7 +572,7 @@ void sqlite3VXPrintf(
/* Remove trailing zeros and the "." if no digits follow the "." */
if( flag_rtz && flag_dp ){
while( bufpt[-1]=='0' ) *(--bufpt) = 0;
assert( bufpt>buf );
assert( bufpt>zOut );
if( bufpt[-1]=='.' ){
if( flag_altform2 ){
*(bufpt++) = '0';
@ -578,7 +582,7 @@ void sqlite3VXPrintf(
}
}
/* Add the "eNNN" suffix */
if( flag_exp || xtype==etEXP ){
if( xtype==etEXP ){
*(bufpt++) = aDigits[infop->charset];
if( exp<0 ){
*(bufpt++) = '-'; exp = -exp;
@ -597,8 +601,8 @@ void sqlite3VXPrintf(
/* The converted number is in buf[] and zero terminated. Output it.
** Note that the number is in the usual order, not reversed as with
** integer conversions. */
length = (int)(bufpt-buf);
bufpt = buf;
length = (int)(bufpt-zOut);
bufpt = zOut;
/* Special case: Add leading zeros if the flag_zeropad flag is
** set and we are not left justified */
@ -736,9 +740,7 @@ void sqlite3VXPrintf(
appendSpace(pAccum, nspace);
}
}
if( zExtra ){
sqlite3_free(zExtra);
}
sqlite3_free(zExtra);
}/* End for loop over the format string */
} /* End of function */

View File

@ -3547,7 +3547,7 @@ do_test printf-4.16 {
do_test printf-5.1 {
set x [sqlite3_mprintf_str {%d %d %100000s} 0 0 {Hello}]
string length $x
} {344}
} {100004}
do_test printf-5.2 {
sqlite3_mprintf_str {%d %d (%-10.10s) %} -9 -10 {HelloHelloHello}
} {-9 -10 (HelloHello) %}