/ Check-in [57ffa07e]
Login

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

Overview
Comment:Enhance the showdb tool to show a btree page layout. Add limit checks so that overflow content does not overflow the buffer.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 57ffa07e26a26d2f4527c8e6d7a9c1f48f380bf7
User & Date: drh 2011-01-06 01:26:38
Context
2011-01-06
15:51
Enhance the showdb tool to show overflow page pointers at the end of overflow cells. check-in: cda5eab1 user: drh tags: trunk
01:26
Enhance the showdb tool to show a btree page layout. Add limit checks so that overflow content does not overflow the buffer. check-in: 57ffa07e user: drh tags: trunk
2011-01-05
21:46
Fix a bug in the showdb utility: the serial types for BLOB and TEXT where reversed. check-in: 65a13faf user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to tool/showdb.c.

    53     53   ** Read content from the file.
    54     54   **
    55     55   ** Space to hold the content is obtained from malloc() and needs to be
    56     56   ** freed by the caller.
    57     57   */
    58     58   static unsigned char *getContent(int ofst, int nByte){
    59     59     unsigned char *aData;
    60         -  aData = malloc(nByte);
           60  +  aData = malloc(nByte+32);
    61     61     if( aData==0 ) out_of_memory();
    62     62     lseek(db, ofst, SEEK_SET);
    63     63     read(db, aData, nByte);
    64     64     return aData;
    65     65   }
    66     66   
    67     67   /*
................................................................................
   180    180     print_decode_line(aData, 96, 4, "SQLite version number");
   181    181   }
   182    182   
   183    183   /*
   184    184   ** Describe cell content.
   185    185   */
   186    186   static int describeContent(
   187         -  unsigned char *a,
   188         -  char *zDesc
          187  +  unsigned char *a,       /* Cell content */
          188  +  int nLocal,             /* Bytes in a[] */
          189  +  char *zDesc             /* Write description here */
   189    190   ){
   190    191     int nDesc = 0;
   191    192     int n, i, j;
   192    193     i64 x, v;
   193    194     const unsigned char *pData;
          195  +  const unsigned char *pLimit;
   194    196     char sep = ' ';
   195    197   
          198  +  pLimit = &a[nLocal];
   196    199     n = decodeVarint(a, &x);
   197    200     pData = &a[x];
   198    201     a += n;
   199    202     i = x - n;
   200         -  while( i>0 ){
          203  +  while( i>0 && pData<=pLimit ){
   201    204       n = decodeVarint(a, &x);
   202    205       a += n;
   203    206       i -= n;
          207  +    nLocal -= n;
   204    208       zDesc[0] = sep;
   205    209       sep = ',';
   206    210       nDesc++;
   207    211       zDesc++;
   208    212       if( x==0 ){
   209         -      sprintf(zDesc, "null");
          213  +      sprintf(zDesc, "*");     /* NULL is a "*" */
   210    214       }else if( x>=1 && x<=6 ){
   211    215         v = (signed char)pData[0];
   212    216         pData++;
   213    217         switch( x ){
   214    218           case 6:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
   215    219           case 5:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
   216    220           case 4:  v = (v<<8) + pData[0];  pData++;
................................................................................
   226    230       }else if( x==9 ){
   227    231         sprintf(zDesc, "1");
   228    232       }else if( x>=12 ){
   229    233         int size = (x-12)/2;
   230    234         if( (x&1)==0 ){
   231    235           sprintf(zDesc, "blob(%d)", size);
   232    236         }else{
   233         -        sprintf(zDesc, "text(%d)", size);
          237  +        sprintf(zDesc, "txt(%d)", size);
   234    238         }
   235    239         pData += size;
   236    240       }
   237    241       j = strlen(zDesc);
   238    242       zDesc += j;
   239    243       nDesc += j;
   240    244     }
   241    245     return nDesc;
   242    246   }
          247  +
          248  +/*
          249  +** Compute the local payload size given the total payload size and
          250  +** the page size.
          251  +*/
          252  +static int localPayload(i64 nPayload, char cType){
          253  +  int maxLocal;
          254  +  int minLocal;
          255  +  int surplus;
          256  +  int nLocal;
          257  +  if( cType==13 ){
          258  +    /* Table leaf */
          259  +    maxLocal = pagesize-35;
          260  +    minLocal = (pagesize-12)*32/255-23;
          261  +  }else{
          262  +    maxLocal = (pagesize-12)*64/255-23;
          263  +    minLocal = (pagesize-12)*32/255-23;
          264  +  }
          265  +  if( nPayload>maxLocal ){
          266  +    surplus = minLocal + (nPayload-minLocal)%(pagesize-4);
          267  +    if( surplus<=maxLocal ){
          268  +      nLocal = surplus;
          269  +    }else{
          270  +      nLocal = minLocal;
          271  +    }
          272  +  }else{
          273  +    nLocal = nPayload;
          274  +  }
          275  +  return nLocal;
          276  +}
   243    277     
   244    278   
   245    279   /*
   246    280   ** Create a description for a single cell.
          281  +**
          282  +** The return value is the local cell size.
   247    283   */
   248    284   static int describeCell(
   249    285     unsigned char cType,    /* Page type */
   250    286     unsigned char *a,       /* Cell content */
   251    287     int showCellContent,    /* Show cell content if true */
   252    288     char **pzDesc           /* Store description here */
   253    289   ){
................................................................................
   269    305     }
   270    306     if( cType!=5 ){
   271    307       i = decodeVarint(a, &nPayload);
   272    308       a += i;
   273    309       n += i;
   274    310       sprintf(&zDesc[nDesc], "n: %lld ", nPayload);
   275    311       nDesc += strlen(&zDesc[nDesc]);
          312  +    nLocal = localPayload(nPayload, cType);
          313  +  }else{
          314  +    nPayload = nLocal = 0;
   276    315     }
   277    316     if( cType==5 || cType==13 ){
   278    317       i = decodeVarint(a, &rowid);
   279    318       a += i;
   280    319       n += i;
   281    320       sprintf(&zDesc[nDesc], "r: %lld ", rowid);
   282    321       nDesc += strlen(&zDesc[nDesc]);
   283    322     }
   284    323     if( showCellContent && cType!=5 ){
   285         -    nDesc += describeContent(a, &zDesc[nDesc]);
          324  +    nDesc += describeContent(a, nLocal, &zDesc[nDesc-1]);
   286    325     }
   287    326     *pzDesc = zDesc;
   288         -  return n;
          327  +  return nLocal+n;
   289    328   }
   290    329   
   291    330   /*
   292    331   ** Decode a btree page
   293    332   */
   294    333   static void decode_btree_page(
   295    334     unsigned char *a,   /* Page content */
   296    335     int pgno,           /* Page number */
   297    336     int hdrSize,        /* Size of the page header.  0 or 100 */
   298    337     char *zArgs         /* Flags to control formatting */
   299    338   ){
   300    339     const char *zType = "unknown";
   301    340     int nCell;
   302         -  int i;
          341  +  int i, j;
   303    342     int iCellPtr;
   304    343     int showCellContent = 0;
          344  +  int showMap = 0;
          345  +  char *zMap = 0;
   305    346     switch( a[0] ){
   306    347       case 2:  zType = "index interior node";  break;
   307    348       case 5:  zType = "table interior node";  break;
   308    349       case 10: zType = "index leaf";           break;
   309    350       case 13: zType = "table leaf";           break;
   310    351     }
   311    352     while( zArgs[0] ){
   312    353       switch( zArgs[0] ){
   313    354         case 'c': showCellContent = 1;  break;
          355  +      case 'm': showMap = 1;          break;
   314    356       }
   315    357       zArgs++;
   316    358     }
   317    359     printf("Decode of btree page %d:\n", pgno);
   318    360     print_decode_line(a, 0, 1, zType);
   319    361     print_decode_line(a, 1, 2, "Offset to first freeblock");
   320    362     print_decode_line(a, 3, 2, "Number of cells on this page");
   321    363     nCell = a[3]*256 + a[4];
   322    364     print_decode_line(a, 5, 2, "Offset to cell content area");
   323    365     print_decode_line(a, 7, 1, "Fragmented byte count");
   324         -  if( nCell>0 ){
   325         -    printf(" key: lx=left-child n=payload-size r=rowid\n");
   326         -  }
   327    366     if( a[0]==2 || a[0]==5 ){
   328    367       print_decode_line(a, 8, 4, "Right child");
   329    368       iCellPtr = 12;
   330    369     }else{
   331    370       iCellPtr = 8;
   332    371     }
          372  +  if( nCell>0 ){
          373  +    printf(" key: lx=left-child n=payload-size r=rowid\n");
          374  +  }
          375  +  if( showMap ){
          376  +    zMap = malloc(pagesize);
          377  +    memset(zMap, '.', pagesize);
          378  +    memset(zMap, '1', hdrSize);
          379  +    memset(&zMap[hdrSize], 'H', iCellPtr);
          380  +    memset(&zMap[hdrSize+iCellPtr], 'P', 2*nCell);
          381  +  }
   333    382     for(i=0; i<nCell; i++){
   334    383       int cofst = iCellPtr + i*2;
   335    384       char *zDesc;
          385  +    int n;
          386  +
   336    387       cofst = a[cofst]*256 + a[cofst+1];
   337         -    describeCell(a[0], &a[cofst-hdrSize], showCellContent, &zDesc);
          388  +    n = describeCell(a[0], &a[cofst-hdrSize], showCellContent, &zDesc);
          389  +    if( showMap ){
          390  +      char zBuf[30];
          391  +      memset(&zMap[cofst], '*', n);
          392  +      zMap[cofst] = '[';
          393  +      zMap[cofst+n-1] = ']';
          394  +      sprintf(zBuf, "%d", i);
          395  +      j = strlen(zBuf);
          396  +      if( j<=n-2 ) memcpy(&zMap[cofst+1], zBuf, j);
          397  +    }
   338    398       printf(" %03x: cell[%d] %s\n", cofst, i, zDesc);
   339    399     }
          400  +  if( showMap ){
          401  +    for(i=0; i<pagesize; i+=64){
          402  +      printf(" %03x: %.64s\n", i, &zMap[i]);
          403  +    }
          404  +    free(zMap);
          405  +  }  
   340    406   }
   341    407   
   342    408   /*
   343    409   ** Decode a freelist trunk page.
   344    410   */
   345    411   static void decode_trunk_page(
   346    412     int pgno,             /* The page number */
................................................................................
   382    448     fprintf(stderr, "Usage %s FILENAME ?args...?\n\n", argv0);
   383    449     fprintf(stderr,
   384    450       "args:\n"
   385    451       "    dbheader        Show database header\n"
   386    452       "    NNN..MMM        Show hex of pages NNN through MMM\n"
   387    453       "    NNN..end        Show hex of pages NNN through end of file\n"
   388    454       "    NNNb            Decode btree page NNN\n"
          455  +    "    NNNbc           Decode btree page NNN and show content\n"
          456  +    "    NNNbm           Decode btree page NNN and show a layout map\n"
   389    457       "    NNNt            Decode freelist trunk page NNN\n"
   390    458       "    NNNtd           Show leave freelist pages on the decode\n"
   391    459       "    NNNtr           Recurisvely decode freelist starting at NNN\n"
   392    460     );
   393    461   }
   394    462   
   395    463   int main(int argc, char **argv){