1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-30 19:03:16 +03:00

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. 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-11T12:39:19.194 D 2011-10-11T17:54:54.587
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in a162fe39e249b8ed4a65ee947c30152786cfe897 F Makefile.in a162fe39e249b8ed4a65ee947c30152786cfe897
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@ -175,7 +175,7 @@ F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050
F src/pcache1.c 24f5e85a78514584b46190260ba7ab0a66312197 F src/pcache1.c 24f5e85a78514584b46190260ba7ab0a66312197
F src/pragma.c 68d7db4fc9de8bcfae94c1d43120531ec252b9c0 F src/pragma.c 68d7db4fc9de8bcfae94c1d43120531ec252b9c0
F src/prepare.c e64261559a3187698a3e7e6c8b001a4f4f98dab4 F src/prepare.c e64261559a3187698a3e7e6c8b001a4f4f98dab4
F src/printf.c 585a36b6a963df832cfb69505afa3a34ed5ef8a1 F src/printf.c 1cd24df913bafc0cb69dc7ae68af85cc480925aa
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
F src/resolve.c 36368f44569208fa074e61f4dd0b6c4fb60ca2b4 F src/resolve.c 36368f44569208fa074e61f4dd0b6c4fb60ca2b4
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
@ -624,7 +624,7 @@ F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
F test/permutations.test ad17319066a90e2db71823c3ff104795ffc71b31 F test/permutations.test ad17319066a90e2db71823c3ff104795ffc71b31
F test/pragma.test c8108e01da04f16e67e5754e610bc62c1b993f6c F test/pragma.test c8108e01da04f16e67e5754e610bc62c1b993f6c
F test/pragma2.test 3a55f82b954242c642f8342b17dffc8b47472947 F test/pragma2.test 3a55f82b954242c642f8342b17dffc8b47472947
F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301 F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
F test/quick.test 1681febc928d686362d50057c642f77a02c62e57 F test/quick.test 1681febc928d686362d50057c642f77a02c62e57
@ -966,7 +966,7 @@ F tool/symbols.sh caaf6ccc7300fd43353318b44524853e222557d5
F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
P e5169f9a5b7e20b8adaf6ebb7868a64e44fd7321 P 9325c1a8c413dfbf0381190d8347f0a446ae5f5b
R fa1bfea306973bc99ccb0d80c9355cfe R e5d1b1fb843cbf71cdab9d042be23020
U drh 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. ** SQLITE_PRINT_BUF_SIZE to be less than 350.
*/ */
#ifndef SQLITE_PRINT_BUF_SIZE #ifndef SQLITE_PRINT_BUF_SIZE
# if defined(SQLITE_SMALL_STACK) # define SQLITE_PRINT_BUF_SIZE 70
# define SQLITE_PRINT_BUF_SIZE 50
# else
# define SQLITE_PRINT_BUF_SIZE 350
# endif
#endif #endif
#define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */ #define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */
@ -250,6 +246,8 @@ void sqlite3VXPrintf(
LONGDOUBLE_TYPE realvalue; /* Value for real types */ LONGDOUBLE_TYPE realvalue; /* Value for real types */
const et_info *infop; /* Pointer to the appropriate info structure */ const et_info *infop; /* Pointer to the appropriate info structure */
char buf[etBUFSIZE]; /* Conversion buffer */ char buf[etBUFSIZE]; /* Conversion buffer */
char *zOut; /* Rendering buffer */
int nOut; /* Size of the rendering buffer */
char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */ char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
etByte xtype = 0; /* Conversion paradigm */ etByte xtype = 0; /* Conversion paradigm */
char *zExtra; /* Extra memory used for etTCLESCAPE conversions */ char *zExtra; /* Extra memory used for etTCLESCAPE conversions */
@ -258,7 +256,6 @@ void sqlite3VXPrintf(
double rounder; /* Used for rounding floating point values */ double rounder; /* Used for rounding floating point values */
etByte flag_dp; /* True if decimal point should be shown */ etByte flag_dp; /* True if decimal point should be shown */
etByte flag_rtz; /* True if trailing zeros should be removed */ 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 */ int nsd; /* Number of significant digits returned */
#endif #endif
@ -307,9 +304,6 @@ void sqlite3VXPrintf(
c = *++fmt; c = *++fmt;
} }
} }
if( width > etBUFSIZE-10 ){
width = etBUFSIZE-10;
}
/* Get the precision */ /* Get the precision */
if( c=='.' ){ if( c=='.' ){
precision = 0; precision = 0;
@ -356,12 +350,6 @@ void sqlite3VXPrintf(
} }
zExtra = 0; 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: ** At this point, variables are initialized as follows:
** **
@ -426,16 +414,26 @@ void sqlite3VXPrintf(
if( flag_zeropad && precision<width-(prefix!=0) ){ if( flag_zeropad && precision<width-(prefix!=0) ){
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 ){ if( xtype==etORDINAL ){
static const char zOrd[] = "thstndrd"; static const char zOrd[] = "thstndrd";
int x = (int)(longvalue % 10); int x = (int)(longvalue % 10);
if( x>=4 || (longvalue/10)%10==1 ){ if( x>=4 || (longvalue/10)%10==1 ){
x = 0; x = 0;
} }
buf[etBUFSIZE-3] = zOrd[x*2]; *(--bufpt) = zOrd[x*2+1];
buf[etBUFSIZE-2] = zOrd[x*2+1]; *(--bufpt) = zOrd[x*2];
bufpt -= 2;
} }
{ {
register const char *cset; /* Use registers for speed */ register const char *cset; /* Use registers for speed */
@ -447,7 +445,7 @@ void sqlite3VXPrintf(
longvalue = longvalue/base; longvalue = longvalue/base;
}while( longvalue>0 ); }while( longvalue>0 );
} }
length = (int)(&buf[etBUFSIZE-1]-bufpt); length = (int)(&zOut[nOut-1]-bufpt);
for(idx=precision-length; idx>0; idx--){ for(idx=precision-length; idx>0; idx--){
*(--bufpt) = '0'; /* Zero pad */ *(--bufpt) = '0'; /* Zero pad */
} }
@ -458,7 +456,7 @@ void sqlite3VXPrintf(
pre = &aPrefix[infop->prefix]; pre = &aPrefix[infop->prefix];
for(; (x=(*pre))!=0; pre++) *(--bufpt) = x; for(; (x=(*pre))!=0; pre++) *(--bufpt) = x;
} }
length = (int)(&buf[etBUFSIZE-1]-bufpt); length = (int)(&zOut[nOut-1]-bufpt);
break; break;
case etFLOAT: case etFLOAT:
case etEXP: case etEXP:
@ -468,7 +466,6 @@ void sqlite3VXPrintf(
length = 0; length = 0;
#else #else
if( precision<0 ) precision = 6; /* Set default precision */ if( precision<0 ) precision = 6; /* Set default precision */
if( precision>etBUFSIZE/2-10 ) precision = etBUFSIZE/2-10;
if( realvalue<0.0 ){ if( realvalue<0.0 ){
realvalue = -realvalue; realvalue = -realvalue;
prefix = '-'; prefix = '-';
@ -516,7 +513,6 @@ void sqlite3VXPrintf(
** If the field type is etGENERIC, then convert to either etEXP ** If the field type is etGENERIC, then convert to either etEXP
** or etFLOAT, as appropriate. ** or etFLOAT, as appropriate.
*/ */
flag_exp = xtype==etEXP;
if( xtype!=etFLOAT ){ if( xtype!=etFLOAT ){
realvalue += rounder; realvalue += rounder;
if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; } if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; }
@ -537,6 +533,14 @@ void sqlite3VXPrintf(
}else{ }else{
e2 = exp; 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; nsd = 0;
flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2; flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2;
/* The sign in front of the number */ /* The sign in front of the number */
@ -568,7 +572,7 @@ void sqlite3VXPrintf(
/* Remove trailing zeros and the "." if no digits follow the "." */ /* Remove trailing zeros and the "." if no digits follow the "." */
if( flag_rtz && flag_dp ){ if( flag_rtz && flag_dp ){
while( bufpt[-1]=='0' ) *(--bufpt) = 0; while( bufpt[-1]=='0' ) *(--bufpt) = 0;
assert( bufpt>buf ); assert( bufpt>zOut );
if( bufpt[-1]=='.' ){ if( bufpt[-1]=='.' ){
if( flag_altform2 ){ if( flag_altform2 ){
*(bufpt++) = '0'; *(bufpt++) = '0';
@ -578,7 +582,7 @@ void sqlite3VXPrintf(
} }
} }
/* Add the "eNNN" suffix */ /* Add the "eNNN" suffix */
if( flag_exp || xtype==etEXP ){ if( xtype==etEXP ){
*(bufpt++) = aDigits[infop->charset]; *(bufpt++) = aDigits[infop->charset];
if( exp<0 ){ if( exp<0 ){
*(bufpt++) = '-'; exp = -exp; *(bufpt++) = '-'; exp = -exp;
@ -597,8 +601,8 @@ void sqlite3VXPrintf(
/* The converted number is in buf[] and zero terminated. Output it. /* The converted number is in buf[] and zero terminated. Output it.
** Note that the number is in the usual order, not reversed as with ** Note that the number is in the usual order, not reversed as with
** integer conversions. */ ** integer conversions. */
length = (int)(bufpt-buf); length = (int)(bufpt-zOut);
bufpt = buf; bufpt = zOut;
/* Special case: Add leading zeros if the flag_zeropad flag is /* Special case: Add leading zeros if the flag_zeropad flag is
** set and we are not left justified */ ** set and we are not left justified */
@ -736,9 +740,7 @@ void sqlite3VXPrintf(
appendSpace(pAccum, nspace); appendSpace(pAccum, nspace);
} }
} }
if( zExtra ){ sqlite3_free(zExtra);
sqlite3_free(zExtra);
}
}/* End for loop over the format string */ }/* End for loop over the format string */
} /* End of function */ } /* End of function */

View File

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