Fossil SCM
Improved quoting for filenames on constructed command-lines.
Commit
b3fab9b5ddfedf9332c177a1959c44bbc5dfe75879b845feae4f63df61ea16d0
Parent
2c66a5395ab5b83…
2 files changed
+93
-49
+6
-1
+93
-49
| --- src/blob.c | ||
| +++ src/blob.c | ||
| @@ -1293,10 +1293,52 @@ | ||
| 1293 | 1293 | z[--j] = z[i]; |
| 1294 | 1294 | } |
| 1295 | 1295 | } |
| 1296 | 1296 | } |
| 1297 | 1297 | |
| 1298 | +/* | |
| 1299 | +** ASCII (for reference): | |
| 1300 | +** x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf | |
| 1301 | +** 0x ^` ^a ^b ^c ^d ^e ^f ^g \b \t \n () \f \r ^n ^o | |
| 1302 | +** 1x ^p ^q ^r ^s ^t ^u ^v ^w ^x ^y ^z ^{ ^| ^} ^~ ^ | |
| 1303 | +** 2x () ! " # $ % & ' ( ) * + , - . / | |
| 1304 | +** 3x 0 1 2 3 4 5 6 7 8 9 : ; < = > ? | |
| 1305 | +** 4x @ A B C D E F G H I J K L M N O | |
| 1306 | +** 5x P Q R S T U V W X Y Z [ \ ] ^ _ | |
| 1307 | +** 6x ` a b c d e f g h i j k l m n o | |
| 1308 | +** 7x p q r s t u v w x y z { | } ~ ^_ | |
| 1309 | +*/ | |
| 1310 | + | |
| 1311 | +/* | |
| 1312 | +** Characters that need to be escaped are marked with 1. | |
| 1313 | +** Illegal characters are marked with 2. | |
| 1314 | +*/ | |
| 1315 | +static const char aSafeChar[256] = { | |
| 1316 | +#ifdef _WIN32 | |
| 1317 | +/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */ | |
| 1318 | + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x */ | |
| 1319 | + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 1x */ | |
| 1320 | + 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, /* 2x */ | |
| 1321 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, /* 3x */ | |
| 1322 | + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */ | |
| 1323 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, /* 5x */ | |
| 1324 | + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */ | |
| 1325 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* 7x */ | |
| 1326 | +#else | |
| 1327 | +/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */ | |
| 1328 | + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x */ | |
| 1329 | + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 1x */ | |
| 1330 | + 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, /* 2x */ | |
| 1331 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, /* 3x */ | |
| 1332 | + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */ | |
| 1333 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, /* 5x */ | |
| 1334 | + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */ | |
| 1335 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* 7x */ | |
| 1336 | +#endif | |
| 1337 | + /* All the rest are zeros */ | |
| 1338 | +}; | |
| 1339 | + | |
| 1298 | 1340 | /* |
| 1299 | 1341 | ** pBlob is a shell command under construction. This routine safely |
| 1300 | 1342 | ** appends argument zIn. |
| 1301 | 1343 | ** |
| 1302 | 1344 | ** The argument is escaped if it contains white space or other characters |
| @@ -1309,69 +1351,71 @@ | ||
| 1309 | 1351 | ** filenames that begin with "-", if zIn begins with "-", prepend |
| 1310 | 1352 | ** an additional "./". |
| 1311 | 1353 | */ |
| 1312 | 1354 | void blob_append_escaped_arg(Blob *pBlob, const char *zIn){ |
| 1313 | 1355 | int i; |
| 1314 | - char c; | |
| 1356 | + unsigned char c; | |
| 1315 | 1357 | int needEscape = 0; |
| 1358 | + int hasIllegal = 0; | |
| 1316 | 1359 | int n = blob_size(pBlob); |
| 1317 | 1360 | char *z = blob_buffer(pBlob); |
| 1318 | 1361 | #if defined(_WIN32) |
| 1319 | - const char cDirSep = '\\'; /* Use \ as directory separator */ | |
| 1320 | - const char cQuote = '"'; /* Use "..." quoting on windows */ | |
| 1321 | - const char cEscape = '^'; /* Use ^X escaping on windows */ | |
| 1362 | + const char *zNeedQuote = "\"^[];*? "; | |
| 1322 | 1363 | #else |
| 1323 | - const char cDirSep = '/'; /* Use / as directory separator */ | |
| 1324 | - const char cQuote = '\''; /* Use '...' quoting on unix */ | |
| 1325 | - const char cEscape = '\\'; /* Use \X escaping on unix */ | |
| 1364 | + const char *zNeedQuote = "\"'\\*?$&|` "; | |
| 1326 | 1365 | #endif |
| 1327 | 1366 | |
| 1328 | - for(i=0; (c = zIn[i])!=0; i++){ | |
| 1329 | - if( c==cQuote || (unsigned char)c<' ' || | |
| 1330 | - c==cEscape || c==';' || c=='*' || c=='?' || c=='[' ){ | |
| 1331 | - Blob bad; | |
| 1332 | - blob_token(pBlob, &bad); | |
| 1333 | - fossil_fatal("the [%s] argument to the \"%s\" command contains " | |
| 1334 | - "a character (ascii 0x%02x) that is a security risk", | |
| 1335 | - zIn, blob_str(&bad), c); | |
| 1336 | - } | |
| 1337 | - if( !needEscape && !fossil_isalnum(c) && c!=cDirSep && c!='.' && c!='_' ){ | |
| 1338 | - needEscape = 1; | |
| 1339 | - } | |
| 1340 | - } | |
| 1367 | + /* Any control character is illegal. This prevents \n and \r in an | |
| 1368 | + ** argument. */ | |
| 1369 | + for(i=0; (c = (unsigned char)zIn[i])!=0; i++){ | |
| 1370 | + if( aSafeChar[c] ){ | |
| 1371 | + if( aSafeChar[c]==2 ){ | |
| 1372 | + Blob bad; | |
| 1373 | + blob_token(pBlob, &bad); | |
| 1374 | + fossil_fatal("the [%s] argument to the \"%s\" command contains " | |
| 1375 | + "a character (ascii 0x%02x) that is a security risk", | |
| 1376 | + zIn, blob_str(&bad), c); | |
| 1377 | + }else{ | |
| 1378 | + needEscape = 1; | |
| 1379 | + } | |
| 1380 | + break; | |
| 1381 | + } | |
| 1382 | + } | |
| 1383 | + | |
| 1384 | + /* Separate from the previous argument by a space */ | |
| 1341 | 1385 | if( n>0 && !fossil_isspace(z[n-1]) ){ |
| 1342 | 1386 | blob_append_char(pBlob, ' '); |
| 1343 | 1387 | } |
| 1344 | - if( needEscape ) blob_append_char(pBlob, cQuote); | |
| 1345 | - if( zIn[0]=='-' ){ | |
| 1346 | - blob_append_char(pBlob, '.'); | |
| 1347 | - blob_append_char(pBlob, cDirSep); | |
| 1348 | -#if defined(_WIN32) | |
| 1349 | - }else if( zIn[0]=='/' ){ | |
| 1350 | - blob_append_char(pBlob, '.'); | |
| 1351 | -#endif | |
| 1352 | - } | |
| 1353 | -#if defined(_WIN32) | |
| 1354 | - if( needEscape ){ | |
| 1355 | - for(i=0; (c = zIn[i])!=0; i++){ | |
| 1356 | - if( c==cQuote ) blob_append_char(pBlob, cDirSep); | |
| 1357 | - blob_append_char(pBlob, c); | |
| 1358 | - } | |
| 1359 | - }else{ | |
| 1360 | - blob_append(pBlob, zIn, -1); | |
| 1361 | - } | |
| 1362 | -#else | |
| 1363 | - blob_append(pBlob, zIn, -1); | |
| 1364 | -#endif | |
| 1365 | - if( needEscape ){ | |
| 1366 | -#if defined(_WIN32) | |
| 1367 | - /* NOTE: Trailing backslash must be doubled before final double quote. */ | |
| 1368 | - if( pBlob->aData[pBlob->nUsed-1]==cDirSep ){ | |
| 1369 | - blob_append_char(pBlob, cDirSep); | |
| 1370 | - } | |
| 1371 | -#endif | |
| 1372 | - blob_append_char(pBlob, cQuote); | |
| 1388 | + | |
| 1389 | + /* Check for characters that need quoting */ | |
| 1390 | + needEscape = strpbrk(zIn, zNeedQuote)!=0; | |
| 1391 | + if( !needEscape ){ | |
| 1392 | + blob_append(pBlob, zIn, -1); | |
| 1393 | + }else{ | |
| 1394 | +#if defined(_WIN32) | |
| 1395 | + blob_append_char(pBlob, '"'); | |
| 1396 | + if( zIn[0]=='-' ){ | |
| 1397 | + blob_append_char(pBlob, '.'); | |
| 1398 | + blob_append_char(pBlob, '\\'); | |
| 1399 | + }else if( zIn[0]=='/' ){ | |
| 1400 | + blob_append_char(pBlob, '.'); | |
| 1401 | + } | |
| 1402 | + for(i=0; (c = (unsigned char)zIn[i])!=0; i++){ | |
| 1403 | + blob_append_char(pBlob, (char)c); | |
| 1404 | + if( c=='"' ) blob_append_char(pBlob, '"'); | |
| 1405 | + } | |
| 1406 | + blob_append_char(pBlob, '"'); | |
| 1407 | +#else | |
| 1408 | + if( zIn[0]=='-' ){ | |
| 1409 | + blob_append_char(pBlob, '.'); | |
| 1410 | + blob_append_char(pBlob, '/'); | |
| 1411 | + } | |
| 1412 | + for(i=0; (c = (unsigned char)zIn[i])!=0; i++){ | |
| 1413 | + if( aSafeChar[c] ) blob_append_char(pBlob, '\\'); | |
| 1414 | + blob_append_char(pBlob, (char)c); | |
| 1415 | + } | |
| 1416 | +#endif | |
| 1373 | 1417 | } |
| 1374 | 1418 | } |
| 1375 | 1419 | |
| 1376 | 1420 | /* |
| 1377 | 1421 | ** COMMAND: test-escaped-arg |
| 1378 | 1422 |
| --- src/blob.c | |
| +++ src/blob.c | |
| @@ -1293,10 +1293,52 @@ | |
| 1293 | z[--j] = z[i]; |
| 1294 | } |
| 1295 | } |
| 1296 | } |
| 1297 | |
| 1298 | /* |
| 1299 | ** pBlob is a shell command under construction. This routine safely |
| 1300 | ** appends argument zIn. |
| 1301 | ** |
| 1302 | ** The argument is escaped if it contains white space or other characters |
| @@ -1309,69 +1351,71 @@ | |
| 1309 | ** filenames that begin with "-", if zIn begins with "-", prepend |
| 1310 | ** an additional "./". |
| 1311 | */ |
| 1312 | void blob_append_escaped_arg(Blob *pBlob, const char *zIn){ |
| 1313 | int i; |
| 1314 | char c; |
| 1315 | int needEscape = 0; |
| 1316 | int n = blob_size(pBlob); |
| 1317 | char *z = blob_buffer(pBlob); |
| 1318 | #if defined(_WIN32) |
| 1319 | const char cDirSep = '\\'; /* Use \ as directory separator */ |
| 1320 | const char cQuote = '"'; /* Use "..." quoting on windows */ |
| 1321 | const char cEscape = '^'; /* Use ^X escaping on windows */ |
| 1322 | #else |
| 1323 | const char cDirSep = '/'; /* Use / as directory separator */ |
| 1324 | const char cQuote = '\''; /* Use '...' quoting on unix */ |
| 1325 | const char cEscape = '\\'; /* Use \X escaping on unix */ |
| 1326 | #endif |
| 1327 | |
| 1328 | for(i=0; (c = zIn[i])!=0; i++){ |
| 1329 | if( c==cQuote || (unsigned char)c<' ' || |
| 1330 | c==cEscape || c==';' || c=='*' || c=='?' || c=='[' ){ |
| 1331 | Blob bad; |
| 1332 | blob_token(pBlob, &bad); |
| 1333 | fossil_fatal("the [%s] argument to the \"%s\" command contains " |
| 1334 | "a character (ascii 0x%02x) that is a security risk", |
| 1335 | zIn, blob_str(&bad), c); |
| 1336 | } |
| 1337 | if( !needEscape && !fossil_isalnum(c) && c!=cDirSep && c!='.' && c!='_' ){ |
| 1338 | needEscape = 1; |
| 1339 | } |
| 1340 | } |
| 1341 | if( n>0 && !fossil_isspace(z[n-1]) ){ |
| 1342 | blob_append_char(pBlob, ' '); |
| 1343 | } |
| 1344 | if( needEscape ) blob_append_char(pBlob, cQuote); |
| 1345 | if( zIn[0]=='-' ){ |
| 1346 | blob_append_char(pBlob, '.'); |
| 1347 | blob_append_char(pBlob, cDirSep); |
| 1348 | #if defined(_WIN32) |
| 1349 | }else if( zIn[0]=='/' ){ |
| 1350 | blob_append_char(pBlob, '.'); |
| 1351 | #endif |
| 1352 | } |
| 1353 | #if defined(_WIN32) |
| 1354 | if( needEscape ){ |
| 1355 | for(i=0; (c = zIn[i])!=0; i++){ |
| 1356 | if( c==cQuote ) blob_append_char(pBlob, cDirSep); |
| 1357 | blob_append_char(pBlob, c); |
| 1358 | } |
| 1359 | }else{ |
| 1360 | blob_append(pBlob, zIn, -1); |
| 1361 | } |
| 1362 | #else |
| 1363 | blob_append(pBlob, zIn, -1); |
| 1364 | #endif |
| 1365 | if( needEscape ){ |
| 1366 | #if defined(_WIN32) |
| 1367 | /* NOTE: Trailing backslash must be doubled before final double quote. */ |
| 1368 | if( pBlob->aData[pBlob->nUsed-1]==cDirSep ){ |
| 1369 | blob_append_char(pBlob, cDirSep); |
| 1370 | } |
| 1371 | #endif |
| 1372 | blob_append_char(pBlob, cQuote); |
| 1373 | } |
| 1374 | } |
| 1375 | |
| 1376 | /* |
| 1377 | ** COMMAND: test-escaped-arg |
| 1378 |
| --- src/blob.c | |
| +++ src/blob.c | |
| @@ -1293,10 +1293,52 @@ | |
| 1293 | z[--j] = z[i]; |
| 1294 | } |
| 1295 | } |
| 1296 | } |
| 1297 | |
| 1298 | /* |
| 1299 | ** ASCII (for reference): |
| 1300 | ** x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf |
| 1301 | ** 0x ^` ^a ^b ^c ^d ^e ^f ^g \b \t \n () \f \r ^n ^o |
| 1302 | ** 1x ^p ^q ^r ^s ^t ^u ^v ^w ^x ^y ^z ^{ ^| ^} ^~ ^ |
| 1303 | ** 2x () ! " # $ % & ' ( ) * + , - . / |
| 1304 | ** 3x 0 1 2 3 4 5 6 7 8 9 : ; < = > ? |
| 1305 | ** 4x @ A B C D E F G H I J K L M N O |
| 1306 | ** 5x P Q R S T U V W X Y Z [ \ ] ^ _ |
| 1307 | ** 6x ` a b c d e f g h i j k l m n o |
| 1308 | ** 7x p q r s t u v w x y z { | } ~ ^_ |
| 1309 | */ |
| 1310 | |
| 1311 | /* |
| 1312 | ** Characters that need to be escaped are marked with 1. |
| 1313 | ** Illegal characters are marked with 2. |
| 1314 | */ |
| 1315 | static const char aSafeChar[256] = { |
| 1316 | #ifdef _WIN32 |
| 1317 | /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */ |
| 1318 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x */ |
| 1319 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 1x */ |
| 1320 | 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, /* 2x */ |
| 1321 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, /* 3x */ |
| 1322 | 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */ |
| 1323 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, /* 5x */ |
| 1324 | 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */ |
| 1325 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* 7x */ |
| 1326 | #else |
| 1327 | /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */ |
| 1328 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x */ |
| 1329 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 1x */ |
| 1330 | 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, /* 2x */ |
| 1331 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, /* 3x */ |
| 1332 | 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */ |
| 1333 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, /* 5x */ |
| 1334 | 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */ |
| 1335 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* 7x */ |
| 1336 | #endif |
| 1337 | /* All the rest are zeros */ |
| 1338 | }; |
| 1339 | |
| 1340 | /* |
| 1341 | ** pBlob is a shell command under construction. This routine safely |
| 1342 | ** appends argument zIn. |
| 1343 | ** |
| 1344 | ** The argument is escaped if it contains white space or other characters |
| @@ -1309,69 +1351,71 @@ | |
| 1351 | ** filenames that begin with "-", if zIn begins with "-", prepend |
| 1352 | ** an additional "./". |
| 1353 | */ |
| 1354 | void blob_append_escaped_arg(Blob *pBlob, const char *zIn){ |
| 1355 | int i; |
| 1356 | unsigned char c; |
| 1357 | int needEscape = 0; |
| 1358 | int hasIllegal = 0; |
| 1359 | int n = blob_size(pBlob); |
| 1360 | char *z = blob_buffer(pBlob); |
| 1361 | #if defined(_WIN32) |
| 1362 | const char *zNeedQuote = "\"^[];*? "; |
| 1363 | #else |
| 1364 | const char *zNeedQuote = "\"'\\*?$&|` "; |
| 1365 | #endif |
| 1366 | |
| 1367 | /* Any control character is illegal. This prevents \n and \r in an |
| 1368 | ** argument. */ |
| 1369 | for(i=0; (c = (unsigned char)zIn[i])!=0; i++){ |
| 1370 | if( aSafeChar[c] ){ |
| 1371 | if( aSafeChar[c]==2 ){ |
| 1372 | Blob bad; |
| 1373 | blob_token(pBlob, &bad); |
| 1374 | fossil_fatal("the [%s] argument to the \"%s\" command contains " |
| 1375 | "a character (ascii 0x%02x) that is a security risk", |
| 1376 | zIn, blob_str(&bad), c); |
| 1377 | }else{ |
| 1378 | needEscape = 1; |
| 1379 | } |
| 1380 | break; |
| 1381 | } |
| 1382 | } |
| 1383 | |
| 1384 | /* Separate from the previous argument by a space */ |
| 1385 | if( n>0 && !fossil_isspace(z[n-1]) ){ |
| 1386 | blob_append_char(pBlob, ' '); |
| 1387 | } |
| 1388 | |
| 1389 | /* Check for characters that need quoting */ |
| 1390 | needEscape = strpbrk(zIn, zNeedQuote)!=0; |
| 1391 | if( !needEscape ){ |
| 1392 | blob_append(pBlob, zIn, -1); |
| 1393 | }else{ |
| 1394 | #if defined(_WIN32) |
| 1395 | blob_append_char(pBlob, '"'); |
| 1396 | if( zIn[0]=='-' ){ |
| 1397 | blob_append_char(pBlob, '.'); |
| 1398 | blob_append_char(pBlob, '\\'); |
| 1399 | }else if( zIn[0]=='/' ){ |
| 1400 | blob_append_char(pBlob, '.'); |
| 1401 | } |
| 1402 | for(i=0; (c = (unsigned char)zIn[i])!=0; i++){ |
| 1403 | blob_append_char(pBlob, (char)c); |
| 1404 | if( c=='"' ) blob_append_char(pBlob, '"'); |
| 1405 | } |
| 1406 | blob_append_char(pBlob, '"'); |
| 1407 | #else |
| 1408 | if( zIn[0]=='-' ){ |
| 1409 | blob_append_char(pBlob, '.'); |
| 1410 | blob_append_char(pBlob, '/'); |
| 1411 | } |
| 1412 | for(i=0; (c = (unsigned char)zIn[i])!=0; i++){ |
| 1413 | if( aSafeChar[c] ) blob_append_char(pBlob, '\\'); |
| 1414 | blob_append_char(pBlob, (char)c); |
| 1415 | } |
| 1416 | #endif |
| 1417 | } |
| 1418 | } |
| 1419 | |
| 1420 | /* |
| 1421 | ** COMMAND: test-escaped-arg |
| 1422 |
+6
-1
| --- src/file.c | ||
| +++ src/file.c | ||
| @@ -1780,20 +1780,21 @@ | ||
| 1780 | 1780 | ** the root of zBasis in its name. |
| 1781 | 1781 | ** |
| 1782 | 1782 | ** If zTag is not NULL, then try to create the temp-file using zTag |
| 1783 | 1783 | ** as a differentiator. If that fails, or if zTag is NULL, then use |
| 1784 | 1784 | ** a bunch of random characters as the tag. |
| 1785 | +** | |
| 1786 | +** Dangerous characters in zBasis are changed. | |
| 1785 | 1787 | */ |
| 1786 | 1788 | void file_tempname(Blob *pBuf, const char *zBasis, const char *zTag){ |
| 1787 | 1789 | #if defined(_WIN32) |
| 1788 | 1790 | const char *azDirs[] = { |
| 1789 | 1791 | 0, /* GetTempPath */ |
| 1790 | 1792 | 0, /* TEMP */ |
| 1791 | 1793 | 0, /* TMP */ |
| 1792 | 1794 | ".", |
| 1793 | 1795 | }; |
| 1794 | - char *z; | |
| 1795 | 1796 | #else |
| 1796 | 1797 | static const char *azDirs[] = { |
| 1797 | 1798 | 0, /* TMPDIR */ |
| 1798 | 1799 | "/var/tmp", |
| 1799 | 1800 | "/usr/tmp", |
| @@ -1810,10 +1811,11 @@ | ||
| 1810 | 1811 | const char *zDir = "."; |
| 1811 | 1812 | int cnt = 0; |
| 1812 | 1813 | char zRand[16]; |
| 1813 | 1814 | int nBasis; |
| 1814 | 1815 | const char *zSuffix; |
| 1816 | + char *z; | |
| 1815 | 1817 | |
| 1816 | 1818 | #if defined(_WIN32) |
| 1817 | 1819 | wchar_t zTmpPath[MAX_PATH]; |
| 1818 | 1820 | |
| 1819 | 1821 | if( GetTempPathW(MAX_PATH, zTmpPath) ){ |
| @@ -1868,10 +1870,13 @@ | ||
| 1868 | 1870 | zRand[15] = 0; |
| 1869 | 1871 | zTag = zRand; |
| 1870 | 1872 | } |
| 1871 | 1873 | blob_appendf(pBuf, "%s/%.*s~%s%s", zDir, nBasis, zBasis, zTag, zSuffix); |
| 1872 | 1874 | zTag = 0; |
| 1875 | + for(z=blob_str(pBuf); z!=0 && (z=strpbrk(z,"'\"`;|$&"))!=0; z++){ | |
| 1876 | + z[0] = '_'; | |
| 1877 | + } | |
| 1873 | 1878 | }while( file_size(blob_str(pBuf), ExtFILE)>=0 ); |
| 1874 | 1879 | |
| 1875 | 1880 | #if defined(_WIN32) |
| 1876 | 1881 | fossil_path_free((char *)azDirs[0]); |
| 1877 | 1882 | fossil_path_free((char *)azDirs[1]); |
| 1878 | 1883 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -1780,20 +1780,21 @@ | |
| 1780 | ** the root of zBasis in its name. |
| 1781 | ** |
| 1782 | ** If zTag is not NULL, then try to create the temp-file using zTag |
| 1783 | ** as a differentiator. If that fails, or if zTag is NULL, then use |
| 1784 | ** a bunch of random characters as the tag. |
| 1785 | */ |
| 1786 | void file_tempname(Blob *pBuf, const char *zBasis, const char *zTag){ |
| 1787 | #if defined(_WIN32) |
| 1788 | const char *azDirs[] = { |
| 1789 | 0, /* GetTempPath */ |
| 1790 | 0, /* TEMP */ |
| 1791 | 0, /* TMP */ |
| 1792 | ".", |
| 1793 | }; |
| 1794 | char *z; |
| 1795 | #else |
| 1796 | static const char *azDirs[] = { |
| 1797 | 0, /* TMPDIR */ |
| 1798 | "/var/tmp", |
| 1799 | "/usr/tmp", |
| @@ -1810,10 +1811,11 @@ | |
| 1810 | const char *zDir = "."; |
| 1811 | int cnt = 0; |
| 1812 | char zRand[16]; |
| 1813 | int nBasis; |
| 1814 | const char *zSuffix; |
| 1815 | |
| 1816 | #if defined(_WIN32) |
| 1817 | wchar_t zTmpPath[MAX_PATH]; |
| 1818 | |
| 1819 | if( GetTempPathW(MAX_PATH, zTmpPath) ){ |
| @@ -1868,10 +1870,13 @@ | |
| 1868 | zRand[15] = 0; |
| 1869 | zTag = zRand; |
| 1870 | } |
| 1871 | blob_appendf(pBuf, "%s/%.*s~%s%s", zDir, nBasis, zBasis, zTag, zSuffix); |
| 1872 | zTag = 0; |
| 1873 | }while( file_size(blob_str(pBuf), ExtFILE)>=0 ); |
| 1874 | |
| 1875 | #if defined(_WIN32) |
| 1876 | fossil_path_free((char *)azDirs[0]); |
| 1877 | fossil_path_free((char *)azDirs[1]); |
| 1878 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -1780,20 +1780,21 @@ | |
| 1780 | ** the root of zBasis in its name. |
| 1781 | ** |
| 1782 | ** If zTag is not NULL, then try to create the temp-file using zTag |
| 1783 | ** as a differentiator. If that fails, or if zTag is NULL, then use |
| 1784 | ** a bunch of random characters as the tag. |
| 1785 | ** |
| 1786 | ** Dangerous characters in zBasis are changed. |
| 1787 | */ |
| 1788 | void file_tempname(Blob *pBuf, const char *zBasis, const char *zTag){ |
| 1789 | #if defined(_WIN32) |
| 1790 | const char *azDirs[] = { |
| 1791 | 0, /* GetTempPath */ |
| 1792 | 0, /* TEMP */ |
| 1793 | 0, /* TMP */ |
| 1794 | ".", |
| 1795 | }; |
| 1796 | #else |
| 1797 | static const char *azDirs[] = { |
| 1798 | 0, /* TMPDIR */ |
| 1799 | "/var/tmp", |
| 1800 | "/usr/tmp", |
| @@ -1810,10 +1811,11 @@ | |
| 1811 | const char *zDir = "."; |
| 1812 | int cnt = 0; |
| 1813 | char zRand[16]; |
| 1814 | int nBasis; |
| 1815 | const char *zSuffix; |
| 1816 | char *z; |
| 1817 | |
| 1818 | #if defined(_WIN32) |
| 1819 | wchar_t zTmpPath[MAX_PATH]; |
| 1820 | |
| 1821 | if( GetTempPathW(MAX_PATH, zTmpPath) ){ |
| @@ -1868,10 +1870,13 @@ | |
| 1870 | zRand[15] = 0; |
| 1871 | zTag = zRand; |
| 1872 | } |
| 1873 | blob_appendf(pBuf, "%s/%.*s~%s%s", zDir, nBasis, zBasis, zTag, zSuffix); |
| 1874 | zTag = 0; |
| 1875 | for(z=blob_str(pBuf); z!=0 && (z=strpbrk(z,"'\"`;|$&"))!=0; z++){ |
| 1876 | z[0] = '_'; |
| 1877 | } |
| 1878 | }while( file_size(blob_str(pBuf), ExtFILE)>=0 ); |
| 1879 | |
| 1880 | #if defined(_WIN32) |
| 1881 | fossil_path_free((char *)azDirs[0]); |
| 1882 | fossil_path_free((char *)azDirs[1]); |
| 1883 |