From: drh <> Date: Thu, 25 Jun 2026 14:48:09 +0000 (+0000) Subject: Improve the sqlite3_str_vappendf() routine for additional robustness in the X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=eac3240484823180c41a22a5289353deceb95bca;p=thirdparty%2Fsqlite.git Improve the sqlite3_str_vappendf() routine for additional robustness in the face of over-sized inputs. Probable fix for [bugs:/info/2026-06-25T11:29:23Z|Bug 2026-06-25T11:29:23Z]. FossilOrigin-Name: d7e4b2a85f81dacfee497d806bbc9f8c262624bd618aa27d4d238191643a4f5d --- diff --git a/manifest b/manifest index 3226cafd98..fa3136514b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Have\ssqlite3_drop_modules()\stake\sthe\sdatabase\smutex.\sBug\s[bugs:/info/2026-06-25T12:11:37Z\s|\s2026-06-25T12:11:37Z\s]. -D 2026-06-25T14:25:15.704 +C Improve\sthe\ssqlite3_str_vappendf()\sroutine\sfor\sadditional\srobustness\sin\sthe\nface\sof\sover-sized\sinputs.\nProbable\sfix\sfor\s[bugs:/info/2026-06-25T11:29:23Z|Bug\s2026-06-25T11:29:23Z]. +D 2026-06-25T14:48:09.072 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -733,7 +733,7 @@ F src/pcache.h 092b758d2c5e4dabb30eae46d8dfad77c0f70b16bf3ff1943f7a232b0fe0d4ba F src/pcache1.c d7ee0f95992501a65379f620b3de1430b64e52e397769938668a9fd9dd1c8145 F src/pragma.c 789ef67117b74b5be0a2db6681f7f0c55e6913791b9da309aefd280de2c8a74d F src/prepare.c b1337cd601f8cb58c07a61bafdf2e501332dd1a07959c5d1c118a5adef01f4c7 -F src/printf.c f85d3d8b8d88cd4775eb1d5f8c748bccc73295b019e23d1fe8b8bdc72e34e4bb +F src/printf.c 69a89414b6368901b286a5579dea34cc3470a7d10f2b0fea93f7eb5d8f1e2e71 F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c F src/resolve.c d0724113da9f5c0430d2052808ce59519f51ae7c4fbb1f5ef21fe3a832956086 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97 @@ -2208,8 +2208,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P 50cce4758361379f1585b30c619f2c9f7f8873dbfaeaec3ff357e26c1034546c -R 41808b48b7d47b44783f317331e7538d -U dan -Z 8791c131d6a449cb873822403028b35a +P 533e59b40c4ce6b3579cb85deb9cb1a7179aa2cf4f91d8848558087869653a76 +R ae624d5f391b48a06271e9ea7c82fcdc +U drh +Z 9b8286faa7f7c2ce59f32e157afe28d6 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 967c212b0f..ac22dc7943 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -533e59b40c4ce6b3579cb85deb9cb1a7179aa2cf4f91d8848558087869653a76 +d7e4b2a85f81dacfee497d806bbc9f8c262624bd618aa27d4d238191643a4f5d diff --git a/src/printf.c b/src/printf.c index 2ab1de0e5f..58b56bbd9c 100644 --- a/src/printf.c +++ b/src/printf.c @@ -193,6 +193,10 @@ static char *printfTempBuf(sqlite3_str *pAccum, sqlite3_int64 n){ # define SQLITE_FP_PRECISION_LIMIT 100000000 #endif +/* Forward reference */ +static void sqlite3StrAppend64(sqlite3_str *p, const char *z, i64 N); +static void sqlite3StrAppendchar64(sqlite3_str *p, i64 N, char c); + /* ** Render a string given by "fmt" into the StrAccum object. */ @@ -203,10 +207,10 @@ void sqlite3_str_vappendf( ){ int c; /* Next character in the format string */ char *bufpt; /* Pointer to the conversion buffer */ - int precision; /* Precision of the current field */ - int length; /* Length of the field */ + i64 precision; /* Precision of the current field */ + i64 length; /* Length of the field */ int idx; /* A general purpose loop counter */ - int width; /* Width of the current field */ + i64 width; /* Width of the current field */ etByte flag_leftjustify; /* True if "-" flag is present */ etByte flag_prefix; /* '+' or ' ' or 0 for prefix */ etByte flag_alternateform; /* True if "#" flag is present */ @@ -254,7 +258,7 @@ void sqlite3_str_vappendf( fmt = bufpt + strlen(bufpt); } #endif - sqlite3_str_append(pAccum, bufpt, (int)(fmt - bufpt)); + sqlite3StrAppend64(pAccum, bufpt, fmt - bufpt); if( *fmt==0 ) break; } if( (c=(*++fmt))==0 ){ @@ -500,22 +504,23 @@ void sqlite3_str_vappendf( longvalue = longvalue/base; }while( longvalue>0 ); } - length = (int)(&zOut[nOut-1]-bufpt); + length = &zOut[nOut-1] - bufpt; if( precision>length ){ /* zero pad */ - int nn = precision-length; + i64 nn = precision-length; bufpt -= nn; memset(bufpt,'0',nn); length = precision; } if( cThousand ){ - int nn = (length - 1)/3; /* Number of "," to insert */ - int ix = (length - 1)%3 + 1; + i64 nn = (length - 1)/3; /* Number of "," to insert */ + i64 ix = (length - 1)%3 + 1; + int ii; bufpt -= nn; - for(idx=0; nn>0; idx++){ - bufpt[idx] = bufpt[idx+nn]; + for(ii=0; nn>0; ii++){ + bufpt[ii] = bufpt[ii+nn]; ix--; if( ix==0 ){ - bufpt[++idx] = cThousand; + bufpt[++ii] = cThousand; nn--; ix = 3; } @@ -528,7 +533,7 @@ void sqlite3_str_vappendf( pre = &aPrefix[infop->prefix]; for(; (x=(*pre))!=0; pre++) *(--bufpt) = x; } - length = (int)(&zOut[nOut-1]-bufpt); + length = &zOut[nOut-1] - bufpt; break; case etFLOAT: case etEXP: @@ -560,8 +565,13 @@ void sqlite3_str_vappendf( sqlite3FpDecode(&s, realvalue, iRound, flag_altform2 ? 20 : 16); if( s.isSpecial ){ if( s.isSpecial==2 ){ - bufpt = flag_zeropad ? "null" : "NaN"; - length = sqlite3Strlen30(bufpt); + if( flag_zeropad ){ + bufpt = "null"; + length = 4; + }else{ + bufpt = "NaN"; + length = 3; + } break; }else if( flag_zeropad ){ s.z[0] = '9'; @@ -577,7 +587,7 @@ void sqlite3_str_vappendf( }else{ bufpt++; } - length = sqlite3Strlen30(bufpt); + length = strlen(bufpt); break; } } @@ -733,7 +743,7 @@ void sqlite3_str_vappendf( *(bufpt++) = (char)(exp%10+'0'); /* 1's digit */ } - length = (int)(bufpt-zOut); + length = bufpt - zOut; assert( length <= szBufNeeded ); if( lengthnChar + length < SMXV(pAccum->nChar) ); pAccum->nChar += length; zOut[length] = 0; continue; @@ -799,10 +810,10 @@ void sqlite3_str_vappendf( i64 nPrior = 1; width -= precision-1; if( width>1 && !flag_leftjustify ){ - sqlite3_str_appendchar(pAccum, width-1, ' '); + sqlite3StrAppendchar64(pAccum, width-1, ' '); width = 0; } - sqlite3_str_append(pAccum, buf, length); + sqlite3StrAppend64(pAccum, buf, length); precision--; while( precision > 1 ){ i64 nCopyBytes; @@ -858,17 +869,17 @@ void sqlite3_str_vappendf( while( precision-- > 0 && z[0] ){ SQLITE_SKIP_UTF8(z); } - length = (int)(0x7fffffff & (z - (unsigned char*)bufpt)); + length = z - (unsigned char*)bufpt; }else{ for(length=0; length0 ){ /* Adjust width to account for extra bytes in UTF-8 characters */ - int ii = length - 1; + i64 ii = length - 1; while( ii>=0 ) if( (bufpt[ii--] & 0xc0)==0x80 ) width++; } break; @@ -903,7 +914,7 @@ void sqlite3_str_vappendf( } for(i=j=0; i0 && sqlite3_str_errcode(pAccum)==SQLITE_OK ){ @@ -935,7 +946,7 @@ void sqlite3_str_vappendf( if( width>len ){ sqlite3_int64 sp = width-len; assert( sp>0 && sp<0x7fffffff ); - sqlite3_str_appendchar(pAccum, (int)sp, ' '); + sqlite3StrAppendchar64(pAccum, (int)sp, ' '); if( !flag_leftjustify && n>0 && sqlite3_str_errcode(pAccum)==0 @@ -1127,11 +1138,11 @@ void sqlite3_str_vappendf( */ width -= length; if( width>0 ){ - if( !flag_leftjustify ) sqlite3_str_appendchar(pAccum, width, ' '); - sqlite3_str_append(pAccum, bufpt, length); - if( flag_leftjustify ) sqlite3_str_appendchar(pAccum, width, ' '); + if( !flag_leftjustify ) sqlite3StrAppendchar64(pAccum, width, ' '); + sqlite3StrAppend64(pAccum, bufpt, length); + if( flag_leftjustify ) sqlite3StrAppendchar64(pAccum, width, ' '); }else{ - sqlite3_str_append(pAccum, bufpt, length); + sqlite3StrAppend64(pAccum, bufpt, length); } if( zExtra ){ @@ -1251,6 +1262,13 @@ void sqlite3_str_appendchar(sqlite3_str *p, int N, char c){ } while( (N--)>0 ) p->zText[p->nChar++] = c; } +static void sqlite3StrAppendchar64(sqlite3_str *p, i64 N, char c){ + testcase( p->nChar + N > 0x7fffffff ); + if( p->nChar+N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){ + return; + } + while( (N--)>0 ) p->zText[p->nChar++] = c; +} /* ** The StrAccum "p" is not large enough to accept N new bytes of z[]. @@ -1285,6 +1303,20 @@ void sqlite3_str_append(sqlite3_str *p, const char *z, int N){ memcpy(&p->zText[p->nChar-N], z, N); } } +static void sqlite3StrAppend64(sqlite3_str *p, const char *z, i64 N){ + assert( z!=0 || N==0 ); + assert( p->zText!=0 || p->nChar==0 || p->accError ); + assert( N>=0 ); + assert( p->accError==0 || p->nAlloc==0 || p->mxAlloc==0 ); + if( p->nChar+N >= (i64)p->nAlloc ){ + enlargeAndAppend(p,z,N); + }else if( N ){ + assert( p->zText ); + p->nChar += N; + memcpy(&p->zText[p->nChar-N], z, N); + } +} + /* ** Append the complete text of zero-terminated string z[] to the p string.