/ Check-in [f21c6f13]
Login

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

Overview
Comment:Detect if two indexes of the same table share a common rootpage while parsing the schema, and throw an error immediately.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: f21c6f1343edc4ba68f9f8e68caac34da0d1c651526ecaf61c0e2d66593a555e
User & Date: drh 2019-01-30 18:33:33
Context
2019-01-30
18:47
Add test case for the previous commit. check-in: 197edb23 user: dan tags: trunk
18:33
Detect if two indexes of the same table share a common rootpage while parsing the schema, and throw an error immediately. check-in: f21c6f13 user: drh tags: trunk
16:58
Fix an off-by-one error when parsing the names of indexes that do not have arguments in the index_usage utility. check-in: dc794d8f user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/build.c.

  3493   3493           assert( p==pIndex );  /* Malloc must have failed */
  3494   3494           sqlite3OomFault(db);
  3495   3495           goto exit_create_index;
  3496   3496         }
  3497   3497         db->mDbFlags |= DBFLAG_SchemaChange;
  3498   3498         if( pTblName!=0 ){
  3499   3499           pIndex->tnum = db->init.newTnum;
         3500  +        if( sqlite3IndexHasDuplicateRootPage(pIndex) ){
         3501  +          sqlite3ErrorMsg(pParse, "invalid root page");
         3502  +          pParse->rc = SQLITE_CORRUPT_BKPT;
         3503  +          goto exit_create_index;
         3504  +        }
  3500   3505         }
  3501   3506       }
  3502   3507   
  3503   3508       /* If this is the initial CREATE INDEX statement (or CREATE TABLE if the
  3504   3509       ** index is an implied index for a UNIQUE or PRIMARY KEY constraint) then
  3505   3510       ** emit code to allocate the index rootpage on disk and make an entry for
  3506   3511       ** the index in the sqlite_master table and populate the index with

Changes to src/prepare.c.

    39     39       if( zObj==0 ) zObj = "?";
    40     40       z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj);
    41     41       if( zExtra && zExtra[0] ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra);
    42     42       *pData->pzErrMsg = z;
    43     43       pData->rc = SQLITE_CORRUPT_BKPT;
    44     44     }
    45     45   }
           46  +
           47  +/*
           48  +** Check to see if any sibling index (another index on the same table)
           49  +** of pIndex has the same root page number, and if it does, return true.
           50  +** This would indicate a corrupt schema.
           51  +*/
           52  +int sqlite3IndexHasDuplicateRootPage(Index *pIndex){
           53  +  Index *p;
           54  +  for(p=pIndex->pTable->pIndex; p; p=p->pNext){
           55  +    if( p->tnum==pIndex->tnum && p!=pIndex ) return 1;
           56  +  }
           57  +  return 0;
           58  +}
    46     59   
    47     60   /*
    48     61   ** This is the callback routine for the code that initializes the
    49     62   ** database.  See sqlite3Init() below for additional information.
    50     63   ** This routine is also called from the OP_ParseSchema opcode of the VDBE.
    51     64   **
    52     65   ** Each callback contains the following information:
................................................................................
   118    131       ** to do here is record the root page number for that index.
   119    132       */
   120    133       Index *pIndex;
   121    134       pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zDbSName);
   122    135       if( pIndex==0
   123    136        || sqlite3GetInt32(argv[1],&pIndex->tnum)==0
   124    137        || pIndex->tnum<2
          138  +     || sqlite3IndexHasDuplicateRootPage(pIndex)
   125    139       ){
   126    140         corruptSchema(pData, argv[0], pIndex?"invalid rootpage":"orphan index");
   127    141       }
   128    142     }
   129    143     return 0;
   130    144   }
   131    145   

Changes to src/sqliteInt.h.

  3840   3840   ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
  3841   3841   ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
  3842   3842   void sqlite3ExprListSetSortOrder(ExprList*,int);
  3843   3843   void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
  3844   3844   void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*);
  3845   3845   void sqlite3ExprListDelete(sqlite3*, ExprList*);
  3846   3846   u32 sqlite3ExprListFlags(const ExprList*);
         3847  +int sqlite3IndexHasDuplicateRootPage(Index*);
  3847   3848   int sqlite3Init(sqlite3*, char**);
  3848   3849   int sqlite3InitCallback(void*, int, char**, char**);
  3849   3850   int sqlite3InitOne(sqlite3*, int, char**, u32);
  3850   3851   void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
  3851   3852   #ifndef SQLITE_OMIT_VIRTUALTABLE
  3852   3853   Module *sqlite3PragmaVtabRegister(sqlite3*,const char *zName);
  3853   3854   #endif