aboutsummaryrefslogtreecommitdiff
path: root/src/printf.c
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2011-10-11 17:54:54 +0000
committerdrh <drh@noemail.net>2011-10-11 17:54:54 +0000
commit59eedf7925f06e8373b226e50e95e1b802034a7b (patch)
tree5a83fcd5543e5b3960563e6d0310a6aba91fbef0 /src/printf.c
parent67855877ffa8a1d70ab17a65ead5dd3872e4623a (diff)
downloadsqlite-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.c62
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 */