/ Check-in [49aa3448]
Login

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

Overview
Comment:Give the SQLITE_TESTCTRL_PRNG_SEED two arguments. The second argument if not NULL is a pointer to a database connection which seeds the connection from its schema cookie. In this way, fuzzers can control the PRNG seed.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | prng-seed-test-control
Files: files | file ages | folders
SHA3-256: 49aa34480622cce4d7a72c59d9cfa8336886387acec8ee15b72f295ea1a52d8c
User & Date: drh 2019-08-03 01:39:20
Context
2019-08-03
01:40
Add the SQLITE_TESTCTRL_PRNG_SEED which can control the PRNG seed either directly or through the schema cookie of a supplied database connection. check-in: 2660e929 user: drh tags: trunk
01:39
Give the SQLITE_TESTCTRL_PRNG_SEED two arguments. The second argument if not NULL is a pointer to a database connection which seeds the connection from its schema cookie. In this way, fuzzers can control the PRNG seed. Closed-Leaf check-in: 49aa3448 user: drh tags: prng-seed-test-control
2019-08-02
21:03
Fixes to the PRNG_SEED pragma idea. check-in: c7109840 user: drh tags: prng-seed-test-control
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/btree.c.

6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
  u8 *pTmp = sqlite3PagerTempSpace(pPg->pBt->pPager);
  u8 *pData;
  int k;                          /* Current slot in pCArray->apEnd[] */
  u8 *pSrcEnd;                    /* Current pCArray->apEnd[k] value */

  assert( i<iEnd );
  j = get2byte(&aData[hdr+5]);
  if( NEVER(j>(u32)usableSize) ){ j = 0; }
  memcpy(&pTmp[j], &aData[j], usableSize - j);

  for(k=0; pCArray->ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
  pSrcEnd = pCArray->apEnd[k];

  pData = pEnd;
  while( 1/*exit by break*/ ){







|







6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
  u8 *pTmp = sqlite3PagerTempSpace(pPg->pBt->pPager);
  u8 *pData;
  int k;                          /* Current slot in pCArray->apEnd[] */
  u8 *pSrcEnd;                    /* Current pCArray->apEnd[k] value */

  assert( i<iEnd );
  j = get2byte(&aData[hdr+5]);
  if( j>(u32)usableSize ){ j = 0; }
  memcpy(&pTmp[j], &aData[j], usableSize - j);

  for(k=0; pCArray->ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
  pSrcEnd = pCArray->apEnd[k];

  pData = pEnd;
  while( 1/*exit by break*/ ){

Changes to src/main.c.

3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830















3831
3832





3833

3834
3835
3836
3837
3838
3839
3840
    ** this verb acts like PRNG_RESET.
    */
    case SQLITE_TESTCTRL_PRNG_RESTORE: {
      sqlite3PrngRestoreState();
      break;
    }

    /*  sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SEED, unsigned int);
    **
    ** Use the integer value as the seed for SQLite's internal PRNG.
    ** rather than the VFS xRandomness() function.















    */
    case SQLITE_TESTCTRL_PRNG_SEED: {





      sqlite3Config.iPrngSeed = va_arg(ap, unsigned int);

      break;
    }

    /*
    **  sqlite3_test_control(BITVEC_TEST, size, program)
    **
    ** Run a test against a Bitvec object of size.  The program argument







|

|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


>
>
>
>
>
|
>







3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
    ** this verb acts like PRNG_RESET.
    */
    case SQLITE_TESTCTRL_PRNG_RESTORE: {
      sqlite3PrngRestoreState();
      break;
    }

    /*  sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SEED, int x, sqlite3 *db);
    **
    ** Control the seed for the pseudo-random number generator (PRNG) that
    ** is built into SQLite.  Cases:
    **
    **    x!=0 && db!=0       Seed the PRNG to the current value of the
    **                        schema cookie in the main database for db, or
    **                        x if the schema cookie is zero.  This case
    **                        is convenient to use with database fuzzers
    **                        as it allows the fuzzer some control over the
    **                        the PRNG seed.
    **
    **    x!=0 && db==0       Seed the PRNG to the value of x.
    **
    **    x==0 && db==0       Revert to default behavior of using the
    **                        xRandomness method on the primary VFS.
    **
    ** This test-control also resets the PRNG so that the new seed will
    ** be used for the next call to sqlite3_randomness().
    */
    case SQLITE_TESTCTRL_PRNG_SEED: {
      int x = va_arg(ap, int);
      int y;
      sqlite3 *db = va_arg(ap, sqlite3*);
      assert( db==0 || db->aDb[0].pSchema!=0 );
      if( db && (y = db->aDb[0].pSchema->schema_cookie)!=0 ){ x = y; }
      sqlite3Config.iPrngSeed = x;
      sqlite3_randomness(0,0);
      break;
    }

    /*
    **  sqlite3_test_control(BITVEC_TEST, size, program)
    **
    ** Run a test against a Bitvec object of size.  The program argument

Changes to src/os.c.

256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){
  pVfs->xDlClose(pVfs, pHandle);
}
#endif /* SQLITE_OMIT_LOAD_EXTENSION */
int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
  if( sqlite3Config.iPrngSeed ){
    memset(zBufOut, 0, nByte);
    if( nByte>sizeof(unsigned) ) nByte = sizeof(unsigned int);
    memcpy(zBufOut, &sqlite3Config.iPrngSeed, nByte);
    return SQLITE_OK;
  }else{
    return pVfs->xRandomness(pVfs, nByte, zBufOut);
  }
  
}







|







256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){
  pVfs->xDlClose(pVfs, pHandle);
}
#endif /* SQLITE_OMIT_LOAD_EXTENSION */
int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
  if( sqlite3Config.iPrngSeed ){
    memset(zBufOut, 0, nByte);
    if( ALWAYS(nByte>sizeof(unsigned)) ) nByte = sizeof(unsigned int);
    memcpy(zBufOut, &sqlite3Config.iPrngSeed, nByte);
    return SQLITE_OK;
  }else{
    return pVfs->xRandomness(pVfs, nByte, zBufOut);
  }
  
}

Changes to src/shell.c.in.

9148
9149
9150
9151
9152
9153
9154
9155
9156
9157
9158
9159
9160
9161
9162
....
9223
9224
9225
9226
9227
9228
9229
9230
9231
9232
9233
9234
9235
9236

















9237
9238
9239
9240
9241
9242
9243
      { "optimizations",      SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK"       },
#ifdef YYCOVERAGE
      { "parser_coverage",    SQLITE_TESTCTRL_PARSER_COVERAGE, ""                 },
#endif
      { "pending_byte",       SQLITE_TESTCTRL_PENDING_BYTE,  "OFFSET  "           },
      { "prng_restore",       SQLITE_TESTCTRL_PRNG_RESTORE,  ""                   },
      { "prng_save",          SQLITE_TESTCTRL_PRNG_SAVE,     ""                   },
      { "prng_seed",          SQLITE_TESTCTRL_PRNG_SEED,     "SEED"               },
      { "reserve",            SQLITE_TESTCTRL_RESERVE,       "BYTES-OF-RESERVE"   },
    };
    int testctrl = -1;
    int iCtrl = -1;
    int rc2 = 0;    /* 0: usage.  1: %d  2: %x  3: no-output */
    int isOk = 0;
    int i, n2;
................................................................................
            rc2 = sqlite3_test_control(testctrl);
            isOk = testctrl==SQLITE_TESTCTRL_BYTEORDER ? 1 : 3;
          }
          break;

        /* sqlite3_test_control(int, uint) */
        case SQLITE_TESTCTRL_PENDING_BYTE:
        case SQLITE_TESTCTRL_PRNG_SEED:
          if( nArg==3 ){
            unsigned int opt = (unsigned int)integerValue(azArg[2]);
            rc2 = sqlite3_test_control(testctrl, opt);
            isOk = 3;
          }
          break;


















        /* sqlite3_test_control(int, int) */
        case SQLITE_TESTCTRL_ASSERT:
        case SQLITE_TESTCTRL_ALWAYS:
        case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
          if( nArg==3 ){
            int opt = booleanValue(azArg[2]);







|







 







<






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







9148
9149
9150
9151
9152
9153
9154
9155
9156
9157
9158
9159
9160
9161
9162
....
9223
9224
9225
9226
9227
9228
9229

9230
9231
9232
9233
9234
9235
9236
9237
9238
9239
9240
9241
9242
9243
9244
9245
9246
9247
9248
9249
9250
9251
9252
9253
9254
9255
9256
9257
9258
9259
      { "optimizations",      SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK"       },
#ifdef YYCOVERAGE
      { "parser_coverage",    SQLITE_TESTCTRL_PARSER_COVERAGE, ""                 },
#endif
      { "pending_byte",       SQLITE_TESTCTRL_PENDING_BYTE,  "OFFSET  "           },
      { "prng_restore",       SQLITE_TESTCTRL_PRNG_RESTORE,  ""                   },
      { "prng_save",          SQLITE_TESTCTRL_PRNG_SAVE,     ""                   },
      { "prng_seed",          SQLITE_TESTCTRL_PRNG_SEED,     "SEED ?db?"          },
      { "reserve",            SQLITE_TESTCTRL_RESERVE,       "BYTES-OF-RESERVE"   },
    };
    int testctrl = -1;
    int iCtrl = -1;
    int rc2 = 0;    /* 0: usage.  1: %d  2: %x  3: no-output */
    int isOk = 0;
    int i, n2;
................................................................................
            rc2 = sqlite3_test_control(testctrl);
            isOk = testctrl==SQLITE_TESTCTRL_BYTEORDER ? 1 : 3;
          }
          break;

        /* sqlite3_test_control(int, uint) */
        case SQLITE_TESTCTRL_PENDING_BYTE:

          if( nArg==3 ){
            unsigned int opt = (unsigned int)integerValue(azArg[2]);
            rc2 = sqlite3_test_control(testctrl, opt);
            isOk = 3;
          }
          break;

        /* sqlite3_test_control(int, int, sqlite3*) */
        case SQLITE_TESTCTRL_PRNG_SEED:
          if( nArg==3 || nArg==4 ){
            int i = (int)integerValue(azArg[2]);
            sqlite3 *db;
            if( nArg==3 ){
              db = 0;
            }else{
              db = p->db;
              /* Make sure the schema has been loaded */
              sqlite3_table_column_metadata(db, 0, "x", 0, 0, 0, 0, 0, 0);
            }
            rc2 = sqlite3_test_control(testctrl, i, db);
            isOk = 3;
          }
          break;

        /* sqlite3_test_control(int, int) */
        case SQLITE_TESTCTRL_ASSERT:
        case SQLITE_TESTCTRL_ALWAYS:
        case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
          if( nArg==3 ){
            int opt = booleanValue(azArg[2]);

Changes to src/test1.c.

6373
6374
6375
6376
6377
6378
6379
6380
6381
6382










6383
6384
6385
6386
6387
6388
6389
6390

6391
6392
6393
6394
6395



6396
6397
6398
6399
6400
6401
6402
6403
6404
  int objc,              /* Number of arguments */
  Tcl_Obj *CONST objv[]  /* Command arguments */
){
  sqlite3_randomness(0,0);
  return TCL_OK;
}
/*
** tclcmd:  prng_seed INT
**
** Establish TEXT as the seed for the PRNG










*/
static int SQLITE_TCLAPI prng_seed(
  ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int objc,              /* Number of arguments */
  Tcl_Obj *CONST objv[]  /* Command arguments */
){
  unsigned int i;

  if( objc!=2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "PRNG-SEED-TEXT");
    return TCL_ERROR;
  }
  if( Tcl_GetIntFromObj(interp,objv[0],&i) ) return TCL_ERROR;



  sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SEED, (unsigned int)i);
  sqlite3_randomness(0,0);
  return TCL_OK;
}

/*
** tclcmd:  database_may_be_corrupt
**
** Indicate that database files might be corrupt. In other words, set the normal







|

|
>
>
>
>
>
>
>
>
>
>







|
>
|
|



>
>
>
|
<







6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410

6411
6412
6413
6414
6415
6416
6417
  int objc,              /* Number of arguments */
  Tcl_Obj *CONST objv[]  /* Command arguments */
){
  sqlite3_randomness(0,0);
  return TCL_OK;
}
/*
** tclcmd:  prng_seed INT ?DB?
**
** Set up the SQLITE_TESTCTRL_PRNG_SEED pragma with parameter INT and DB.
** INT is an integer.  DB is a database connection, or a NULL pointer if
** omitted.
**
** When INT!=0 and DB!=0, set the PRNG seed to the value of the schema
** cookie for DB, or to INT if the schema cookie happens to be zero.
**
** When INT!=0 and DB==0, set the PRNG seed to just INT.
**
** If INT==0 and DB==0 then use the default procedure of calling the
** xRandomness method on the default VFS to get the PRNG seed.
*/
static int SQLITE_TCLAPI prng_seed(
  ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int objc,              /* Number of arguments */
  Tcl_Obj *CONST objv[]  /* Command arguments */
){
  int i = 0;
  sqlite3 *db = 0;
  if( objc!=2 && objc!=3 ){
    Tcl_WrongNumArgs(interp, 1, objv, "SEED ?DB?");
    return TCL_ERROR;
  }
  if( Tcl_GetIntFromObj(interp,objv[0],&i) ) return TCL_ERROR;
  if( objc==3 && getDbPointer(interp, Tcl_GetString(objv[2]), &db) ){
    return TCL_ERROR;
  }
  sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SEED, i, db);

  return TCL_OK;
}

/*
** tclcmd:  database_may_be_corrupt
**
** Indicate that database files might be corrupt. In other words, set the normal

Changes to test/dbfuzz2.c.

208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
  if( bVdbeDebug ){
    sqlite3_exec(db, "PRAGMA vdbe_debug=ON", 0, 0, 0);
  }
  if( mxCb>0 ){
    sqlite3_progress_handler(db, 10, progress_handler, 0);
  }
#ifdef SQLITE_TESTCTRL_PRNG_SEED
  sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SEED, 0);
  sqlite3_randomness(0,0);
#endif
  for(i=0; i<sizeof(azSql)/sizeof(azSql[0]); i++){
    if( eVerbosity>=1 ){
      printf("%s\n", azSql[i]);
      fflush(stdout);
    }
    zErr = 0;







|
<







208
209
210
211
212
213
214
215

216
217
218
219
220
221
222
  if( bVdbeDebug ){
    sqlite3_exec(db, "PRAGMA vdbe_debug=ON", 0, 0, 0);
  }
  if( mxCb>0 ){
    sqlite3_progress_handler(db, 10, progress_handler, 0);
  }
#ifdef SQLITE_TESTCTRL_PRNG_SEED
  sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SEED, 1, db);

#endif
  for(i=0; i<sizeof(azSql)/sizeof(azSql[0]); i++){
    if( eVerbosity>=1 ){
      printf("%s\n", azSql[i]);
      fflush(stdout);
    }
    zErr = 0;

Changes to test/fuzzcheck.c.

1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
          if( sqlFuzz || vdbeLimitFlag ){
            sqlite3_progress_handler(db, 100000, progressHandler,
                                     &vdbeLimitFlag);
          }
#endif
#ifdef SQLITE_TESTCTRL_PRNG_SEED
          sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SEED, 0);
          sqlite3_randomness(0,0);
#endif
          do{
            runSql(db, (char*)pSql->a, runFlags);
          }while( timeoutTest );
          setAlarm(0);
          sqlite3_exec(db, "PRAGMA temp_store_directory=''", 0, 0, 0);
          sqlite3_close(db);







|
<







1803
1804
1805
1806
1807
1808
1809
1810

1811
1812
1813
1814
1815
1816
1817
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
          if( sqlFuzz || vdbeLimitFlag ){
            sqlite3_progress_handler(db, 100000, progressHandler,
                                     &vdbeLimitFlag);
          }
#endif
#ifdef SQLITE_TESTCTRL_PRNG_SEED
          sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SEED, 1, db);

#endif
          do{
            runSql(db, (char*)pSql->a, runFlags);
          }while( timeoutTest );
          setAlarm(0);
          sqlite3_exec(db, "PRAGMA temp_store_directory=''", 0, 0, 0);
          sqlite3_close(db);