Fossil

Check-in [421fe241]
Login

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

Overview
Comment: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.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256:421fe24138cd443b0059bb51baec08f4561a783f6f93ed2ec8ad9a17d2b85f4c
User & Date: drh 2017-12-13 19:16:52
Context
2017-12-13
20:36
Improved error reporting when trying to write to a repository that is in a read-only directory. check-in: 500b0a2a user: drh tags: trunk
19:16
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. check-in: 421fe241 user: drh tags: trunk
17:17
Always generate timeline-data for a timeline even if the table has no check-ins and thus no graph. This causes the timeline-data scanner to continue looking for subsequent timelines. check-in: 3f316764 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/db.c.

52
53
54
55
56
57
58

59
60
61
62
63
64
65
..
67
68
69
70
71
72
73

74
75
76

77
78
79
80
81
82
83
..
95
96
97
98
99
100
101

102
103
104
105
106
107
108
...
271
272
273
274
275
276
277

278
279
280
281
282
283
284
...
357
358
359
360
361
362
363

364
365
366
367
368
369
370
** structure.
*/
struct Stmt {
  Blob sql;               /* The SQL for this statement */
  sqlite3_stmt *pStmt;    /* The results of sqlite3_prepare_v2() */
  Stmt *pNext, *pPrev;    /* List of all unfinalized statements */
  int nStep;              /* Number of sqlite3_step() calls */

};

/*
** Copy this to initialize a Stmt object to a clean/empty state. This
** is useful to help avoid assertions when performing cleanup in some
** error handling cases.
*/
................................................................................
#endif /* INTERFACE */
const struct Stmt empty_Stmt = empty_Stmt_m;

/*
** Call this routine when a database error occurs.
*/
static void db_err(const char *zFormat, ...){

  va_list ap;
  char *z;
  int rc = 1;

  va_start(ap, zFormat);
  z = vmprintf(zFormat, ap);
  va_end(ap);
#ifdef FOSSIL_ENABLE_JSON
  if( g.json.isJsonMode ){
    json_err( 0, z, 1 );
    if( g.isHTTP ){
................................................................................
    g.cgiOutput = 0;
    cgi_printf("<h1>Database Error</h1>\n<p>%h</p>\n", z);
    cgi_reply();
  }else{
    fprintf(stderr, "%s: %s\n", g.argv[0], z);
  }
  free(z);

  db_force_rollback();
  fossil_exit(rc);
}

/*
** All static variable that a used by only this file are gathered into
** the following structure.
................................................................................
  }
  rc = sqlite3_prepare_v3(g.db, zSql, -1, prepFlags, &pStmt->pStmt, 0);
  if( rc!=0 && (flags & DB_PREPARE_IGNORE_ERROR)!=0 ){
    db_err("%s\n%s", sqlite3_errmsg(g.db), zSql);
  }
  pStmt->pNext = pStmt->pPrev = 0;
  pStmt->nStep = 0;

  return rc;
}
int db_prepare(Stmt *pStmt, const char *zFormat, ...){
  int rc;
  va_list ap;
  va_start(ap, zFormat);
  rc = db_vprepare(pStmt, 0, zFormat, ap);
................................................................................

/*
** Step the SQL statement.  Return either SQLITE_ROW or an error code
** or SQLITE_OK if the statement finishes successfully.
*/
int db_step(Stmt *pStmt){
  int rc;

  rc = sqlite3_step(pStmt->pStmt);
  pStmt->nStep++;
  return rc;
}

/*
** Print warnings if a query is inefficient.







>







 







>



>







 







>







 







>







 







>







52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
..
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
..
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
...
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
...
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
** structure.
*/
struct Stmt {
  Blob sql;               /* The SQL for this statement */
  sqlite3_stmt *pStmt;    /* The results of sqlite3_prepare_v2() */
  Stmt *pNext, *pPrev;    /* List of all unfinalized statements */
  int nStep;              /* Number of sqlite3_step() calls */
  int rc;                 /* Error from db_vprepare() */
};

/*
** Copy this to initialize a Stmt object to a clean/empty state. This
** is useful to help avoid assertions when performing cleanup in some
** error handling cases.
*/
................................................................................
#endif /* INTERFACE */
const struct Stmt empty_Stmt = empty_Stmt_m;

/*
** Call this routine when a database error occurs.
*/
static void db_err(const char *zFormat, ...){
  static int rcLooping = 0;
  va_list ap;
  char *z;
  int rc = 1;
  if( rcLooping ) exit(rcLooping);
  va_start(ap, zFormat);
  z = vmprintf(zFormat, ap);
  va_end(ap);
#ifdef FOSSIL_ENABLE_JSON
  if( g.json.isJsonMode ){
    json_err( 0, z, 1 );
    if( g.isHTTP ){
................................................................................
    g.cgiOutput = 0;
    cgi_printf("<h1>Database Error</h1>\n<p>%h</p>\n", z);
    cgi_reply();
  }else{
    fprintf(stderr, "%s: %s\n", g.argv[0], z);
  }
  free(z);
  rcLooping = rc;
  db_force_rollback();
  fossil_exit(rc);
}

/*
** All static variable that a used by only this file are gathered into
** the following structure.
................................................................................
  }
  rc = sqlite3_prepare_v3(g.db, zSql, -1, prepFlags, &pStmt->pStmt, 0);
  if( rc!=0 && (flags & DB_PREPARE_IGNORE_ERROR)!=0 ){
    db_err("%s\n%s", sqlite3_errmsg(g.db), zSql);
  }
  pStmt->pNext = pStmt->pPrev = 0;
  pStmt->nStep = 0;
  pStmt->rc = rc;
  return rc;
}
int db_prepare(Stmt *pStmt, const char *zFormat, ...){
  int rc;
  va_list ap;
  va_start(ap, zFormat);
  rc = db_vprepare(pStmt, 0, zFormat, ap);
................................................................................

/*
** Step the SQL statement.  Return either SQLITE_ROW or an error code
** or SQLITE_OK if the statement finishes successfully.
*/
int db_step(Stmt *pStmt){
  int rc;
  if( pStmt->pStmt==0 ) return pStmt->rc;
  rc = sqlite3_step(pStmt->pStmt);
  pStmt->nStep++;
  return rc;
}

/*
** Print warnings if a query is inefficient.