Index: ext/fts3/fts3.c ================================================================== --- ext/fts3/fts3.c +++ ext/fts3/fts3.c @@ -2578,10 +2578,12 @@ }else{ fts3PutDeltaVarint3(&p, bDescDoclist, &iPrev, &bFirstOut, i2); fts3PoslistCopy(&p, &p2); fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2); } + + assert( (p-aOut)<=((p1?(p1-a1):n1)+(p2?(p2-a2):n2)+FTS3_VARINT_MAX-1) ); } if( rc!=SQLITE_OK ){ sqlite3_free(aOut); p = aOut = 0; Index: src/test_hexio.c ================================================================== --- src/test_hexio.c +++ src/test_hexio.c @@ -335,10 +335,21 @@ x += y * (*q++); *v = (sqlite_int64) x; return (int) (q - (unsigned char *)p); } +static int putFts3Varint(char *p, sqlite_int64 v){ + unsigned char *q = (unsigned char *) p; + sqlite_uint64 vu = v; + do{ + *q++ = (unsigned char) ((vu & 0x7f) | 0x80); + vu >>= 7; + }while( vu!=0 ); + q[-1] &= 0x7f; /* turn off high bit in final byte */ + assert( q - (unsigned char *)p <= 10 ); + return (int) (q - (unsigned char *)p); +} /* ** USAGE: read_fts3varint BLOB VARNAME ** ** Read a varint from the start of BLOB. Set variable VARNAME to contain @@ -365,10 +376,72 @@ Tcl_ObjSetVar2(interp, objv[2], 0, Tcl_NewWideIntObj(iVal), 0); Tcl_SetObjResult(interp, Tcl_NewIntObj(nVal)); return TCL_OK; } +/* +** USAGE: make_fts3record ARGLIST +*/ +static int SQLITE_TCLAPI make_fts3record( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + Tcl_Obj **aArg = 0; + int nArg = 0; + unsigned char *aOut = 0; + int nOut = 0; + int nAlloc = 0; + int i; + int rc = TCL_OK; + + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "LIST"); + return TCL_ERROR; + } + if( Tcl_ListObjGetElements(interp, objv[1], &nArg, &aArg) ){ + return TCL_ERROR; + } + + for(i=0; inAlloc ){ + int nNew = nAlloc?nAlloc*2:128; + unsigned char *aNew = sqlite3_realloc(aOut, nNew); + if( aNew==0 ){ + sqlite3_free(aOut); + return TCL_ERROR; + } + aOut = aNew; + nAlloc = nNew; + } + nOut += putFts3Varint((char*)&aOut[nOut], iVal); + }else{ + int nVal = 0; + char *zVal = Tcl_GetStringFromObj(aArg[i], &nVal); + while( (nOut + nVal)>nAlloc ){ + int nNew = nAlloc?nAlloc*2:128; + unsigned char *aNew = sqlite3_realloc(aOut, nNew); + if( aNew==0 ){ + sqlite3_free(aOut); + return TCL_ERROR; + } + aOut = aNew; + nAlloc = nNew; + } + memcpy(&aOut[nOut], zVal, nVal); + nOut += nVal; + } + } + + Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(aOut, nOut)); + sqlite3_free(aOut); + return TCL_OK; +} + /* ** Register commands with the TCL interpreter. */ int Sqlitetest_hexio_Init(Tcl_Interp *interp){ @@ -381,12 +454,13 @@ { "hexio_get_int", hexio_get_int }, { "hexio_render_int16", hexio_render_int16 }, { "hexio_render_int32", hexio_render_int32 }, { "utf8_to_utf8", utf8_to_utf8 }, { "read_fts3varint", read_fts3varint }, + { "make_fts3record", make_fts3record }, }; int i; for(i=0; i