Fix some crashes in the sqlite3changeset_apply() function that could be caused

by corrupt changeset blobs.

FossilOrigin-Name: 745a9a7fef0f28a57ea3f44899058993f6ecdedda52c81a09a4a9ce09c9004d6
This commit is contained in:
dan
2018-03-01 12:05:51 +00:00
parent bda30ce4d8
commit dd8a4af8e7
4 changed files with 67 additions and 22 deletions
+25
View File
@@ -64,4 +64,29 @@ do_test 1.3 {
list [catch { sqlite3changeset_apply db $x xConflict } msg] $msg
} {1 SQLITE_CORRUPT}
#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.0 {
CREATE TABLE t1(a INTEGER PRIMARY KEY,b,c,d);
CREATE TABLE t2(e TEXT PRIMARY KEY NOT NULL,f,g);
CREATE TABLE t3(w REAL PRIMARY KEY NOT NULL,x,y);
CREATE TABLE t4(z PRIMARY KEY) WITHOUT ROWID;
}
foreach {tn blob} {
1 {54010174340012000000}
2 {54fefe8bcb0012000300}
3 {5480809280808001017434001200fb}
4 {50af9c939c9c9cb09c9c6400b09c9c6400}
5 {12000300}
6 {09847304}
7 {5401017434001208}
} {
if {$tn==7} breakpoint
do_test 2.$tn {
set changeset [binary decode hex $blob]
list [catch { sqlite3changeset_apply db $changeset xConflict } msg] $msg
} {1 SQLITE_CORRUPT}
}
finish_test
+33 -13
View File
@@ -2718,15 +2718,18 @@ static int sessionReadRecord(
for(i=0; i<nCol && rc==SQLITE_OK; i++){
int eType = 0; /* Type of value (SQLITE_NULL, TEXT etc.) */
if( abPK && abPK[i]==0 ) continue;
rc = sessionInputBuffer(pIn, 9);
if( pIn->iNext>=pIn->nData ){
rc = SQLITE_CORRUPT;
}else{
rc = sessionInputBuffer(pIn, 9);
}
if( rc==SQLITE_OK ){
eType = pIn->aData[pIn->iNext++];
}
assert( apOut[i]==0 );
if( eType ){
apOut[i] = sqlite3ValueNew(0);
if( !apOut[i] ) rc = SQLITE_NOMEM;
assert( apOut[i]==0 );
if( eType ){
apOut[i] = sqlite3ValueNew(0);
if( !apOut[i] ) rc = SQLITE_NOMEM;
}
}
if( rc==SQLITE_OK ){
@@ -2857,11 +2860,15 @@ static int sessionChangesetReadTblhdr(sqlite3_changeset_iter *p){
int nByte;
int nVarint;
nVarint = sessionVarintGet(&p->in.aData[p->in.iNext], &p->nCol);
nCopy -= nVarint;
p->in.iNext += nVarint;
nByte = p->nCol * sizeof(sqlite3_value*) * 2 + nCopy;
p->tblhdr.nBuf = 0;
sessionBufferGrow(&p->tblhdr, nByte, &rc);
if( p->nCol>0 ){
nCopy -= nVarint;
p->in.iNext += nVarint;
nByte = p->nCol * sizeof(sqlite3_value*) * 2 + nCopy;
p->tblhdr.nBuf = 0;
sessionBufferGrow(&p->tblhdr, nByte, &rc);
}else{
rc = SQLITE_CORRUPT;
}
}
if( rc==SQLITE_OK ){
@@ -2939,6 +2946,13 @@ static int sessionChangesetNext(
op = p->in.aData[p->in.iNext++];
}
if( p->zTab==0 ){
/* The first record in the changeset is not a table header. Must be a
** corrupt changeset. */
assert( p->in.iNext==1 );
return (p->rc = SQLITE_CORRUPT_BKPT);
}
p->op = op;
p->bIndirect = p->in.aData[p->in.iNext++];
if( p->op!=SQLITE_UPDATE && p->op!=SQLITE_DELETE && p->op!=SQLITE_INSERT ){
@@ -3708,7 +3722,13 @@ static int sessionBindRow(
if( !abPK || abPK[i] ){
sqlite3_value *pVal;
(void)xValue(pIter, i, &pVal);
rc = sessionBindValue(pStmt, i+1, pVal);
if( pVal==0 ){
/* The value in the changeset was "undefined". This indicates a
** corrupt changeset blob. */
rc = SQLITE_CORRUPT;
}else{
rc = sessionBindValue(pStmt, i+1, pVal);
}
}
}
return rc;