/ Check-in [23bf9f26]
Login

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

Overview
Comment:Fix the sqlite3_prepare() family of interfaces so that they zero the *ppStmt value even on an SQLITE_MISUSE return. Make it clear in the documentation that the ppStmt parameter cannot be zero. (CVS 6441)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 23bf9f266559603e37b2703715eaf8ef5af6bb17
User & Date: drh 2009-04-02 18:32:27
Context
2009-04-02
20:16
Make sure the VACUUM statement locks down the page_size and auto_vacuum modes after it runs. Otherwise, pragmas might change these settings on a populated database, resulting in problems. (CVS 6442) check-in: 85e6a474 user: drh tags: trunk
18:32
Fix the sqlite3_prepare() family of interfaces so that they zero the *ppStmt value even on an SQLITE_MISUSE return. Make it clear in the documentation that the ppStmt parameter cannot be zero. (CVS 6441) check-in: 23bf9f26 user: drh tags: trunk
18:28
Fix a problem causing the BtShared.isPending flag to be cleared to early. Also coverage improvements for btree.c. (CVS 6440) check-in: 8f142344 user: danielk1977 tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/prepare.c.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
524
525
526
527
528
529
530
531
532
533
534
535

536
537
538
539
540
541
542
...
667
668
669
670
671
672
673


674
675
676
677
678
679
680
...
769
770
771
772
773
774
775

776
777
778
779
780
781
782
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the implementation of the sqlite3_prepare()
** interface, and routines that contribute to loading the database schema
** from disk.
**
** $Id: prepare.c,v 1.115 2009/04/01 16:33:38 drh Exp $
*/
#include "sqliteInt.h"

/*
** Fill the InitData structure with an error message that indicates
** that the database is corrupt.
*/
................................................................................
  const char **pzTail       /* OUT: End of parsed string */
){
  Parse sParse;
  char *zErrMsg = 0;
  int rc = SQLITE_OK;
  int i;

  assert( ppStmt );
  *ppStmt = 0;
  if( sqlite3SafetyOn(db) ){
    return SQLITE_MISUSE;
  }

  assert( !db->mallocFailed );
  assert( sqlite3_mutex_held(db->mutex) );

  /* Check to verify that it is possible to get a read lock on all
  ** database schemas.  The inability to get a read lock indicates that
  ** some other database connection is holding a write-lock, which in
  ** turn means that the other connection has made uncommitted changes
................................................................................
  const char *zSql,         /* UTF-8 encoded SQL statement. */
  int nBytes,               /* Length of zSql in bytes. */
  int saveSqlFlag,          /* True to copy SQL text into the sqlite3_stmt */
  sqlite3_stmt **ppStmt,    /* OUT: A pointer to the prepared statement */
  const char **pzTail       /* OUT: End of parsed string */
){
  int rc;


  if( !sqlite3SafetyCheckOk(db) ){
    return SQLITE_MISUSE;
  }
  sqlite3_mutex_enter(db->mutex);
  sqlite3BtreeEnterAll(db);
  rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, ppStmt, pzTail);
  sqlite3BtreeLeaveAll(db);
................................................................................
  ** encoded string to UTF-8, then invoking sqlite3_prepare(). The
  ** tricky bit is figuring out the pointer to return in *pzTail.
  */
  char *zSql8;
  const char *zTail8 = 0;
  int rc = SQLITE_OK;


  *ppStmt = 0;
  if( !sqlite3SafetyCheckOk(db) ){
    return SQLITE_MISUSE;
  }
  sqlite3_mutex_enter(db->mutex);
  zSql8 = sqlite3Utf16to8(db, zSql, nBytes);
  if( zSql8 ){







|







 







<
<
|
<
<
>







 







>
>







 







>







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
524
525
526
527
528
529
530


531


532
533
534
535
536
537
538
539
...
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
...
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the implementation of the sqlite3_prepare()
** interface, and routines that contribute to loading the database schema
** from disk.
**
** $Id: prepare.c,v 1.116 2009/04/02 18:32:27 drh Exp $
*/
#include "sqliteInt.h"

/*
** Fill the InitData structure with an error message that indicates
** that the database is corrupt.
*/
................................................................................
  const char **pzTail       /* OUT: End of parsed string */
){
  Parse sParse;
  char *zErrMsg = 0;
  int rc = SQLITE_OK;
  int i;



  if( sqlite3SafetyOn(db) ) return SQLITE_MISUSE;


  assert( ppStmt && *ppStmt==0 );
  assert( !db->mallocFailed );
  assert( sqlite3_mutex_held(db->mutex) );

  /* Check to verify that it is possible to get a read lock on all
  ** database schemas.  The inability to get a read lock indicates that
  ** some other database connection is holding a write-lock, which in
  ** turn means that the other connection has made uncommitted changes
................................................................................
  const char *zSql,         /* UTF-8 encoded SQL statement. */
  int nBytes,               /* Length of zSql in bytes. */
  int saveSqlFlag,          /* True to copy SQL text into the sqlite3_stmt */
  sqlite3_stmt **ppStmt,    /* OUT: A pointer to the prepared statement */
  const char **pzTail       /* OUT: End of parsed string */
){
  int rc;
  assert( ppStmt!=0 );
  *ppStmt = 0;
  if( !sqlite3SafetyCheckOk(db) ){
    return SQLITE_MISUSE;
  }
  sqlite3_mutex_enter(db->mutex);
  sqlite3BtreeEnterAll(db);
  rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, ppStmt, pzTail);
  sqlite3BtreeLeaveAll(db);
................................................................................
  ** encoded string to UTF-8, then invoking sqlite3_prepare(). The
  ** tricky bit is figuring out the pointer to return in *pzTail.
  */
  char *zSql8;
  const char *zTail8 = 0;
  int rc = SQLITE_OK;

  assert( ppStmt );
  *ppStmt = 0;
  if( !sqlite3SafetyCheckOk(db) ){
    return SQLITE_MISUSE;
  }
  sqlite3_mutex_enter(db->mutex);
  zSql8 = sqlite3Utf16to8(db, zSql, nBytes);
  if( zSql8 ){

Changes to src/sqlite.h.in.

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
....
2225
2226
2227
2228
2229
2230
2231
2232

2233
2234
2235
2236
2237
2238
2239
....
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259

2260
2261
2262
2263
2264
2265
2266
** on how SQLite interfaces are suppose to operate.
**
** The name of this file under configuration management is "sqlite.h.in".
** The makefile makes some minor changes to this file (such as inserting
** the version number) and changes its name to "sqlite3.h" as
** part of the build process.
**
** @(#) $Id: sqlite.h.in,v 1.436 2009/03/20 13:15:30 drh Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** Make sure we can call this stuff from C++.
................................................................................
** CAPI3REF: Compiling An SQL Statement {H13010} <S10000>
** KEYWORDS: {SQL statement compiler}
**
** To execute an SQL query, it must first be compiled into a byte-code
** program using one of these routines.
**
** The first argument, "db", is a [database connection] obtained from a
** prior call to [sqlite3_open()], [sqlite3_open_v2()] or [sqlite3_open16()].

**
** The second argument, "zSql", is the statement to be compiled, encoded
** as either UTF-8 or UTF-16.  The sqlite3_prepare() and sqlite3_prepare_v2()
** interfaces use UTF-8, and sqlite3_prepare16() and sqlite3_prepare16_v2()
** use UTF-16.
**
** If the nByte argument is less than zero, then zSql is read up to the
................................................................................
** zSql string ends at either the first '\000' or '\u0000' character or
** the nByte-th byte, whichever comes first. If the caller knows
** that the supplied string is nul-terminated, then there is a small
** performance advantage to be gained by passing an nByte parameter that
** is equal to the number of bytes in the input string <i>including</i>
** the nul-terminator bytes.
**
** *pzTail is made to point to the first byte past the end of the
** first SQL statement in zSql.  These routines only compile the first
** statement in zSql, so *pzTail is left pointing to what remains
** uncompiled.
**
** *ppStmt is left pointing to a compiled [prepared statement] that can be
** executed using [sqlite3_step()].  If there is an error, *ppStmt is set
** to NULL.  If the input text contains no SQL (if the input is an empty
** string or a comment) then *ppStmt is set to NULL.
** {A13018} The calling procedure is responsible for deleting the compiled
** SQL statement using [sqlite3_finalize()] after it has finished with it.

**
** On success, [SQLITE_OK] is returned, otherwise an [error code] is returned.
**
** The sqlite3_prepare_v2() and sqlite3_prepare16_v2() interfaces are
** recommended for all new programs. The two older interfaces are retained
** for backwards compatibility, but their use is discouraged.
** In the "v2" interfaces, the prepared statement







|







 







|
>







 







|
|
|
|





|

>







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
....
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
....
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
** on how SQLite interfaces are suppose to operate.
**
** The name of this file under configuration management is "sqlite.h.in".
** The makefile makes some minor changes to this file (such as inserting
** the version number) and changes its name to "sqlite3.h" as
** part of the build process.
**
** @(#) $Id: sqlite.h.in,v 1.437 2009/04/02 18:32:27 drh Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** Make sure we can call this stuff from C++.
................................................................................
** CAPI3REF: Compiling An SQL Statement {H13010} <S10000>
** KEYWORDS: {SQL statement compiler}
**
** To execute an SQL query, it must first be compiled into a byte-code
** program using one of these routines.
**
** The first argument, "db", is a [database connection] obtained from a
** prior successful call to [sqlite3_open()], [sqlite3_open_v2()] or
** [sqlite3_open16()].  The database connection must not have been closed.
**
** The second argument, "zSql", is the statement to be compiled, encoded
** as either UTF-8 or UTF-16.  The sqlite3_prepare() and sqlite3_prepare_v2()
** interfaces use UTF-8, and sqlite3_prepare16() and sqlite3_prepare16_v2()
** use UTF-16.
**
** If the nByte argument is less than zero, then zSql is read up to the
................................................................................
** zSql string ends at either the first '\000' or '\u0000' character or
** the nByte-th byte, whichever comes first. If the caller knows
** that the supplied string is nul-terminated, then there is a small
** performance advantage to be gained by passing an nByte parameter that
** is equal to the number of bytes in the input string <i>including</i>
** the nul-terminator bytes.
**
** If pzTail is not NULL then *pzTail is made to point to the first byte
** past the end of the first SQL statement in zSql.  These routines only
** compile the first statement in zSql, so *pzTail is left pointing to
** what remains uncompiled.
**
** *ppStmt is left pointing to a compiled [prepared statement] that can be
** executed using [sqlite3_step()].  If there is an error, *ppStmt is set
** to NULL.  If the input text contains no SQL (if the input is an empty
** string or a comment) then *ppStmt is set to NULL.
** The calling procedure is responsible for deleting the compiled
** SQL statement using [sqlite3_finalize()] after it has finished with it.
** ppStmt may not be NULL.
**
** On success, [SQLITE_OK] is returned, otherwise an [error code] is returned.
**
** The sqlite3_prepare_v2() and sqlite3_prepare16_v2() interfaces are
** recommended for all new programs. The two older interfaces are retained
** for backwards compatibility, but their use is discouraged.
** In the "v2" interfaces, the prepared statement

Changes to src/test9.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
110
111
112
113
114
115
116

117
118
119
120
121
122
123
...
134
135
136
137
138
139
140

141
142
143
144
145

146

147
148
149
150
151

152
153

154
155
156
157
158


159
160
161
162
163

164
165
166
167
168
169
170
**
*************************************************************************
**
** This file contains obscure tests of the C-interface required
** for completeness. Test code is written in C for these cases
** as there is not much point in binding to Tcl.
**
** $Id: test9.c,v 1.6 2008/07/11 13:53:55 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>

/*
................................................................................
  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 */
){
  const char *zErrFunction = "N/A";
  sqlite3 *db = 0;

  int rc;

  if( objc!=1 ){
    Tcl_WrongNumArgs(interp, 1, objv, "");
    return TCL_ERROR;
  }

................................................................................

  rc = sqlite3_errcode(db);
  if( rc!=SQLITE_MISUSE ){
    zErrFunction = "sqlite3_errcode";
    goto error_out;
  }


  rc = sqlite3_prepare(db, 0, 0, 0, 0);
  if( rc!=SQLITE_MISUSE ){
    zErrFunction = "sqlite3_prepare";
    goto error_out;
  }



  rc = sqlite3_prepare_v2(db, 0, 0, 0, 0);
  if( rc!=SQLITE_MISUSE ){
    zErrFunction = "sqlite3_prepare_v2";
    goto error_out;
  }


#ifndef SQLITE_OMIT_UTF16

  rc = sqlite3_prepare16(db, 0, 0, 0, 0);
  if( rc!=SQLITE_MISUSE ){
    zErrFunction = "sqlite3_prepare16";
    goto error_out;
  }


  rc = sqlite3_prepare16_v2(db, 0, 0, 0, 0);
  if( rc!=SQLITE_MISUSE ){
    zErrFunction = "sqlite3_prepare16_v2";
    goto error_out;
  }

#endif

  return TCL_OK;

error_out:
  Tcl_ResetResult(interp);
  Tcl_AppendResult(interp, "Error testing function: ", zErrFunction, 0);







|







 







>







 







>
|




>

>
|




>


>
|




>
>
|




>







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
...
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
**
*************************************************************************
**
** This file contains obscure tests of the C-interface required
** for completeness. Test code is written in C for these cases
** as there is not much point in binding to Tcl.
**
** $Id: test9.c,v 1.7 2009/04/02 18:32:27 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>

/*
................................................................................
  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 */
){
  const char *zErrFunction = "N/A";
  sqlite3 *db = 0;
  sqlite3_stmt *pStmt;
  int rc;

  if( objc!=1 ){
    Tcl_WrongNumArgs(interp, 1, objv, "");
    return TCL_ERROR;
  }

................................................................................

  rc = sqlite3_errcode(db);
  if( rc!=SQLITE_MISUSE ){
    zErrFunction = "sqlite3_errcode";
    goto error_out;
  }

  pStmt = (sqlite3_stmt*)1234;
  rc = sqlite3_prepare(db, 0, 0, &pStmt, 0);
  if( rc!=SQLITE_MISUSE ){
    zErrFunction = "sqlite3_prepare";
    goto error_out;
  }
  assert( pStmt==0 ); /* Verify that pStmt is zeroed even on a MISUSE error */

  pStmt = (sqlite3_stmt*)1234;
  rc = sqlite3_prepare_v2(db, 0, 0, &pStmt, 0);
  if( rc!=SQLITE_MISUSE ){
    zErrFunction = "sqlite3_prepare_v2";
    goto error_out;
  }
  assert( pStmt==0 );

#ifndef SQLITE_OMIT_UTF16
  pStmt = (sqlite3_stmt*)1234;
  rc = sqlite3_prepare16(db, 0, 0, &pStmt, 0);
  if( rc!=SQLITE_MISUSE ){
    zErrFunction = "sqlite3_prepare16";
    goto error_out;
  }
  assert( pStmt==0 );
  pStmt = (sqlite3_stmt*)1234;
  rc = sqlite3_prepare16_v2(db, 0, 0, &pStmt, 0);
  if( rc!=SQLITE_MISUSE ){
    zErrFunction = "sqlite3_prepare16_v2";
    goto error_out;
  }
  assert( pStmt==0 );
#endif

  return TCL_OK;

error_out:
  Tcl_ResetResult(interp);
  Tcl_AppendResult(interp, "Error testing function: ", zErrFunction, 0);