Let me first say that we sometimes see databases that go corrupt.  I
haven't pinpointed the cause yet, but what I think I can describe, is a
possibly way that a corrupt database is causing sqlite to segfault.

I use a java wrapper for sqlite.  I've seen this exact segfault happen on
an older wrapper I used, and the current wrapper I use.  I have several
detailed java dumps if anyone wants to see them.

Here is what I've determined is happening.  Please look at the
function sqlite3VdbeRecordCompare.

  int d1;            /* Offset into aKey[] of next data element */
  u32 idx1;          /* Offset into aKey[] of next header element */
  u32 szHdr1;        /* Number of bytes in header */

...

  idx1 = getVarint32(aKey1, szHdr1);
  d1 = szHdr1;
  if( pPKey2->flags & UNPACKED_IGNORE_ROWID ){
    szHdr1--;
  }
  nField = pKeyInfo->nField;
  while( idx1<szHdr1 && i<pPKey2->nField ){
    u32 serial_type1;

    /* Read the serial types for the next element in each key. */
    idx1 += getVarint32( aKey1+idx1, serial_type1 );
    if( d1>=nKey1 && sqlite3VdbeSerialTypeLen(serial_type1)>0 ) break;

    /* Extract the values to be compared.
    */
    d1 += sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1);



Correct me if I'm wrong, but aKey is just a buffer directly read from the
database.  What's happening to me is that the getVarint32 that reads szHdr1
is reading a very large 32 bit value, >= 2^31, such as 0xbd21d318.  The
next line assigns it to d1, which is a signed integer, so d1 gets a
negative value.  Sqlite will then segfault inside of sqlite3VdbeSerialGet
when it tries to read from the bogus memory location &aKey1[d1].  I have no
idea if this impacts security of programs that read sqlite databases.

I realize that this function is a very high runner, so more sanity checking
might have a measurable performance impact.  But can d1 be unsigned to
prevent it from going negative?  Is d1 supposed to always be <nKey1 ?  It
sounds like the code should just break out of the loop whenever that's not
the case.  Sure, it won't be doing the correct thing, but at least it won't
segfault.

Does this make sense?  Maybe with some work, I can create a test database
to reproduce this.

Thanks,
Brian Vincent
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to