Fossil SCM

Strengthen the codecheck1.c utility program to help find cases where query parameters are used in unsafe ways. No unsafe usage of query parameters was detected in the current code.

drh 2018-06-21 16:40 trunk
Commit bb9233a61a83ebae4e4bd723f65c85608644ee6637c298d42c673a0252ccb228
+108 -49
--- src/codecheck1.c
+++ src/codecheck1.c
@@ -39,10 +39,15 @@
3939
#include <stdlib.h>
4040
#include <ctype.h>
4141
#include <string.h>
4242
#include <assert.h>
4343
44
+/*
45
+** Debugging switch
46
+*/
47
+static int eVerbose = 0;
48
+
4449
/*
4550
** Malloc, aborting if it fails.
4651
*/
4752
void *safe_malloc(int nByte){
4853
void *x = malloc(nByte);
@@ -198,10 +203,32 @@
198203
*/
199204
static const char *skip_space(const char *z){
200205
while( isspace(z[0]) ){ z++; }
201206
return z;
202207
}
208
+
209
+/*
210
+** Remove excess whitespace and nested "()" from string z.
211
+*/
212
+static char *simplify_expr(char *z){
213
+ int n = (int)strlen(z);
214
+ while( n>0 ){
215
+ if( isspace(z[0]) ){
216
+ z++;
217
+ n--;
218
+ continue;
219
+ }
220
+ if( z[0]=='(' && z[n-1]==')' ){
221
+ z++;
222
+ n -= 2;
223
+ continue;
224
+ }
225
+ break;
226
+ }
227
+ z[n] = 0;
228
+ return z;
229
+}
203230
204231
/*
205232
** Return true if the input is a string literal.
206233
*/
207234
static int is_string_lit(const char *z){
@@ -268,11 +295,11 @@
268295
269296
/*
270297
** Return true if the input is an argument that is safe to use with %s
271298
** while building an SQL statement.
272299
*/
273
-static int is_s_safe(const char *z){
300
+static int is_sql_safe(const char *z){
274301
int len, eType;
275302
int i;
276303
277304
/* A string literal is safe for use with %s */
278305
if( is_string_lit(z) ) return 1;
@@ -297,15 +324,29 @@
297324
** let it through */
298325
if( strstr(z, "/*safe-for-%s*/")!=0 ) return 1;
299326
300327
return 0;
301328
}
329
+
330
+/*
331
+** Return true if the input is an argument that is never safe for use
332
+** with %s.
333
+*/
334
+static int never_safe(const char *z){
335
+ if( strstr(z,"/*safe-for-%s*/")!=0 ) return 0;
336
+ if( z[0]=='P' ) return 1; /* CGI macros like P() and PD() */
337
+ if( strncmp(z,"cgi_param",9)==0 ) return 1;
338
+ return 0;
339
+}
302340
303341
/*
304342
** Processing flags
305343
*/
306
-#define FMT_NO_S 0x00001 /* Do not allow %s substitutions */
344
+#define FMT_SQL 0x00001 /* Generates SQL text */
345
+#define FMT_HTML 0x00002 /* Generates HTML text */
346
+#define FMT_URL 0x00004 /* Generates URLs */
347
+#define FMT_SAFE 0x00008 /* Always safe for %s */
307348
308349
/*
309350
** A list of internal Fossil interfaces that take a printf-style format
310351
** string.
311352
*/
@@ -313,55 +354,55 @@
313354
const char *zFName; /* Name of the function */
314355
int iFmtArg; /* Index of format argument. Leftmost is 1. */
315356
unsigned fmtFlags; /* Processing flags */
316357
} aFmtFunc[] = {
317358
{ "admin_log", 1, 0 },
318
- { "blob_append_sql", 2, FMT_NO_S },
359
+ { "blob_append_sql", 2, FMT_SQL },
319360
{ "blob_appendf", 2, 0 },
320
- { "cgi_debug", 1, 0 },
321
- { "cgi_panic", 1, 0 },
322
- { "cgi_printf", 1, 0 },
323
- { "cgi_redirectf", 1, 0 },
324
- { "chref", 2, 0 },
325
- { "db_blob", 2, FMT_NO_S },
326
- { "db_debug", 1, FMT_NO_S },
327
- { "db_double", 2, FMT_NO_S },
361
+ { "cgi_debug", 1, FMT_SAFE },
362
+ { "cgi_panic", 1, FMT_SAFE },
363
+ { "cgi_printf", 1, FMT_HTML },
364
+ { "cgi_redirectf", 1, FMT_URL },
365
+ { "chref", 2, FMT_URL },
366
+ { "db_blob", 2, FMT_SQL },
367
+ { "db_debug", 1, FMT_SQL },
368
+ { "db_double", 2, FMT_SQL },
328369
{ "db_err", 1, 0 },
329
- { "db_exists", 1, FMT_NO_S },
370
+ { "db_exists", 1, FMT_SQL },
330371
{ "db_get_mprintf", 2, 0 },
331
- { "db_int", 2, FMT_NO_S },
332
- { "db_int64", 2, FMT_NO_S },
333
- { "db_multi_exec", 1, FMT_NO_S },
334
- { "db_optional_sql", 2, FMT_NO_S },
335
- { "db_prepare", 2, FMT_NO_S },
336
- { "db_prepare_ignore_error", 2, FMT_NO_S },
372
+ { "db_int", 2, FMT_SQL },
373
+ { "db_int64", 2, FMT_SQL },
374
+ { "db_multi_exec", 1, FMT_SQL },
375
+ { "db_optional_sql", 2, FMT_SQL },
376
+ { "db_prepare", 2, FMT_SQL },
377
+ { "db_prepare_ignore_error", 2, FMT_SQL },
337378
{ "db_set_mprintf", 3, 0 },
338
- { "db_static_prepare", 2, FMT_NO_S },
339
- { "db_text", 2, FMT_NO_S },
379
+ { "db_static_prepare", 2, FMT_SQL },
380
+ { "db_text", 2, FMT_SQL },
340381
{ "db_unset_mprintf", 2, 0 },
341
- { "form_begin", 2, 0 },
342
- { "fossil_error", 2, 0 },
343
- { "fossil_errorlog", 1, 0 },
344
- { "fossil_fatal", 1, 0 },
345
- { "fossil_fatal_recursive", 1, 0 },
346
- { "fossil_panic", 1, 0 },
347
- { "fossil_print", 1, 0 },
348
- { "fossil_trace", 1, 0 },
349
- { "fossil_warning", 1, 0 },
350
- { "href", 1, 0 },
382
+ { "form_begin", 2, FMT_URL },
383
+ { "fossil_error", 2, FMT_SAFE },
384
+ { "fossil_errorlog", 1, FMT_SAFE },
385
+ { "fossil_fatal", 1, FMT_SAFE },
386
+ { "fossil_fatal_recursive", 1, FMT_SAFE },
387
+ { "fossil_panic", 1, FMT_SAFE },
388
+ { "fossil_print", 1, FMT_SAFE },
389
+ { "fossil_trace", 1, FMT_SAFE },
390
+ { "fossil_warning", 1, FMT_SAFE },
391
+ { "href", 1, FMT_URL },
351392
{ "json_new_string_f", 1, 0 },
352393
{ "json_set_err", 2, 0 },
353394
{ "json_warn", 2, 0 },
354395
{ "mprintf", 1, 0 },
355396
{ "socket_set_errmsg", 1, 0 },
356397
{ "ssl_set_errmsg", 1, 0 },
357
- { "style_header", 1, 0 },
358
- { "style_set_current_page", 1, 0 },
359
- { "style_submenu_element", 2, 0 },
360
- { "style_submenu_sql", 3, 0 },
361
- { "webpage_error", 1, 0 },
362
- { "xhref", 2, 0 },
398
+ { "style_header", 1, FMT_HTML },
399
+ { "style_set_current_page", 1, FMT_URL },
400
+ { "style_submenu_element", 2, FMT_URL },
401
+ { "style_submenu_sql", 3, FMT_SQL },
402
+ { "webpage_error", 1, FMT_SAFE },
403
+ { "xhref", 2, FMT_URL },
363404
};
364405
365406
/*
366407
** Determine if the indentifier zIdent of length nIndent is a Fossil
367408
** internal interface that uses a printf-style argument. Return zero if not.
@@ -464,16 +505,17 @@
464505
zCopy[len] = 0;
465506
azArg = 0;
466507
nArg = 0;
467508
z = zCopy;
468509
while( z[0] ){
510
+ char cEnd;
469511
len = distance_to(z, ',');
470
- azArg = safe_realloc((char*)azArg, (sizeof(azArg[0])+1)*(nArg+1));
471
- azArg[nArg++] = skip_space(z);
472
- if( z[len]==0 ) break;
512
+ cEnd = z[len];
473513
z[len] = 0;
474
- for(i=len-1; i>0 && isspace(z[i]); i--){ z[i] = 0; }
514
+ azArg = safe_realloc((char*)azArg, (sizeof(azArg[0])+1)*(nArg+1));
515
+ azArg[nArg++] = simplify_expr(z);
516
+ if( cEnd==0 ) break;
475517
z += len + 1;
476518
}
477519
acType = (char*)&azArg[nArg];
478520
if( fmtArg>nArg ){
479521
printf("%s:%d: too few arguments to %.*s()\n",
@@ -492,28 +534,37 @@
492534
printf("%s:%d: too %s arguments to %.*s() "
493535
"- got %d and expected %d\n",
494536
zFilename, lnFCall, (nArg<fmtArg+k ? "few" : "many"),
495537
szFName, zFCall, nArg, fmtArg+k);
496538
nErr++;
497
- }else if( fmtFlags & FMT_NO_S ){
539
+ }else if( (fmtFlags & FMT_SAFE)==0 ){
498540
for(i=0; i<nArg && i<k; i++){
499
- if( (acType[i]=='s' || acType[i]=='z' || acType[i]=='b')
500
- && !is_s_safe(azArg[fmtArg+i])
501
- ){
502
- printf("%s:%d: Argument %d to %.*s() not safe for SQL\n",
503
- zFilename, lnFCall, i+fmtArg, szFName, zFCall);
504
- nErr++;
541
+ if( (acType[i]=='s' || acType[i]=='z' || acType[i]=='b') ){
542
+ const char *zExpr = azArg[fmtArg+i];
543
+ if( never_safe(zExpr) ){
544
+ printf("%s:%d: Argument %d to %.*s() is not safe for"
545
+ " a query parameter\n",
546
+ zFilename, lnFCall, i+fmtArg, szFName, zFCall);
547
+ nErr++;
548
+
549
+ }else if( (fmtFlags & FMT_SQL)!=0 && !is_sql_safe(zExpr) ){
550
+ printf("%s:%d: Argument %d to %.*s() not safe for SQL\n",
551
+ zFilename, lnFCall, i+fmtArg, szFName, zFCall);
552
+ nErr++;
553
+ }
505554
}
506555
}
507556
}
508557
}
509558
if( nErr ){
510559
for(i=0; i<nArg; i++){
511560
printf(" arg[%d]: %s\n", i, azArg[i]);
512561
}
562
+ }else if( eVerbose>1 ){
563
+ printf("%s:%d: %.*s() ok for %d arguments\n",
564
+ zFilename, lnFCall, szFName, zFCall, nArg);
513565
}
514
-
515566
free((char*)azArg);
516567
free(zCopy);
517568
return nErr;
518569
}
519570
@@ -563,16 +614,24 @@
563614
}
564615
565616
/*
566617
** Check for format-string design rule violations on all files listed
567618
** on the command-line.
619
+**
620
+** The eVerbose global variable is incremented with each "-v" argument.
568621
*/
569622
int main(int argc, char **argv){
570623
int i;
571624
int nErr = 0;
572625
for(i=1; i<argc; i++){
573
- char *zFile = read_file(argv[i]);
626
+ char *zFile;
627
+ if( strcmp(argv[i],"-v")==0 ){
628
+ eVerbose++;
629
+ continue;
630
+ }
631
+ if( eVerbose>0 ) printf("Processing %s...\n", argv[i]);
632
+ zFile = read_file(argv[i]);
574633
nErr += scan_file(argv[i], zFile);
575634
free(zFile);
576635
}
577636
return nErr;
578637
}
579638
--- src/codecheck1.c
+++ src/codecheck1.c
@@ -39,10 +39,15 @@
39 #include <stdlib.h>
40 #include <ctype.h>
41 #include <string.h>
42 #include <assert.h>
43
 
 
 
 
 
44 /*
45 ** Malloc, aborting if it fails.
46 */
47 void *safe_malloc(int nByte){
48 void *x = malloc(nByte);
@@ -198,10 +203,32 @@
198 */
199 static const char *skip_space(const char *z){
200 while( isspace(z[0]) ){ z++; }
201 return z;
202 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
204 /*
205 ** Return true if the input is a string literal.
206 */
207 static int is_string_lit(const char *z){
@@ -268,11 +295,11 @@
268
269 /*
270 ** Return true if the input is an argument that is safe to use with %s
271 ** while building an SQL statement.
272 */
273 static int is_s_safe(const char *z){
274 int len, eType;
275 int i;
276
277 /* A string literal is safe for use with %s */
278 if( is_string_lit(z) ) return 1;
@@ -297,15 +324,29 @@
297 ** let it through */
298 if( strstr(z, "/*safe-for-%s*/")!=0 ) return 1;
299
300 return 0;
301 }
 
 
 
 
 
 
 
 
 
 
 
302
303 /*
304 ** Processing flags
305 */
306 #define FMT_NO_S 0x00001 /* Do not allow %s substitutions */
 
 
 
307
308 /*
309 ** A list of internal Fossil interfaces that take a printf-style format
310 ** string.
311 */
@@ -313,55 +354,55 @@
313 const char *zFName; /* Name of the function */
314 int iFmtArg; /* Index of format argument. Leftmost is 1. */
315 unsigned fmtFlags; /* Processing flags */
316 } aFmtFunc[] = {
317 { "admin_log", 1, 0 },
318 { "blob_append_sql", 2, FMT_NO_S },
319 { "blob_appendf", 2, 0 },
320 { "cgi_debug", 1, 0 },
321 { "cgi_panic", 1, 0 },
322 { "cgi_printf", 1, 0 },
323 { "cgi_redirectf", 1, 0 },
324 { "chref", 2, 0 },
325 { "db_blob", 2, FMT_NO_S },
326 { "db_debug", 1, FMT_NO_S },
327 { "db_double", 2, FMT_NO_S },
328 { "db_err", 1, 0 },
329 { "db_exists", 1, FMT_NO_S },
330 { "db_get_mprintf", 2, 0 },
331 { "db_int", 2, FMT_NO_S },
332 { "db_int64", 2, FMT_NO_S },
333 { "db_multi_exec", 1, FMT_NO_S },
334 { "db_optional_sql", 2, FMT_NO_S },
335 { "db_prepare", 2, FMT_NO_S },
336 { "db_prepare_ignore_error", 2, FMT_NO_S },
337 { "db_set_mprintf", 3, 0 },
338 { "db_static_prepare", 2, FMT_NO_S },
339 { "db_text", 2, FMT_NO_S },
340 { "db_unset_mprintf", 2, 0 },
341 { "form_begin", 2, 0 },
342 { "fossil_error", 2, 0 },
343 { "fossil_errorlog", 1, 0 },
344 { "fossil_fatal", 1, 0 },
345 { "fossil_fatal_recursive", 1, 0 },
346 { "fossil_panic", 1, 0 },
347 { "fossil_print", 1, 0 },
348 { "fossil_trace", 1, 0 },
349 { "fossil_warning", 1, 0 },
350 { "href", 1, 0 },
351 { "json_new_string_f", 1, 0 },
352 { "json_set_err", 2, 0 },
353 { "json_warn", 2, 0 },
354 { "mprintf", 1, 0 },
355 { "socket_set_errmsg", 1, 0 },
356 { "ssl_set_errmsg", 1, 0 },
357 { "style_header", 1, 0 },
358 { "style_set_current_page", 1, 0 },
359 { "style_submenu_element", 2, 0 },
360 { "style_submenu_sql", 3, 0 },
361 { "webpage_error", 1, 0 },
362 { "xhref", 2, 0 },
363 };
364
365 /*
366 ** Determine if the indentifier zIdent of length nIndent is a Fossil
367 ** internal interface that uses a printf-style argument. Return zero if not.
@@ -464,16 +505,17 @@
464 zCopy[len] = 0;
465 azArg = 0;
466 nArg = 0;
467 z = zCopy;
468 while( z[0] ){
 
469 len = distance_to(z, ',');
470 azArg = safe_realloc((char*)azArg, (sizeof(azArg[0])+1)*(nArg+1));
471 azArg[nArg++] = skip_space(z);
472 if( z[len]==0 ) break;
473 z[len] = 0;
474 for(i=len-1; i>0 && isspace(z[i]); i--){ z[i] = 0; }
 
 
475 z += len + 1;
476 }
477 acType = (char*)&azArg[nArg];
478 if( fmtArg>nArg ){
479 printf("%s:%d: too few arguments to %.*s()\n",
@@ -492,28 +534,37 @@
492 printf("%s:%d: too %s arguments to %.*s() "
493 "- got %d and expected %d\n",
494 zFilename, lnFCall, (nArg<fmtArg+k ? "few" : "many"),
495 szFName, zFCall, nArg, fmtArg+k);
496 nErr++;
497 }else if( fmtFlags & FMT_NO_S ){
498 for(i=0; i<nArg && i<k; i++){
499 if( (acType[i]=='s' || acType[i]=='z' || acType[i]=='b')
500 && !is_s_safe(azArg[fmtArg+i])
501 ){
502 printf("%s:%d: Argument %d to %.*s() not safe for SQL\n",
503 zFilename, lnFCall, i+fmtArg, szFName, zFCall);
504 nErr++;
 
 
 
 
 
 
 
505 }
506 }
507 }
508 }
509 if( nErr ){
510 for(i=0; i<nArg; i++){
511 printf(" arg[%d]: %s\n", i, azArg[i]);
512 }
 
 
 
513 }
514
515 free((char*)azArg);
516 free(zCopy);
517 return nErr;
518 }
519
@@ -563,16 +614,24 @@
563 }
564
565 /*
566 ** Check for format-string design rule violations on all files listed
567 ** on the command-line.
 
 
568 */
569 int main(int argc, char **argv){
570 int i;
571 int nErr = 0;
572 for(i=1; i<argc; i++){
573 char *zFile = read_file(argv[i]);
 
 
 
 
 
 
574 nErr += scan_file(argv[i], zFile);
575 free(zFile);
576 }
577 return nErr;
578 }
579
--- src/codecheck1.c
+++ src/codecheck1.c
@@ -39,10 +39,15 @@
39 #include <stdlib.h>
40 #include <ctype.h>
41 #include <string.h>
42 #include <assert.h>
43
44 /*
45 ** Debugging switch
46 */
47 static int eVerbose = 0;
48
49 /*
50 ** Malloc, aborting if it fails.
51 */
52 void *safe_malloc(int nByte){
53 void *x = malloc(nByte);
@@ -198,10 +203,32 @@
203 */
204 static const char *skip_space(const char *z){
205 while( isspace(z[0]) ){ z++; }
206 return z;
207 }
208
209 /*
210 ** Remove excess whitespace and nested "()" from string z.
211 */
212 static char *simplify_expr(char *z){
213 int n = (int)strlen(z);
214 while( n>0 ){
215 if( isspace(z[0]) ){
216 z++;
217 n--;
218 continue;
219 }
220 if( z[0]=='(' && z[n-1]==')' ){
221 z++;
222 n -= 2;
223 continue;
224 }
225 break;
226 }
227 z[n] = 0;
228 return z;
229 }
230
231 /*
232 ** Return true if the input is a string literal.
233 */
234 static int is_string_lit(const char *z){
@@ -268,11 +295,11 @@
295
296 /*
297 ** Return true if the input is an argument that is safe to use with %s
298 ** while building an SQL statement.
299 */
300 static int is_sql_safe(const char *z){
301 int len, eType;
302 int i;
303
304 /* A string literal is safe for use with %s */
305 if( is_string_lit(z) ) return 1;
@@ -297,15 +324,29 @@
324 ** let it through */
325 if( strstr(z, "/*safe-for-%s*/")!=0 ) return 1;
326
327 return 0;
328 }
329
330 /*
331 ** Return true if the input is an argument that is never safe for use
332 ** with %s.
333 */
334 static int never_safe(const char *z){
335 if( strstr(z,"/*safe-for-%s*/")!=0 ) return 0;
336 if( z[0]=='P' ) return 1; /* CGI macros like P() and PD() */
337 if( strncmp(z,"cgi_param",9)==0 ) return 1;
338 return 0;
339 }
340
341 /*
342 ** Processing flags
343 */
344 #define FMT_SQL 0x00001 /* Generates SQL text */
345 #define FMT_HTML 0x00002 /* Generates HTML text */
346 #define FMT_URL 0x00004 /* Generates URLs */
347 #define FMT_SAFE 0x00008 /* Always safe for %s */
348
349 /*
350 ** A list of internal Fossil interfaces that take a printf-style format
351 ** string.
352 */
@@ -313,55 +354,55 @@
354 const char *zFName; /* Name of the function */
355 int iFmtArg; /* Index of format argument. Leftmost is 1. */
356 unsigned fmtFlags; /* Processing flags */
357 } aFmtFunc[] = {
358 { "admin_log", 1, 0 },
359 { "blob_append_sql", 2, FMT_SQL },
360 { "blob_appendf", 2, 0 },
361 { "cgi_debug", 1, FMT_SAFE },
362 { "cgi_panic", 1, FMT_SAFE },
363 { "cgi_printf", 1, FMT_HTML },
364 { "cgi_redirectf", 1, FMT_URL },
365 { "chref", 2, FMT_URL },
366 { "db_blob", 2, FMT_SQL },
367 { "db_debug", 1, FMT_SQL },
368 { "db_double", 2, FMT_SQL },
369 { "db_err", 1, 0 },
370 { "db_exists", 1, FMT_SQL },
371 { "db_get_mprintf", 2, 0 },
372 { "db_int", 2, FMT_SQL },
373 { "db_int64", 2, FMT_SQL },
374 { "db_multi_exec", 1, FMT_SQL },
375 { "db_optional_sql", 2, FMT_SQL },
376 { "db_prepare", 2, FMT_SQL },
377 { "db_prepare_ignore_error", 2, FMT_SQL },
378 { "db_set_mprintf", 3, 0 },
379 { "db_static_prepare", 2, FMT_SQL },
380 { "db_text", 2, FMT_SQL },
381 { "db_unset_mprintf", 2, 0 },
382 { "form_begin", 2, FMT_URL },
383 { "fossil_error", 2, FMT_SAFE },
384 { "fossil_errorlog", 1, FMT_SAFE },
385 { "fossil_fatal", 1, FMT_SAFE },
386 { "fossil_fatal_recursive", 1, FMT_SAFE },
387 { "fossil_panic", 1, FMT_SAFE },
388 { "fossil_print", 1, FMT_SAFE },
389 { "fossil_trace", 1, FMT_SAFE },
390 { "fossil_warning", 1, FMT_SAFE },
391 { "href", 1, FMT_URL },
392 { "json_new_string_f", 1, 0 },
393 { "json_set_err", 2, 0 },
394 { "json_warn", 2, 0 },
395 { "mprintf", 1, 0 },
396 { "socket_set_errmsg", 1, 0 },
397 { "ssl_set_errmsg", 1, 0 },
398 { "style_header", 1, FMT_HTML },
399 { "style_set_current_page", 1, FMT_URL },
400 { "style_submenu_element", 2, FMT_URL },
401 { "style_submenu_sql", 3, FMT_SQL },
402 { "webpage_error", 1, FMT_SAFE },
403 { "xhref", 2, FMT_URL },
404 };
405
406 /*
407 ** Determine if the indentifier zIdent of length nIndent is a Fossil
408 ** internal interface that uses a printf-style argument. Return zero if not.
@@ -464,16 +505,17 @@
505 zCopy[len] = 0;
506 azArg = 0;
507 nArg = 0;
508 z = zCopy;
509 while( z[0] ){
510 char cEnd;
511 len = distance_to(z, ',');
512 cEnd = z[len];
 
 
513 z[len] = 0;
514 azArg = safe_realloc((char*)azArg, (sizeof(azArg[0])+1)*(nArg+1));
515 azArg[nArg++] = simplify_expr(z);
516 if( cEnd==0 ) break;
517 z += len + 1;
518 }
519 acType = (char*)&azArg[nArg];
520 if( fmtArg>nArg ){
521 printf("%s:%d: too few arguments to %.*s()\n",
@@ -492,28 +534,37 @@
534 printf("%s:%d: too %s arguments to %.*s() "
535 "- got %d and expected %d\n",
536 zFilename, lnFCall, (nArg<fmtArg+k ? "few" : "many"),
537 szFName, zFCall, nArg, fmtArg+k);
538 nErr++;
539 }else if( (fmtFlags & FMT_SAFE)==0 ){
540 for(i=0; i<nArg && i<k; i++){
541 if( (acType[i]=='s' || acType[i]=='z' || acType[i]=='b') ){
542 const char *zExpr = azArg[fmtArg+i];
543 if( never_safe(zExpr) ){
544 printf("%s:%d: Argument %d to %.*s() is not safe for"
545 " a query parameter\n",
546 zFilename, lnFCall, i+fmtArg, szFName, zFCall);
547 nErr++;
548
549 }else if( (fmtFlags & FMT_SQL)!=0 && !is_sql_safe(zExpr) ){
550 printf("%s:%d: Argument %d to %.*s() not safe for SQL\n",
551 zFilename, lnFCall, i+fmtArg, szFName, zFCall);
552 nErr++;
553 }
554 }
555 }
556 }
557 }
558 if( nErr ){
559 for(i=0; i<nArg; i++){
560 printf(" arg[%d]: %s\n", i, azArg[i]);
561 }
562 }else if( eVerbose>1 ){
563 printf("%s:%d: %.*s() ok for %d arguments\n",
564 zFilename, lnFCall, szFName, zFCall, nArg);
565 }
 
566 free((char*)azArg);
567 free(zCopy);
568 return nErr;
569 }
570
@@ -563,16 +614,24 @@
614 }
615
616 /*
617 ** Check for format-string design rule violations on all files listed
618 ** on the command-line.
619 **
620 ** The eVerbose global variable is incremented with each "-v" argument.
621 */
622 int main(int argc, char **argv){
623 int i;
624 int nErr = 0;
625 for(i=1; i<argc; i++){
626 char *zFile;
627 if( strcmp(argv[i],"-v")==0 ){
628 eVerbose++;
629 continue;
630 }
631 if( eVerbose>0 ) printf("Processing %s...\n", argv[i]);
632 zFile = read_file(argv[i]);
633 nErr += scan_file(argv[i], zFile);
634 free(zFile);
635 }
636 return nErr;
637 }
638
+1 -1
--- src/login.c
+++ src/login.c
@@ -521,11 +521,11 @@
521521
if( zQS==0 ){
522522
zQS = "?redir=1";
523523
}else if( zQS[0]!=0 ){
524524
zQS = mprintf("?%s&redir=1", zQS);
525525
}
526
- cgi_redirectf("%s%s%s", g.zHttpsURL, P("PATH_INFO"), zQS);
526
+ cgi_redirectf("%s%T%s", g.zHttpsURL, P("PATH_INFO"), zQS);
527527
return;
528528
}
529529
sqlite3_create_function(g.db, "constant_time_cmp", 2, SQLITE_UTF8, 0,
530530
constant_time_cmp_function, 0, 0);
531531
zUsername = P("u");
532532
--- src/login.c
+++ src/login.c
@@ -521,11 +521,11 @@
521 if( zQS==0 ){
522 zQS = "?redir=1";
523 }else if( zQS[0]!=0 ){
524 zQS = mprintf("?%s&redir=1", zQS);
525 }
526 cgi_redirectf("%s%s%s", g.zHttpsURL, P("PATH_INFO"), zQS);
527 return;
528 }
529 sqlite3_create_function(g.db, "constant_time_cmp", 2, SQLITE_UTF8, 0,
530 constant_time_cmp_function, 0, 0);
531 zUsername = P("u");
532
--- src/login.c
+++ src/login.c
@@ -521,11 +521,11 @@
521 if( zQS==0 ){
522 zQS = "?redir=1";
523 }else if( zQS[0]!=0 ){
524 zQS = mprintf("?%s&redir=1", zQS);
525 }
526 cgi_redirectf("%s%T%s", g.zHttpsURL, P("PATH_INFO"), zQS);
527 return;
528 }
529 sqlite3_create_function(g.db, "constant_time_cmp", 2, SQLITE_UTF8, 0,
530 constant_time_cmp_function, 0, 0);
531 zUsername = P("u");
532
+1 -1
--- src/main.c
+++ src/main.c
@@ -1637,11 +1637,11 @@
16371637
&& (zPathInfo[7]=='/' || zPathInfo[7]==0)
16381638
){
16391639
int iSkin = zPathInfo[6] - '0';
16401640
char *zNewScript;
16411641
skin_use_draft(iSkin);
1642
- zNewScript = mprintf("%s/draft%d", P("SCRIPT_NAME"), iSkin);
1642
+ zNewScript = mprintf("%T/draft%d", P("SCRIPT_NAME"), iSkin);
16431643
if( g.zTop ) g.zTop = mprintf("%s/draft%d", g.zTop, iSkin);
16441644
if( g.zBaseURL ) g.zBaseURL = mprintf("%s/draft%d", g.zBaseURL, iSkin);
16451645
zPathInfo += 7;
16461646
cgi_replace_parameter("PATH_INFO", zPathInfo);
16471647
cgi_replace_parameter("SCRIPT_NAME", zNewScript);
16481648
--- src/main.c
+++ src/main.c
@@ -1637,11 +1637,11 @@
1637 && (zPathInfo[7]=='/' || zPathInfo[7]==0)
1638 ){
1639 int iSkin = zPathInfo[6] - '0';
1640 char *zNewScript;
1641 skin_use_draft(iSkin);
1642 zNewScript = mprintf("%s/draft%d", P("SCRIPT_NAME"), iSkin);
1643 if( g.zTop ) g.zTop = mprintf("%s/draft%d", g.zTop, iSkin);
1644 if( g.zBaseURL ) g.zBaseURL = mprintf("%s/draft%d", g.zBaseURL, iSkin);
1645 zPathInfo += 7;
1646 cgi_replace_parameter("PATH_INFO", zPathInfo);
1647 cgi_replace_parameter("SCRIPT_NAME", zNewScript);
1648
--- src/main.c
+++ src/main.c
@@ -1637,11 +1637,11 @@
1637 && (zPathInfo[7]=='/' || zPathInfo[7]==0)
1638 ){
1639 int iSkin = zPathInfo[6] - '0';
1640 char *zNewScript;
1641 skin_use_draft(iSkin);
1642 zNewScript = mprintf("%T/draft%d", P("SCRIPT_NAME"), iSkin);
1643 if( g.zTop ) g.zTop = mprintf("%s/draft%d", g.zTop, iSkin);
1644 if( g.zBaseURL ) g.zBaseURL = mprintf("%s/draft%d", g.zBaseURL, iSkin);
1645 zPathInfo += 7;
1646 cgi_replace_parameter("PATH_INFO", zPathInfo);
1647 cgi_replace_parameter("SCRIPT_NAME", zNewScript);
1648
+1 -1
--- src/zip.c
+++ src/zip.c
@@ -891,11 +891,11 @@
891891
}else{
892892
eType = ARCHIVE_ZIP;
893893
zType = "ZIP";
894894
}
895895
load_control();
896
- zName = mprintf("%s", PD("name",""));
896
+ zName = fossil_strdup(PD("name",""));
897897
z = P("r");
898898
if( z==0 ) z = P("uuid");
899899
if( z==0 ) z = tar_uuid_from_name(&zName);
900900
if( z==0 ) z = "trunk";
901901
nName = strlen(zName);
902902
--- src/zip.c
+++ src/zip.c
@@ -891,11 +891,11 @@
891 }else{
892 eType = ARCHIVE_ZIP;
893 zType = "ZIP";
894 }
895 load_control();
896 zName = mprintf("%s", PD("name",""));
897 z = P("r");
898 if( z==0 ) z = P("uuid");
899 if( z==0 ) z = tar_uuid_from_name(&zName);
900 if( z==0 ) z = "trunk";
901 nName = strlen(zName);
902
--- src/zip.c
+++ src/zip.c
@@ -891,11 +891,11 @@
891 }else{
892 eType = ARCHIVE_ZIP;
893 zType = "ZIP";
894 }
895 load_control();
896 zName = fossil_strdup(PD("name",""));
897 z = P("r");
898 if( z==0 ) z = P("uuid");
899 if( z==0 ) z = tar_uuid_from_name(&zName);
900 if( z==0 ) z = "trunk";
901 nName = strlen(zName);
902

Keyboard Shortcuts

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