SQLite

Check-in [1a4eb3a3ef]
Login

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

Overview
Comment:Fix the wal-index header read routine so that it correctly detects a zero header as being malformed and in need of a wal-index rebuild.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 1a4eb3a3efe86c7caff4d9a5894953bce378f841
User & Date: drh 2010-05-21 13:16:19.000
Context
2010-05-21
15:31
Remove entries from wal-index hash tables when a rollback or savepoint rollback occurs. (check-in: 36795c2b23 user: dan tags: trunk)
13:16
Fix the wal-index header read routine so that it correctly detects a zero header as being malformed and in need of a wal-index rebuild. (check-in: 1a4eb3a3ef user: drh tags: trunk)
2010-05-20
23:51
Add a new xShmBarrier method to the VFS - a shared-memory fence operation. Implement the same in both unix and win32. Use it to make the WAL subsystem more robust. (check-in: 1bd011c9fe user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/wal.c.
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144





1145
1146
1147
1148
1149
1150
1151
1152


1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
** and *pChanged is set to 1.
**
** If the checksum cannot be verified return non-zero. If the header
** is read successfully and the checksum verified, return zero.
*/
int walIndexTryHdr(Wal *pWal, int *pChanged){
  u32 aCksum[2];               /* Checksum on the header content */
  WalIndexHdr hdr1, hdr2;      /* Two copies of the header content */
  WalIndexHdr *aHdr;           /* Header in shared memory */

  assert( pWal->pWiData );
  if( pWal->szWIndex==0 ){
    /* The wal-index is of size 0 bytes. This is handled in the same way
    ** as an invalid header. The caller will run recovery to construct
    ** a valid wal-index file before accessing the database.
    */
    return 1;
  }

  /* Read the header. The caller may or may not have an exclusive 
  ** (WRITE, PENDING, CHECKPOINT or RECOVER) lock on the wal-index
  ** file, meaning it is possible that an inconsistent snapshot is read
  ** from the file. If this happens, return non-zero.





  */
  aHdr = (WalIndexHdr*)pWal->pWiData;
  memcpy(&hdr1, &aHdr[0], sizeof(hdr1));
  sqlite3OsShmBarrier(pWal->pDbFd);
  memcpy(&hdr2, &aHdr[1], sizeof(hdr2));

  if( memcmp(&hdr1, &hdr2, sizeof(hdr1))!=0 ){
    /* Dirty read */


    return 1;
  }  
  walChecksumBytes((u8*)&hdr1, sizeof(hdr1)-sizeof(hdr1.aCksum), 0, aCksum);
  if( aCksum[0]!=hdr1.aCksum[0] || aCksum[1]!=hdr1.aCksum[1] ){
    /* Malformed header */
    return 1;
  }

  if( memcmp(&pWal->hdr, &hdr1, sizeof(WalIndexHdr)) ){
    *pChanged = 1;
    memcpy(&pWal->hdr, &hdr1, sizeof(WalIndexHdr));
    pWal->szPage = pWal->hdr.szPage;
  }

  /* The header was successfully read. Return zero. */
  return 0;
}








|















>
>
>
>
>


|

|

|
|
>
>
|
|
|
|
<
|


|

|







1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163

1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
** and *pChanged is set to 1.
**
** If the checksum cannot be verified return non-zero. If the header
** is read successfully and the checksum verified, return zero.
*/
int walIndexTryHdr(Wal *pWal, int *pChanged){
  u32 aCksum[2];               /* Checksum on the header content */
  WalIndexHdr h1, h2;          /* Two copies of the header content */
  WalIndexHdr *aHdr;           /* Header in shared memory */

  assert( pWal->pWiData );
  if( pWal->szWIndex==0 ){
    /* The wal-index is of size 0 bytes. This is handled in the same way
    ** as an invalid header. The caller will run recovery to construct
    ** a valid wal-index file before accessing the database.
    */
    return 1;
  }

  /* Read the header. The caller may or may not have an exclusive 
  ** (WRITE, PENDING, CHECKPOINT or RECOVER) lock on the wal-index
  ** file, meaning it is possible that an inconsistent snapshot is read
  ** from the file. If this happens, return non-zero.
  **
  ** There are two copies of the header at the beginning of the wal-index.
  ** When reading, read [0] first then [1].  Writes are in the reverse order.
  ** Memory barriers are used to prevent the compiler or the hardware from
  ** reordering the reads and writes.
  */
  aHdr = (WalIndexHdr*)pWal->pWiData;
  memcpy(&h1, &aHdr[0], sizeof(h1));
  sqlite3OsShmBarrier(pWal->pDbFd);
  memcpy(&h2, &aHdr[1], sizeof(h2));

  if( memcmp(&h1, &h2, sizeof(h1))!=0 ){
    return 1;   /* Dirty read */
  }  
  if( h1.szPage==0 ){
    return 1;   /* Malformed header - probably all zeros */
  }
  walChecksumBytes((u8*)&h1, sizeof(h1)-sizeof(h1.aCksum), 0, aCksum);
  if( aCksum[0]!=h1.aCksum[0] || aCksum[1]!=h1.aCksum[1] ){

    return 1;   /* Checksum does not match */
  }

  if( memcmp(&pWal->hdr, &h1, sizeof(WalIndexHdr)) ){
    *pChanged = 1;
    memcpy(&pWal->hdr, &h1, sizeof(WalIndexHdr));
    pWal->szPage = pWal->hdr.szPage;
  }

  /* The header was successfully read. Return zero. */
  return 0;
}