]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Improve the sqlite3_str_vappendf() routine for additional robustness in the
authordrh <>
Thu, 25 Jun 2026 14:48:09 +0000 (14:48 +0000)
committerdrh <>
Thu, 25 Jun 2026 14:48:09 +0000 (14:48 +0000)
face of over-sized inputs.
Probable fix for [bugs:/info/2026-06-25T11:29:23Z|Bug 2026-06-25T11:29:23Z].

FossilOrigin-Name: d7e4b2a85f81dacfee497d806bbc9f8c262624bd618aa27d4d238191643a4f5d

manifest
manifest.uuid
src/printf.c

index 3226cafd98b5a823d8147d408a76bb58ee5ebead..fa3136514bea1f42663add8b2180b669cc4e3bf6 100644 (file)
--- 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.
index 967c212b0fad283e33f553db178dbe3a2274d28b..ac22dc7943acb80f2e7dc655c8bc37461f4abe48 100644 (file)
@@ -1 +1 @@
-533e59b40c4ce6b3579cb85deb9cb1a7179aa2cf4f91d8848558087869653a76
+d7e4b2a85f81dacfee497d806bbc9f8c262624bd618aa27d4d238191643a4f5d
index 2ab1de0e5fbc3a3ae2fc61db5302aeee7b82874e..58b56bbd9c5c0b5f7d77e35a585340af8fdf0cb9 100644 (file)
@@ -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( length<width ){
           i64 nPad = width - length;
@@ -753,6 +763,7 @@ void sqlite3_str_vappendf(
         if( zExtra==0 ){
           /* The result is being rendered directory into pAccum.  This
           ** is the common and fast case */
+          assert( pAccum->nChar + 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; length<precision && bufpt[length]; length++){}
           }
         }else{
-          length = 0x7fffffff & (int)strlen(bufpt);
+          length = strlen(bufpt);
         }
       adjust_width_for_utf8:
         if( flag_altform2 && width>0 ){
           /* 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; i<px; i++){
             if( (ch = ((u8*)escarg)[i])<=0x1f || ch=='"' || ch=='\\' ){
-              if( j<i ) sqlite3_str_append(pAccum, &escarg[j], i-j);
+              if( j<i ) sqlite3StrAppend64(pAccum, &escarg[j], i-j);
               j = i+1;
               if( ch==0 ) break;
               sqlite3_str_appendchar(pAccum, 1, '\\');
@@ -919,7 +930,7 @@ void sqlite3_str_vappendf(
               }
             }
           }
-          if( j<i ) sqlite3_str_append(pAccum, &escarg[j], i-j);
+          if( j<i ) sqlite3StrAppend64(pAccum, &escarg[j], i-j);
           if( xtype==etESCAPE_J ) sqlite3_str_append(pAccum, "\"", 1);
         }
         if( width>0 && 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.