/ Check-in [d612fb78]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Make sure the OP_Concat opcode always correctly zero-terminates a UTF16 string, even if the input strings are ill-formed. This is a followup to check-in [3a16ddf91f0c9c516a7] that fixes a case the previous check-in missed. Also add assert()s to prove correct zero termination.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: d612fb7873cf59dfda18cabe45f674c37aa78a4587de3378b1840c99465a0269
User & Date: drh 2019-05-16 01:22:21
References
2019-05-16
11:47
Fix a harmless use-of-initialized-value fault in the assert() logic added by check-in [d612fb7873cf59d] check-in: 3dac9072 user: drh tags: trunk
Context
2019-05-16
03:47
Fix harmless compiler warning in the session extension. check-in: dff823ca user: mistachkin tags: trunk
01:22
Make sure the OP_Concat opcode always correctly zero-terminates a UTF16 string, even if the input strings are ill-formed. This is a followup to check-in [3a16ddf91f0c9c516a7] that fixes a case the previous check-in missed. Also add assert()s to prove correct zero termination. check-in: d612fb78 user: drh tags: trunk
2019-05-15
18:42
Fix the count-of-view optimization so that it is (correctly) disabled for a query that includes a WHERE clause or a GROUP BY clause. check-in: 05897ca4 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/vdbe.c.

  1497   1497       if( sqlite3VdbeMemExpandBlob(pIn2) ) goto no_mem;
  1498   1498       flags2 = pIn2->flags & ~MEM_Str;
  1499   1499     }
  1500   1500     nByte = pIn1->n + pIn2->n;
  1501   1501     if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
  1502   1502       goto too_big;
  1503   1503     }
  1504         -  if( sqlite3VdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2) ){
         1504  +  if( sqlite3VdbeMemGrow(pOut, (int)nByte+3, pOut==pIn2) ){
  1505   1505       goto no_mem;
  1506   1506     }
  1507   1507     MemSetTypeFlag(pOut, MEM_Str);
  1508   1508     if( pOut!=pIn2 ){
  1509   1509       memcpy(pOut->z, pIn2->z, pIn2->n);
  1510   1510       assert( (pIn2->flags & MEM_Dyn) == (flags2 & MEM_Dyn) );
  1511   1511       pIn2->flags = flags2;
  1512   1512     }
  1513   1513     memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n);
  1514   1514     assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
  1515   1515     pIn1->flags = flags1;
  1516   1516     pOut->z[nByte]=0;
  1517   1517     pOut->z[nByte+1] = 0;
         1518  +  pOut->z[nByte+2] = 0;
  1518   1519     pOut->flags |= MEM_Term;
  1519   1520     pOut->n = (int)nByte;
  1520   1521     pOut->enc = encoding;
  1521   1522     UPDATE_MAX_BLOBSIZE(pOut);
  1522   1523     break;
  1523   1524   }
  1524   1525   

Changes to src/vdbemem.c.

   114    114     }
   115    115     assert( acc.zText==zBuf && acc.mxAlloc<=0 );
   116    116     zBuf[acc.nChar] = 0; /* Fast version of sqlite3StrAccumFinish(&acc) */
   117    117   }
   118    118   
   119    119   #ifdef SQLITE_DEBUG
   120    120   /*
   121         -** Check that string value of pMem agrees with its integer or real value.
          121  +** Validity checks on pMem.  pMem holds a string.
          122  +**
          123  +** (1) Check that string value of pMem agrees with its integer or real value.
          124  +** (2) Check that the string is correctly zero terminated
   122    125   **
   123    126   ** A single int or real value always converts to the same strings.  But
   124    127   ** many different strings can be converted into the same int or real.
   125    128   ** If a table contains a numeric value and an index is based on the
   126    129   ** corresponding string value, then it is important that the string be
   127    130   ** derived from the numeric value, not the other way around, to ensure
   128    131   ** that the index and table are consistent.  See ticket
................................................................................
   132    135   ** This routine looks at pMem to verify that if it has both a numeric
   133    136   ** representation and a string representation then the string rep has
   134    137   ** been derived from the numeric and not the other way around.  It returns
   135    138   ** true if everything is ok and false if there is a problem.
   136    139   **
   137    140   ** This routine is for use inside of assert() statements only.
   138    141   */
   139         -int sqlite3VdbeMemConsistentDualRep(Mem *p){
          142  +int sqlite3VdbeMemValidStrRep(Mem *p){
   140    143     char zBuf[100];
   141    144     char *z;
   142    145     int i, j, incr;
   143    146     if( (p->flags & MEM_Str)==0 ) return 1;
          147  +  if( p->flags & MEM_Term ){
          148  +    /* Insure that the string is properly zero-terminated.  Pay particular
          149  +    ** attention to the case where p->n is odd */
          150  +    if( p->z==p->zMalloc && p->szMalloc>0 ){
          151  +      assert( p->enc==SQLITE_UTF8 || p->szMalloc >= ((p->n+1)&~1)+2 );
          152  +      assert( p->enc!=SQLITE_UTF8 || p->szMalloc >= p->n+1 );
          153  +    }
          154  +    assert( p->z[p->n]==0 );
          155  +    assert( p->enc==SQLITE_UTF8 || p->z[(p->n+1)&~1]==0 );
          156  +    assert( p->enc==SQLITE_UTF8 || p->z[((p->n+1)&~1)+1]==0 );
          157  +  }
   144    158     if( (p->flags & (MEM_Int|MEM_Real|MEM_IntReal))==0 ) return 1;
   145    159     vdbeMemRenderNum(sizeof(zBuf), zBuf, p);
   146    160     z = p->z;
   147    161     i = j = 0;
   148    162     incr = 1;
   149    163     if( p->enc!=SQLITE_UTF8 ){
   150    164       incr = 2;
................................................................................
  1217   1231     }else{
  1218   1232       sqlite3VdbeMemStringify(pVal, enc, 0);
  1219   1233       assert( 0==(1&SQLITE_PTR_TO_INT(pVal->z)) );
  1220   1234     }
  1221   1235     assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || pVal->db==0
  1222   1236                 || pVal->db->mallocFailed );
  1223   1237     if( pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) ){
  1224         -    assert( sqlite3VdbeMemConsistentDualRep(pVal) );
         1238  +    assert( sqlite3VdbeMemValidStrRep(pVal) );
  1225   1239       return pVal->z;
  1226   1240     }else{
  1227   1241       return 0;
  1228   1242     }
  1229   1243   }
  1230   1244   
  1231   1245   /* This function is only available internally, it is not part of the
................................................................................
  1240   1254   */
  1241   1255   const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){
  1242   1256     if( !pVal ) return 0;
  1243   1257     assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) );
  1244   1258     assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) );
  1245   1259     assert( !sqlite3VdbeMemIsRowSet(pVal) );
  1246   1260     if( (pVal->flags&(MEM_Str|MEM_Term))==(MEM_Str|MEM_Term) && pVal->enc==enc ){
  1247         -    assert( sqlite3VdbeMemConsistentDualRep(pVal) );
         1261  +    assert( sqlite3VdbeMemValidStrRep(pVal) );
  1248   1262       return pVal->z;
  1249   1263     }
  1250   1264     if( pVal->flags&MEM_Null ){
  1251   1265       return 0;
  1252   1266     }
  1253   1267     return valueToText(pVal, enc);
  1254   1268   }