From: drh Date: Tue, 11 Oct 2011 17:54:54 +0000 (+0000) Subject: Remove all precision and width limits from formatting fields in the X-Git-Tag: version-3.7.9~52 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=59eedf7925f06e8373b226e50e95e1b802034a7b;p=thirdparty%2Fsqlite.git 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 --- diff --git a/manifest b/manifest index 79c4572a2b..f38e0e3be4 100644 --- a/manifest +++ b/manifest @@ -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 diff --git a/manifest.uuid b/manifest.uuid index 076bf3c8fd..4c5accd9f0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9325c1a8c413dfbf0381190d8347f0a446ae5f5b \ No newline at end of file +1f843fb383583ee7ef51c13b8a820744e450101a \ No newline at end of file diff --git a/src/printf.c b/src/printf.c index 2a3dd81d7d..2f6945577b 100644 --- a/src/printf.c +++ b/src/printf.c @@ -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 && precisionmallocFailed = 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 */ diff --git a/test/printf.test b/test/printf.test index 100ce96b12..73222720ab 100644 --- a/test/printf.test +++ b/test/printf.test @@ -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) %}