diff options
author | drh <drh@noemail.net> | 2011-10-11 17:54:54 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2011-10-11 17:54:54 +0000 |
commit | 59eedf7925f06e8373b226e50e95e1b802034a7b (patch) | |
tree | 5a83fcd5543e5b3960563e6d0310a6aba91fbef0 /src/printf.c | |
parent | 67855877ffa8a1d70ab17a65ead5dd3872e4623a (diff) | |
download | sqlite-59eedf7925f06e8373b226e50e95e1b802034a7b.tar.gz sqlite-59eedf7925f06e8373b226e50e95e1b802034a7b.zip |
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
Diffstat (limited to 'src/printf.c')
-rw-r--r-- | src/printf.c | 62 |
1 files changed, 32 insertions, 30 deletions
diff --git a/src/printf.c b/src/printf.c index 2a3dd81d7..2f6945577 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 && 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 */ |