Fossil SCM

Fix an infinite recursion on db_err() that might occur if SQLite is unable to create the WAL file for a database due to lack of write permission on the containing directory.

drh 2017-12-13 19:16 trunk
Commit 421fe24138cd443b0059bb51baec08f4561a783f6f93ed2ec8ad9a17d2b85f4c
1 file changed +6
+6
--- src/db.c
+++ src/db.c
@@ -54,10 +54,11 @@
5454
struct Stmt {
5555
Blob sql; /* The SQL for this statement */
5656
sqlite3_stmt *pStmt; /* The results of sqlite3_prepare_v2() */
5757
Stmt *pNext, *pPrev; /* List of all unfinalized statements */
5858
int nStep; /* Number of sqlite3_step() calls */
59
+ int rc; /* Error from db_vprepare() */
5960
};
6061
6162
/*
6263
** Copy this to initialize a Stmt object to a clean/empty state. This
6364
** is useful to help avoid assertions when performing cleanup in some
@@ -69,13 +70,15 @@
6970
7071
/*
7172
** Call this routine when a database error occurs.
7273
*/
7374
static void db_err(const char *zFormat, ...){
75
+ static int rcLooping = 0;
7476
va_list ap;
7577
char *z;
7678
int rc = 1;
79
+ if( rcLooping ) exit(rcLooping);
7780
va_start(ap, zFormat);
7881
z = vmprintf(zFormat, ap);
7982
va_end(ap);
8083
#ifdef FOSSIL_ENABLE_JSON
8184
if( g.json.isJsonMode ){
@@ -97,10 +100,11 @@
97100
cgi_reply();
98101
}else{
99102
fprintf(stderr, "%s: %s\n", g.argv[0], z);
100103
}
101104
free(z);
105
+ rcLooping = rc;
102106
db_force_rollback();
103107
fossil_exit(rc);
104108
}
105109
106110
/*
@@ -273,10 +277,11 @@
273277
if( rc!=0 && (flags & DB_PREPARE_IGNORE_ERROR)!=0 ){
274278
db_err("%s\n%s", sqlite3_errmsg(g.db), zSql);
275279
}
276280
pStmt->pNext = pStmt->pPrev = 0;
277281
pStmt->nStep = 0;
282
+ pStmt->rc = rc;
278283
return rc;
279284
}
280285
int db_prepare(Stmt *pStmt, const char *zFormat, ...){
281286
int rc;
282287
va_list ap;
@@ -359,10 +364,11 @@
359364
** Step the SQL statement. Return either SQLITE_ROW or an error code
360365
** or SQLITE_OK if the statement finishes successfully.
361366
*/
362367
int db_step(Stmt *pStmt){
363368
int rc;
369
+ if( pStmt->pStmt==0 ) return pStmt->rc;
364370
rc = sqlite3_step(pStmt->pStmt);
365371
pStmt->nStep++;
366372
return rc;
367373
}
368374
369375
--- src/db.c
+++ src/db.c
@@ -54,10 +54,11 @@
54 struct Stmt {
55 Blob sql; /* The SQL for this statement */
56 sqlite3_stmt *pStmt; /* The results of sqlite3_prepare_v2() */
57 Stmt *pNext, *pPrev; /* List of all unfinalized statements */
58 int nStep; /* Number of sqlite3_step() calls */
 
59 };
60
61 /*
62 ** Copy this to initialize a Stmt object to a clean/empty state. This
63 ** is useful to help avoid assertions when performing cleanup in some
@@ -69,13 +70,15 @@
69
70 /*
71 ** Call this routine when a database error occurs.
72 */
73 static void db_err(const char *zFormat, ...){
 
74 va_list ap;
75 char *z;
76 int rc = 1;
 
77 va_start(ap, zFormat);
78 z = vmprintf(zFormat, ap);
79 va_end(ap);
80 #ifdef FOSSIL_ENABLE_JSON
81 if( g.json.isJsonMode ){
@@ -97,10 +100,11 @@
97 cgi_reply();
98 }else{
99 fprintf(stderr, "%s: %s\n", g.argv[0], z);
100 }
101 free(z);
 
102 db_force_rollback();
103 fossil_exit(rc);
104 }
105
106 /*
@@ -273,10 +277,11 @@
273 if( rc!=0 && (flags & DB_PREPARE_IGNORE_ERROR)!=0 ){
274 db_err("%s\n%s", sqlite3_errmsg(g.db), zSql);
275 }
276 pStmt->pNext = pStmt->pPrev = 0;
277 pStmt->nStep = 0;
 
278 return rc;
279 }
280 int db_prepare(Stmt *pStmt, const char *zFormat, ...){
281 int rc;
282 va_list ap;
@@ -359,10 +364,11 @@
359 ** Step the SQL statement. Return either SQLITE_ROW or an error code
360 ** or SQLITE_OK if the statement finishes successfully.
361 */
362 int db_step(Stmt *pStmt){
363 int rc;
 
364 rc = sqlite3_step(pStmt->pStmt);
365 pStmt->nStep++;
366 return rc;
367 }
368
369
--- src/db.c
+++ src/db.c
@@ -54,10 +54,11 @@
54 struct Stmt {
55 Blob sql; /* The SQL for this statement */
56 sqlite3_stmt *pStmt; /* The results of sqlite3_prepare_v2() */
57 Stmt *pNext, *pPrev; /* List of all unfinalized statements */
58 int nStep; /* Number of sqlite3_step() calls */
59 int rc; /* Error from db_vprepare() */
60 };
61
62 /*
63 ** Copy this to initialize a Stmt object to a clean/empty state. This
64 ** is useful to help avoid assertions when performing cleanup in some
@@ -69,13 +70,15 @@
70
71 /*
72 ** Call this routine when a database error occurs.
73 */
74 static void db_err(const char *zFormat, ...){
75 static int rcLooping = 0;
76 va_list ap;
77 char *z;
78 int rc = 1;
79 if( rcLooping ) exit(rcLooping);
80 va_start(ap, zFormat);
81 z = vmprintf(zFormat, ap);
82 va_end(ap);
83 #ifdef FOSSIL_ENABLE_JSON
84 if( g.json.isJsonMode ){
@@ -97,10 +100,11 @@
100 cgi_reply();
101 }else{
102 fprintf(stderr, "%s: %s\n", g.argv[0], z);
103 }
104 free(z);
105 rcLooping = rc;
106 db_force_rollback();
107 fossil_exit(rc);
108 }
109
110 /*
@@ -273,10 +277,11 @@
277 if( rc!=0 && (flags & DB_PREPARE_IGNORE_ERROR)!=0 ){
278 db_err("%s\n%s", sqlite3_errmsg(g.db), zSql);
279 }
280 pStmt->pNext = pStmt->pPrev = 0;
281 pStmt->nStep = 0;
282 pStmt->rc = rc;
283 return rc;
284 }
285 int db_prepare(Stmt *pStmt, const char *zFormat, ...){
286 int rc;
287 va_list ap;
@@ -359,10 +364,11 @@
364 ** Step the SQL statement. Return either SQLITE_ROW or an error code
365 ** or SQLITE_OK if the statement finishes successfully.
366 */
367 int db_step(Stmt *pStmt){
368 int rc;
369 if( pStmt->pStmt==0 ) return pStmt->rc;
370 rc = sqlite3_step(pStmt->pStmt);
371 pStmt->nStep++;
372 return rc;
373 }
374
375

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button