aboutsummaryrefslogtreecommitdiff
path: root/src/tclsqlite.c
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2004-08-26 00:56:05 +0000
committerdrh <drh@noemail.net>2004-08-26 00:56:05 +0000
commit1d895039e272bcef4aeaa1e9bbc480b3dbceef56 (patch)
tree5c05817d218362632b43d83da1987bfb3715d52d /src/tclsqlite.c
parent2c6674cf7edd7b8ee18c26176c24a14180401163 (diff)
downloadsqlite-1d895039e272bcef4aeaa1e9bbc480b3dbceef56.tar.gz
sqlite-1d895039e272bcef4aeaa1e9bbc480b3dbceef56.zip
Protect Tcl_Obj pointers from change using Tcl_IncrRefCount() while
executing SQL statements in the TCL bindings. (CVS 1903) FossilOrigin-Name: 6199f2f243514bbd4befbf768a7e03aec775bed2
Diffstat (limited to 'src/tclsqlite.c')
-rw-r--r--src/tclsqlite.c27
1 files changed, 25 insertions, 2 deletions
diff --git a/src/tclsqlite.c b/src/tclsqlite.c
index 8388495c3..8c91ccd10 100644
--- a/src/tclsqlite.c
+++ b/src/tclsqlite.c
@@ -11,7 +11,7 @@
*************************************************************************
** A TCL Interface to SQLite
**
-** $Id: tclsqlite.c,v 1.102 2004/08/25 04:07:02 drh Exp $
+** $Id: tclsqlite.c,v 1.103 2004/08/26 00:56:05 drh Exp $
*/
#ifndef NO_TCL /* Omit this whole file if TCL is unavailable */
@@ -698,6 +698,9 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
sqlite3_stmt *pStmt; /* Compiled SQL statment */
Tcl_Obj *pArray; /* Name of array into which results are written */
Tcl_Obj *pScript; /* Script to run for each result set */
+ Tcl_Obj **apParm; /* Parameters that need a Tcl_DecrRefCount() */
+ int nParm; /* Number of entries used in apParm[] */
+ Tcl_Obj *aParm[10]; /* Static space for apParm[] in the common case */
Tcl_Obj *pRet = Tcl_NewObj();
Tcl_IncrRefCount(pRet);
@@ -717,6 +720,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
pScript = objv[4];
}
+ Tcl_IncrRefCount(objv[2]);
zSql = Tcl_GetStringFromObj(objv[2], 0);
while( zSql[0] ){
int i; /* Loop counter */
@@ -741,8 +745,14 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
}
}
- /* Bind values to wildcards that begin with $ */
+ /* Bind values to wildcards that begin with $ or : */
nVar = sqlite3_bind_parameter_count(pStmt);
+ nParm = 0;
+ if( nVar>sizeof(aParm)/sizeof(aParm[0]) ){
+ apParm = (Tcl_Obj**)Tcl_Alloc(nVar*sizeof(apParm[0]));
+ }else{
+ apParm = aParm;
+ }
for(i=1; i<=nVar; i++){
const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
if( zVar[0]=='$' || zVar[0]==':' ){
@@ -755,6 +765,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
if( c=='b' && strcmp(zType,"bytearray")==0 ){
data = Tcl_GetByteArrayFromObj(pVar, &n);
sqlite3_bind_blob(pStmt, i, data, n, SQLITE_STATIC);
+ Tcl_IncrRefCount(pVar);
+ apParm[nParm++] = pVar;
}else if( (c=='b' && strcmp(zType,"boolean")==0) ||
(c=='i' && strcmp(zType,"int")==0) ){
Tcl_GetIntFromObj(interp, pVar, &n);
@@ -766,6 +778,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
}else{
data = Tcl_GetStringFromObj(pVar, &n);
sqlite3_bind_text(pStmt, i, data, n, SQLITE_STATIC);
+ Tcl_IncrRefCount(pVar);
+ apParm[nParm++] = pVar;
}
}
}
@@ -853,6 +867,14 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
Tcl_Free((char*)apColName);
}
+ /* Free the bound string and blob parameters */
+ for(i=0; i<nParm; i++){
+ Tcl_DecrRefCount(apParm[i]);
+ }
+ if( apParm!=aParm ){
+ Tcl_Free((char*)apParm);
+ }
+
/* Finalize the statement. If the result code is SQLITE_SCHEMA, then
** try again to execute the same statement
*/
@@ -868,6 +890,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
zSql = zLeft;
}
+ Tcl_DecrRefCount(objv[2]);
if( rc==TCL_OK ){
Tcl_SetObjResult(interp, pRet);