Fossil SCM
Enhance the blob_append_escaped_args() routine with a new parameter to indicate if the argument is a filename. Only prepend "./" to filename arguments that begin with "-". The "%$" printf conversion assumes a filename, but the "%!$" conversion does not.
Commit
4f83d06275804a8320e79fd90df1cc990fb4fd23a2b54b85927609f5f9c4efbc
Parent
ffe2a84ceca6a17…
10 files changed
+3
-3
+1
-1
+27
-11
+3
-3
+3
-3
+6
-6
+5
-4
+8
-8
+4
-2
+5
-5
+3
-3
| --- src/backoffice.c | ||
| +++ src/backoffice.c | ||
| @@ -754,11 +754,11 @@ | ||
| 754 | 754 | && (nMin<=0 || aLastRun[i]+nMin>iNow) |
| 755 | 755 | ){ |
| 756 | 756 | continue; /* Not yet time to run this one */ |
| 757 | 757 | } |
| 758 | 758 | blob_init(&cmd, 0, 0); |
| 759 | - blob_append_escaped_arg(&cmd, g.nameOfExe); | |
| 759 | + blob_append_escaped_arg(&cmd, g.nameOfExe, 1); | |
| 760 | 760 | blob_append(&cmd, " backoffice --nodelay", -1); |
| 761 | 761 | if( g.fAnyTrace ){ |
| 762 | 762 | blob_append(&cmd, " --trace", -1); |
| 763 | 763 | } |
| 764 | 764 | if( bDebug ){ |
| @@ -767,13 +767,13 @@ | ||
| 767 | 767 | if( nPoll>0 ){ |
| 768 | 768 | blob_append(&cmd, " --nolease", -1); |
| 769 | 769 | } |
| 770 | 770 | if( backofficeLogfile ){ |
| 771 | 771 | blob_append(&cmd, " --logfile", -1); |
| 772 | - blob_append_escaped_arg(&cmd, backofficeLogfile); | |
| 772 | + blob_append_escaped_arg(&cmd, backofficeLogfile, 1); | |
| 773 | 773 | } |
| 774 | - blob_append_escaped_arg(&cmd, g.argv[i]); | |
| 774 | + blob_append_escaped_arg(&cmd, g.argv[i], 1); | |
| 775 | 775 | nCmd++; |
| 776 | 776 | if( bDebug ){ |
| 777 | 777 | fossil_print("COMMAND[%u]: %s\n", nCmd, blob_str(&cmd)); |
| 778 | 778 | } |
| 779 | 779 | fossil_system(blob_str(&cmd)); |
| 780 | 780 |
| --- src/backoffice.c | |
| +++ src/backoffice.c | |
| @@ -754,11 +754,11 @@ | |
| 754 | && (nMin<=0 || aLastRun[i]+nMin>iNow) |
| 755 | ){ |
| 756 | continue; /* Not yet time to run this one */ |
| 757 | } |
| 758 | blob_init(&cmd, 0, 0); |
| 759 | blob_append_escaped_arg(&cmd, g.nameOfExe); |
| 760 | blob_append(&cmd, " backoffice --nodelay", -1); |
| 761 | if( g.fAnyTrace ){ |
| 762 | blob_append(&cmd, " --trace", -1); |
| 763 | } |
| 764 | if( bDebug ){ |
| @@ -767,13 +767,13 @@ | |
| 767 | if( nPoll>0 ){ |
| 768 | blob_append(&cmd, " --nolease", -1); |
| 769 | } |
| 770 | if( backofficeLogfile ){ |
| 771 | blob_append(&cmd, " --logfile", -1); |
| 772 | blob_append_escaped_arg(&cmd, backofficeLogfile); |
| 773 | } |
| 774 | blob_append_escaped_arg(&cmd, g.argv[i]); |
| 775 | nCmd++; |
| 776 | if( bDebug ){ |
| 777 | fossil_print("COMMAND[%u]: %s\n", nCmd, blob_str(&cmd)); |
| 778 | } |
| 779 | fossil_system(blob_str(&cmd)); |
| 780 |
| --- src/backoffice.c | |
| +++ src/backoffice.c | |
| @@ -754,11 +754,11 @@ | |
| 754 | && (nMin<=0 || aLastRun[i]+nMin>iNow) |
| 755 | ){ |
| 756 | continue; /* Not yet time to run this one */ |
| 757 | } |
| 758 | blob_init(&cmd, 0, 0); |
| 759 | blob_append_escaped_arg(&cmd, g.nameOfExe, 1); |
| 760 | blob_append(&cmd, " backoffice --nodelay", -1); |
| 761 | if( g.fAnyTrace ){ |
| 762 | blob_append(&cmd, " --trace", -1); |
| 763 | } |
| 764 | if( bDebug ){ |
| @@ -767,13 +767,13 @@ | |
| 767 | if( nPoll>0 ){ |
| 768 | blob_append(&cmd, " --nolease", -1); |
| 769 | } |
| 770 | if( backofficeLogfile ){ |
| 771 | blob_append(&cmd, " --logfile", -1); |
| 772 | blob_append_escaped_arg(&cmd, backofficeLogfile, 1); |
| 773 | } |
| 774 | blob_append_escaped_arg(&cmd, g.argv[i], 1); |
| 775 | nCmd++; |
| 776 | if( bDebug ){ |
| 777 | fossil_print("COMMAND[%u]: %s\n", nCmd, blob_str(&cmd)); |
| 778 | } |
| 779 | fossil_system(blob_str(&cmd)); |
| 780 |
+1
-1
| --- src/bisect.c | ||
| +++ src/bisect.c | ||
| @@ -411,11 +411,11 @@ | ||
| 411 | 411 | } |
| 412 | 412 | while( db_lget_int("bisect-complete",0)==0 ){ |
| 413 | 413 | int rc; |
| 414 | 414 | Blob cmd; |
| 415 | 415 | blob_init(&cmd, 0, 0); |
| 416 | - blob_append_escaped_arg(&cmd, g.nameOfExe); | |
| 416 | + blob_append_escaped_arg(&cmd, g.nameOfExe, 1); | |
| 417 | 417 | rc = fossil_unsafe_system(zCmd); |
| 418 | 418 | if( isInteractive ){ |
| 419 | 419 | Blob in; |
| 420 | 420 | fossil_print("test-command result: %d\n", rc); |
| 421 | 421 | while(1){ |
| 422 | 422 |
| --- src/bisect.c | |
| +++ src/bisect.c | |
| @@ -411,11 +411,11 @@ | |
| 411 | } |
| 412 | while( db_lget_int("bisect-complete",0)==0 ){ |
| 413 | int rc; |
| 414 | Blob cmd; |
| 415 | blob_init(&cmd, 0, 0); |
| 416 | blob_append_escaped_arg(&cmd, g.nameOfExe); |
| 417 | rc = fossil_unsafe_system(zCmd); |
| 418 | if( isInteractive ){ |
| 419 | Blob in; |
| 420 | fossil_print("test-command result: %d\n", rc); |
| 421 | while(1){ |
| 422 |
| --- src/bisect.c | |
| +++ src/bisect.c | |
| @@ -411,11 +411,11 @@ | |
| 411 | } |
| 412 | while( db_lget_int("bisect-complete",0)==0 ){ |
| 413 | int rc; |
| 414 | Blob cmd; |
| 415 | blob_init(&cmd, 0, 0); |
| 416 | blob_append_escaped_arg(&cmd, g.nameOfExe, 1); |
| 417 | rc = fossil_unsafe_system(zCmd); |
| 418 | if( isInteractive ){ |
| 419 | Blob in; |
| 420 | fossil_print("test-command result: %d\n", rc); |
| 421 | while(1){ |
| 422 |
+27
-11
| --- src/blob.c | ||
| +++ src/blob.c | ||
| @@ -1367,17 +1367,18 @@ | ||
| 1367 | 1367 | ** |
| 1368 | 1368 | ** The argument is escaped if it contains white space or other characters |
| 1369 | 1369 | ** that need to be escaped for the shell. If zIn contains characters |
| 1370 | 1370 | ** that cannot be safely escaped, then throw a fatal error. |
| 1371 | 1371 | ** |
| 1372 | -** The argument is expected to be a filename. As shell commands | |
| 1373 | -** commonly have command-line options that begin with "-" and since we | |
| 1374 | -** do not want an attacker to be able to invoke these switches using | |
| 1375 | -** filenames that begin with "-", if zIn begins with "-", prepend | |
| 1376 | -** an additional "./" (or ".\\" on Windows). | |
| 1372 | +** If the isFilename argument is true, then the argument is expected | |
| 1373 | +** to be a filename. As shell commands commonly have command-line | |
| 1374 | +** options that begin with "-" and since we do not want an attacker | |
| 1375 | +** to be able to invoke these switches using filenames that begin | |
| 1376 | +** with "-", if zIn begins with "-", prepend an additional "./" | |
| 1377 | +** (or ".\\" on Windows). | |
| 1377 | 1378 | */ |
| 1378 | -void blob_append_escaped_arg(Blob *pBlob, const char *zIn){ | |
| 1379 | +void blob_append_escaped_arg(Blob *pBlob, const char *zIn, int isFilename){ | |
| 1379 | 1380 | int i; |
| 1380 | 1381 | unsigned char c; |
| 1381 | 1382 | int needEscape = 0; |
| 1382 | 1383 | int n = blob_size(pBlob); |
| 1383 | 1384 | char *z = blob_buffer(pBlob); |
| @@ -1418,11 +1419,11 @@ | ||
| 1418 | 1419 | blob_append_char(pBlob, ' '); |
| 1419 | 1420 | } |
| 1420 | 1421 | |
| 1421 | 1422 | /* Check for characters that need quoting */ |
| 1422 | 1423 | if( !needEscape ){ |
| 1423 | - if( zIn[0]=='-' ){ | |
| 1424 | + if( isFilename && zIn[0]=='-' ){ | |
| 1424 | 1425 | blob_append_char(pBlob, '.'); |
| 1425 | 1426 | #if defined(_WIN32) |
| 1426 | 1427 | blob_append_char(pBlob, '\\'); |
| 1427 | 1428 | #else |
| 1428 | 1429 | blob_append_char(pBlob, '/'); |
| @@ -1434,11 +1435,11 @@ | ||
| 1434 | 1435 | /* Quoting strategy for windows: |
| 1435 | 1436 | ** Put the entire name inside of "...". Any " characters within |
| 1436 | 1437 | ** the name get doubled. |
| 1437 | 1438 | */ |
| 1438 | 1439 | blob_append_char(pBlob, '"'); |
| 1439 | - if( zIn[0]=='-' ){ | |
| 1440 | + if( isFilename && zIn[0]=='-' ){ | |
| 1440 | 1441 | blob_append_char(pBlob, '.'); |
| 1441 | 1442 | blob_append_char(pBlob, '\\'); |
| 1442 | 1443 | }else if( zIn[0]=='/' ){ |
| 1443 | 1444 | blob_append_char(pBlob, '.'); |
| 1444 | 1445 | } |
| @@ -1452,21 +1453,21 @@ | ||
| 1452 | 1453 | ** If the name does not contain ', then surround the whole thing |
| 1453 | 1454 | ** with '...'. If there is one or more ' characters within the |
| 1454 | 1455 | ** name, then put \ before each special character. |
| 1455 | 1456 | */ |
| 1456 | 1457 | if( strchr(zIn,'\'') ){ |
| 1457 | - if( zIn[0]=='-' ){ | |
| 1458 | + if( isFilename && zIn[0]=='-' ){ | |
| 1458 | 1459 | blob_append_char(pBlob, '.'); |
| 1459 | 1460 | blob_append_char(pBlob, '/'); |
| 1460 | 1461 | } |
| 1461 | 1462 | for(i=0; (c = (unsigned char)zIn[i])!=0; i++){ |
| 1462 | 1463 | if( aSafeChar[c] && aSafeChar[c]!=2 ) blob_append_char(pBlob, '\\'); |
| 1463 | 1464 | blob_append_char(pBlob, (char)c); |
| 1464 | 1465 | } |
| 1465 | 1466 | }else{ |
| 1466 | 1467 | blob_append_char(pBlob, '\''); |
| 1467 | - if( zIn[0]=='-' ){ | |
| 1468 | + if( isFilename && zIn[0]=='-' ){ | |
| 1468 | 1469 | blob_append_char(pBlob, '.'); |
| 1469 | 1470 | blob_append_char(pBlob, '/'); |
| 1470 | 1471 | } |
| 1471 | 1472 | blob_append(pBlob, zIn, -1); |
| 1472 | 1473 | blob_append_char(pBlob, '\''); |
| @@ -1484,10 +1485,14 @@ | ||
| 1484 | 1485 | ** result. Append each argument to "fossil test-echo" and run that |
| 1485 | 1486 | ** using fossil_system() to verify that it really does get escaped |
| 1486 | 1487 | ** correctly. |
| 1487 | 1488 | ** |
| 1488 | 1489 | ** Other options: |
| 1490 | +** | |
| 1491 | +** --filename-args BOOL Subsequent arguments are assumed to be | |
| 1492 | +** filenames if BOOL is true, or not if BOOL | |
| 1493 | +** is false. Defaults on. | |
| 1489 | 1494 | ** |
| 1490 | 1495 | ** --hex HEX Skip the --hex flag and instead decode HEX |
| 1491 | 1496 | ** into ascii. This provides a way to insert |
| 1492 | 1497 | ** unusual characters as an argument for testing. |
| 1493 | 1498 | ** |
| @@ -1501,10 +1506,11 @@ | ||
| 1501 | 1506 | */ |
| 1502 | 1507 | void test_escaped_arg_command(void){ |
| 1503 | 1508 | int i; |
| 1504 | 1509 | Blob x; |
| 1505 | 1510 | const char *zArg; |
| 1511 | + int isFilename = 1; | |
| 1506 | 1512 | char zBuf[100]; |
| 1507 | 1513 | blob_init(&x, 0, 0); |
| 1508 | 1514 | for(i=2; i<g.argc; i++){ |
| 1509 | 1515 | zArg = g.argv[i]; |
| 1510 | 1516 | if( fossil_strcmp(zArg, "--hex")==0 && i+1<g.argc ){ |
| @@ -1586,13 +1592,23 @@ | ||
| 1586 | 1592 | rc = fossil_system(blob_str(&x)); |
| 1587 | 1593 | if( rc ) fossil_fatal("failed test (%d): %s\n", rc, blob_str(&x)); |
| 1588 | 1594 | blob_reset(&x); |
| 1589 | 1595 | } |
| 1590 | 1596 | continue; |
| 1597 | + }else if( fossil_strcmp(zArg, "--filename-args")==0 ){ | |
| 1598 | + if( i+1<g.argc ){ | |
| 1599 | + i++; | |
| 1600 | + isFilename = is_truth(g.argv[i]); | |
| 1601 | + } | |
| 1602 | + continue; | |
| 1591 | 1603 | } |
| 1592 | 1604 | fossil_print("%3d [%s]: ", i, zArg); |
| 1593 | - blob_appendf(&x, "%$ test-echo %$", g.nameOfExe, zArg); | |
| 1605 | + if( isFilename ){ | |
| 1606 | + blob_appendf(&x, "%$ test-echo %$", g.nameOfExe, zArg); | |
| 1607 | + }else{ | |
| 1608 | + blob_appendf(&x, "%$ test-echo %!$", g.nameOfExe, zArg); | |
| 1609 | + } | |
| 1594 | 1610 | fossil_print("%s\n", blob_str(&x)); |
| 1595 | 1611 | fossil_system(blob_str(&x)); |
| 1596 | 1612 | blob_reset(&x); |
| 1597 | 1613 | } |
| 1598 | 1614 | } |
| 1599 | 1615 |
| --- src/blob.c | |
| +++ src/blob.c | |
| @@ -1367,17 +1367,18 @@ | |
| 1367 | ** |
| 1368 | ** The argument is escaped if it contains white space or other characters |
| 1369 | ** that need to be escaped for the shell. If zIn contains characters |
| 1370 | ** that cannot be safely escaped, then throw a fatal error. |
| 1371 | ** |
| 1372 | ** The argument is expected to be a filename. As shell commands |
| 1373 | ** commonly have command-line options that begin with "-" and since we |
| 1374 | ** do not want an attacker to be able to invoke these switches using |
| 1375 | ** filenames that begin with "-", if zIn begins with "-", prepend |
| 1376 | ** an additional "./" (or ".\\" on Windows). |
| 1377 | */ |
| 1378 | void blob_append_escaped_arg(Blob *pBlob, const char *zIn){ |
| 1379 | int i; |
| 1380 | unsigned char c; |
| 1381 | int needEscape = 0; |
| 1382 | int n = blob_size(pBlob); |
| 1383 | char *z = blob_buffer(pBlob); |
| @@ -1418,11 +1419,11 @@ | |
| 1418 | blob_append_char(pBlob, ' '); |
| 1419 | } |
| 1420 | |
| 1421 | /* Check for characters that need quoting */ |
| 1422 | if( !needEscape ){ |
| 1423 | if( zIn[0]=='-' ){ |
| 1424 | blob_append_char(pBlob, '.'); |
| 1425 | #if defined(_WIN32) |
| 1426 | blob_append_char(pBlob, '\\'); |
| 1427 | #else |
| 1428 | blob_append_char(pBlob, '/'); |
| @@ -1434,11 +1435,11 @@ | |
| 1434 | /* Quoting strategy for windows: |
| 1435 | ** Put the entire name inside of "...". Any " characters within |
| 1436 | ** the name get doubled. |
| 1437 | */ |
| 1438 | blob_append_char(pBlob, '"'); |
| 1439 | if( zIn[0]=='-' ){ |
| 1440 | blob_append_char(pBlob, '.'); |
| 1441 | blob_append_char(pBlob, '\\'); |
| 1442 | }else if( zIn[0]=='/' ){ |
| 1443 | blob_append_char(pBlob, '.'); |
| 1444 | } |
| @@ -1452,21 +1453,21 @@ | |
| 1452 | ** If the name does not contain ', then surround the whole thing |
| 1453 | ** with '...'. If there is one or more ' characters within the |
| 1454 | ** name, then put \ before each special character. |
| 1455 | */ |
| 1456 | if( strchr(zIn,'\'') ){ |
| 1457 | if( zIn[0]=='-' ){ |
| 1458 | blob_append_char(pBlob, '.'); |
| 1459 | blob_append_char(pBlob, '/'); |
| 1460 | } |
| 1461 | for(i=0; (c = (unsigned char)zIn[i])!=0; i++){ |
| 1462 | if( aSafeChar[c] && aSafeChar[c]!=2 ) blob_append_char(pBlob, '\\'); |
| 1463 | blob_append_char(pBlob, (char)c); |
| 1464 | } |
| 1465 | }else{ |
| 1466 | blob_append_char(pBlob, '\''); |
| 1467 | if( zIn[0]=='-' ){ |
| 1468 | blob_append_char(pBlob, '.'); |
| 1469 | blob_append_char(pBlob, '/'); |
| 1470 | } |
| 1471 | blob_append(pBlob, zIn, -1); |
| 1472 | blob_append_char(pBlob, '\''); |
| @@ -1484,10 +1485,14 @@ | |
| 1484 | ** result. Append each argument to "fossil test-echo" and run that |
| 1485 | ** using fossil_system() to verify that it really does get escaped |
| 1486 | ** correctly. |
| 1487 | ** |
| 1488 | ** Other options: |
| 1489 | ** |
| 1490 | ** --hex HEX Skip the --hex flag and instead decode HEX |
| 1491 | ** into ascii. This provides a way to insert |
| 1492 | ** unusual characters as an argument for testing. |
| 1493 | ** |
| @@ -1501,10 +1506,11 @@ | |
| 1501 | */ |
| 1502 | void test_escaped_arg_command(void){ |
| 1503 | int i; |
| 1504 | Blob x; |
| 1505 | const char *zArg; |
| 1506 | char zBuf[100]; |
| 1507 | blob_init(&x, 0, 0); |
| 1508 | for(i=2; i<g.argc; i++){ |
| 1509 | zArg = g.argv[i]; |
| 1510 | if( fossil_strcmp(zArg, "--hex")==0 && i+1<g.argc ){ |
| @@ -1586,13 +1592,23 @@ | |
| 1586 | rc = fossil_system(blob_str(&x)); |
| 1587 | if( rc ) fossil_fatal("failed test (%d): %s\n", rc, blob_str(&x)); |
| 1588 | blob_reset(&x); |
| 1589 | } |
| 1590 | continue; |
| 1591 | } |
| 1592 | fossil_print("%3d [%s]: ", i, zArg); |
| 1593 | blob_appendf(&x, "%$ test-echo %$", g.nameOfExe, zArg); |
| 1594 | fossil_print("%s\n", blob_str(&x)); |
| 1595 | fossil_system(blob_str(&x)); |
| 1596 | blob_reset(&x); |
| 1597 | } |
| 1598 | } |
| 1599 |
| --- src/blob.c | |
| +++ src/blob.c | |
| @@ -1367,17 +1367,18 @@ | |
| 1367 | ** |
| 1368 | ** The argument is escaped if it contains white space or other characters |
| 1369 | ** that need to be escaped for the shell. If zIn contains characters |
| 1370 | ** that cannot be safely escaped, then throw a fatal error. |
| 1371 | ** |
| 1372 | ** If the isFilename argument is true, then the argument is expected |
| 1373 | ** to be a filename. As shell commands commonly have command-line |
| 1374 | ** options that begin with "-" and since we do not want an attacker |
| 1375 | ** to be able to invoke these switches using filenames that begin |
| 1376 | ** with "-", if zIn begins with "-", prepend an additional "./" |
| 1377 | ** (or ".\\" on Windows). |
| 1378 | */ |
| 1379 | void blob_append_escaped_arg(Blob *pBlob, const char *zIn, int isFilename){ |
| 1380 | int i; |
| 1381 | unsigned char c; |
| 1382 | int needEscape = 0; |
| 1383 | int n = blob_size(pBlob); |
| 1384 | char *z = blob_buffer(pBlob); |
| @@ -1418,11 +1419,11 @@ | |
| 1419 | blob_append_char(pBlob, ' '); |
| 1420 | } |
| 1421 | |
| 1422 | /* Check for characters that need quoting */ |
| 1423 | if( !needEscape ){ |
| 1424 | if( isFilename && zIn[0]=='-' ){ |
| 1425 | blob_append_char(pBlob, '.'); |
| 1426 | #if defined(_WIN32) |
| 1427 | blob_append_char(pBlob, '\\'); |
| 1428 | #else |
| 1429 | blob_append_char(pBlob, '/'); |
| @@ -1434,11 +1435,11 @@ | |
| 1435 | /* Quoting strategy for windows: |
| 1436 | ** Put the entire name inside of "...". Any " characters within |
| 1437 | ** the name get doubled. |
| 1438 | */ |
| 1439 | blob_append_char(pBlob, '"'); |
| 1440 | if( isFilename && zIn[0]=='-' ){ |
| 1441 | blob_append_char(pBlob, '.'); |
| 1442 | blob_append_char(pBlob, '\\'); |
| 1443 | }else if( zIn[0]=='/' ){ |
| 1444 | blob_append_char(pBlob, '.'); |
| 1445 | } |
| @@ -1452,21 +1453,21 @@ | |
| 1453 | ** If the name does not contain ', then surround the whole thing |
| 1454 | ** with '...'. If there is one or more ' characters within the |
| 1455 | ** name, then put \ before each special character. |
| 1456 | */ |
| 1457 | if( strchr(zIn,'\'') ){ |
| 1458 | if( isFilename && zIn[0]=='-' ){ |
| 1459 | blob_append_char(pBlob, '.'); |
| 1460 | blob_append_char(pBlob, '/'); |
| 1461 | } |
| 1462 | for(i=0; (c = (unsigned char)zIn[i])!=0; i++){ |
| 1463 | if( aSafeChar[c] && aSafeChar[c]!=2 ) blob_append_char(pBlob, '\\'); |
| 1464 | blob_append_char(pBlob, (char)c); |
| 1465 | } |
| 1466 | }else{ |
| 1467 | blob_append_char(pBlob, '\''); |
| 1468 | if( isFilename && zIn[0]=='-' ){ |
| 1469 | blob_append_char(pBlob, '.'); |
| 1470 | blob_append_char(pBlob, '/'); |
| 1471 | } |
| 1472 | blob_append(pBlob, zIn, -1); |
| 1473 | blob_append_char(pBlob, '\''); |
| @@ -1484,10 +1485,14 @@ | |
| 1485 | ** result. Append each argument to "fossil test-echo" and run that |
| 1486 | ** using fossil_system() to verify that it really does get escaped |
| 1487 | ** correctly. |
| 1488 | ** |
| 1489 | ** Other options: |
| 1490 | ** |
| 1491 | ** --filename-args BOOL Subsequent arguments are assumed to be |
| 1492 | ** filenames if BOOL is true, or not if BOOL |
| 1493 | ** is false. Defaults on. |
| 1494 | ** |
| 1495 | ** --hex HEX Skip the --hex flag and instead decode HEX |
| 1496 | ** into ascii. This provides a way to insert |
| 1497 | ** unusual characters as an argument for testing. |
| 1498 | ** |
| @@ -1501,10 +1506,11 @@ | |
| 1506 | */ |
| 1507 | void test_escaped_arg_command(void){ |
| 1508 | int i; |
| 1509 | Blob x; |
| 1510 | const char *zArg; |
| 1511 | int isFilename = 1; |
| 1512 | char zBuf[100]; |
| 1513 | blob_init(&x, 0, 0); |
| 1514 | for(i=2; i<g.argc; i++){ |
| 1515 | zArg = g.argv[i]; |
| 1516 | if( fossil_strcmp(zArg, "--hex")==0 && i+1<g.argc ){ |
| @@ -1586,13 +1592,23 @@ | |
| 1592 | rc = fossil_system(blob_str(&x)); |
| 1593 | if( rc ) fossil_fatal("failed test (%d): %s\n", rc, blob_str(&x)); |
| 1594 | blob_reset(&x); |
| 1595 | } |
| 1596 | continue; |
| 1597 | }else if( fossil_strcmp(zArg, "--filename-args")==0 ){ |
| 1598 | if( i+1<g.argc ){ |
| 1599 | i++; |
| 1600 | isFilename = is_truth(g.argv[i]); |
| 1601 | } |
| 1602 | continue; |
| 1603 | } |
| 1604 | fossil_print("%3d [%s]: ", i, zArg); |
| 1605 | if( isFilename ){ |
| 1606 | blob_appendf(&x, "%$ test-echo %$", g.nameOfExe, zArg); |
| 1607 | }else{ |
| 1608 | blob_appendf(&x, "%$ test-echo %!$", g.nameOfExe, zArg); |
| 1609 | } |
| 1610 | fossil_print("%s\n", blob_str(&x)); |
| 1611 | fossil_system(blob_str(&x)); |
| 1612 | blob_reset(&x); |
| 1613 | } |
| 1614 | } |
| 1615 |
+3
-3
| --- src/clone.c | ||
| +++ src/clone.c | ||
| @@ -290,15 +290,15 @@ | ||
| 290 | 290 | if( zWorkDir!=0 && zWorkDir[0]!=0 && !noOpen ){ |
| 291 | 291 | Blob cmd; |
| 292 | 292 | fossil_print("opening the new %s repository in directory %s...\n", |
| 293 | 293 | zRepo, zWorkDir); |
| 294 | 294 | blob_init(&cmd, 0, 0); |
| 295 | - blob_append_escaped_arg(&cmd, g.nameOfExe); | |
| 295 | + blob_append_escaped_arg(&cmd, g.nameOfExe, 1); | |
| 296 | 296 | blob_append(&cmd, " open ", -1); |
| 297 | - blob_append_escaped_arg(&cmd, zRepo); | |
| 297 | + blob_append_escaped_arg(&cmd, zRepo, 1); | |
| 298 | 298 | blob_append(&cmd, " --workdir ", -1); |
| 299 | - blob_append_escaped_arg(&cmd, zWorkDir); | |
| 299 | + blob_append_escaped_arg(&cmd, zWorkDir, 1); | |
| 300 | 300 | if( allowNested ){ |
| 301 | 301 | blob_append(&cmd, " --nested", -1); |
| 302 | 302 | } |
| 303 | 303 | fossil_system(blob_str(&cmd)); |
| 304 | 304 | blob_reset(&cmd); |
| 305 | 305 |
| --- src/clone.c | |
| +++ src/clone.c | |
| @@ -290,15 +290,15 @@ | |
| 290 | if( zWorkDir!=0 && zWorkDir[0]!=0 && !noOpen ){ |
| 291 | Blob cmd; |
| 292 | fossil_print("opening the new %s repository in directory %s...\n", |
| 293 | zRepo, zWorkDir); |
| 294 | blob_init(&cmd, 0, 0); |
| 295 | blob_append_escaped_arg(&cmd, g.nameOfExe); |
| 296 | blob_append(&cmd, " open ", -1); |
| 297 | blob_append_escaped_arg(&cmd, zRepo); |
| 298 | blob_append(&cmd, " --workdir ", -1); |
| 299 | blob_append_escaped_arg(&cmd, zWorkDir); |
| 300 | if( allowNested ){ |
| 301 | blob_append(&cmd, " --nested", -1); |
| 302 | } |
| 303 | fossil_system(blob_str(&cmd)); |
| 304 | blob_reset(&cmd); |
| 305 |
| --- src/clone.c | |
| +++ src/clone.c | |
| @@ -290,15 +290,15 @@ | |
| 290 | if( zWorkDir!=0 && zWorkDir[0]!=0 && !noOpen ){ |
| 291 | Blob cmd; |
| 292 | fossil_print("opening the new %s repository in directory %s...\n", |
| 293 | zRepo, zWorkDir); |
| 294 | blob_init(&cmd, 0, 0); |
| 295 | blob_append_escaped_arg(&cmd, g.nameOfExe, 1); |
| 296 | blob_append(&cmd, " open ", -1); |
| 297 | blob_append_escaped_arg(&cmd, zRepo, 1); |
| 298 | blob_append(&cmd, " --workdir ", -1); |
| 299 | blob_append_escaped_arg(&cmd, zWorkDir, 1); |
| 300 | if( allowNested ){ |
| 301 | blob_append(&cmd, " --nested", -1); |
| 302 | } |
| 303 | fossil_system(blob_str(&cmd)); |
| 304 | blob_reset(&cmd); |
| 305 |
M
src/db.c
+3
-3
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -3599,14 +3599,14 @@ | ||
| 3599 | 3599 | } |
| 3600 | 3600 | if( zRepoDir==0 ) zRepoDir = zPwd; |
| 3601 | 3601 | zRepo = mprintf("%s/%s.fossil", zRepoDir, zNewBase); |
| 3602 | 3602 | fossil_free(zNewBase); |
| 3603 | 3603 | blob_init(&cmd, 0, 0); |
| 3604 | - blob_append_escaped_arg(&cmd, g.nameOfExe); | |
| 3604 | + blob_append_escaped_arg(&cmd, g.nameOfExe, 1); | |
| 3605 | 3605 | blob_append(&cmd, " clone", -1); |
| 3606 | - blob_append_escaped_arg(&cmd, zUri); | |
| 3607 | - blob_append_escaped_arg(&cmd, zRepo); | |
| 3606 | + blob_append_escaped_arg(&cmd, zUri, 1); | |
| 3607 | + blob_append_escaped_arg(&cmd, zRepo, 1); | |
| 3608 | 3608 | zCmd = blob_str(&cmd); |
| 3609 | 3609 | fossil_print("%s\n", zCmd); |
| 3610 | 3610 | if( zWorkDir ) file_chdir(zPwd, 0); |
| 3611 | 3611 | rc = fossil_system(zCmd); |
| 3612 | 3612 | if( rc ){ |
| 3613 | 3613 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -3599,14 +3599,14 @@ | |
| 3599 | } |
| 3600 | if( zRepoDir==0 ) zRepoDir = zPwd; |
| 3601 | zRepo = mprintf("%s/%s.fossil", zRepoDir, zNewBase); |
| 3602 | fossil_free(zNewBase); |
| 3603 | blob_init(&cmd, 0, 0); |
| 3604 | blob_append_escaped_arg(&cmd, g.nameOfExe); |
| 3605 | blob_append(&cmd, " clone", -1); |
| 3606 | blob_append_escaped_arg(&cmd, zUri); |
| 3607 | blob_append_escaped_arg(&cmd, zRepo); |
| 3608 | zCmd = blob_str(&cmd); |
| 3609 | fossil_print("%s\n", zCmd); |
| 3610 | if( zWorkDir ) file_chdir(zPwd, 0); |
| 3611 | rc = fossil_system(zCmd); |
| 3612 | if( rc ){ |
| 3613 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -3599,14 +3599,14 @@ | |
| 3599 | } |
| 3600 | if( zRepoDir==0 ) zRepoDir = zPwd; |
| 3601 | zRepo = mprintf("%s/%s.fossil", zRepoDir, zNewBase); |
| 3602 | fossil_free(zNewBase); |
| 3603 | blob_init(&cmd, 0, 0); |
| 3604 | blob_append_escaped_arg(&cmd, g.nameOfExe, 1); |
| 3605 | blob_append(&cmd, " clone", -1); |
| 3606 | blob_append_escaped_arg(&cmd, zUri, 1); |
| 3607 | blob_append_escaped_arg(&cmd, zRepo, 1); |
| 3608 | zCmd = blob_str(&cmd); |
| 3609 | fossil_print("%s\n", zCmd); |
| 3610 | if( zWorkDir ) file_chdir(zPwd, 0); |
| 3611 | rc = fossil_system(zCmd); |
| 3612 | if( rc ){ |
| 3613 |
+6
-6
| --- src/diffcmd.c | ||
| +++ src/diffcmd.c | ||
| @@ -271,15 +271,15 @@ | ||
| 271 | 271 | |
| 272 | 272 | /* Construct the external diff command */ |
| 273 | 273 | blob_zero(&cmd); |
| 274 | 274 | blob_append(&cmd, zDiffCmd, -1); |
| 275 | 275 | if( fSwapDiff ){ |
| 276 | - blob_append_escaped_arg(&cmd, zFile2); | |
| 277 | - blob_append_escaped_arg(&cmd, blob_str(&nameFile1)); | |
| 276 | + blob_append_escaped_arg(&cmd, zFile2, 1); | |
| 277 | + blob_append_escaped_arg(&cmd, blob_str(&nameFile1), 1); | |
| 278 | 278 | }else{ |
| 279 | - blob_append_escaped_arg(&cmd, blob_str(&nameFile1)); | |
| 280 | - blob_append_escaped_arg(&cmd, zFile2); | |
| 279 | + blob_append_escaped_arg(&cmd, blob_str(&nameFile1), 1); | |
| 280 | + blob_append_escaped_arg(&cmd, zFile2, 1); | |
| 281 | 281 | } |
| 282 | 282 | |
| 283 | 283 | /* Run the external diff command */ |
| 284 | 284 | fossil_system(blob_str(&cmd)); |
| 285 | 285 | |
| @@ -357,12 +357,12 @@ | ||
| 357 | 357 | blob_write_to_file(pFile2, blob_str(&temp2)); |
| 358 | 358 | |
| 359 | 359 | /* Construct the external diff command */ |
| 360 | 360 | blob_zero(&cmd); |
| 361 | 361 | blob_append(&cmd, zDiffCmd, -1); |
| 362 | - blob_append_escaped_arg(&cmd, blob_str(&temp1)); | |
| 363 | - blob_append_escaped_arg(&cmd, blob_str(&temp2)); | |
| 362 | + blob_append_escaped_arg(&cmd, blob_str(&temp1), 1); | |
| 363 | + blob_append_escaped_arg(&cmd, blob_str(&temp2), 1); | |
| 364 | 364 | |
| 365 | 365 | /* Run the external diff command */ |
| 366 | 366 | fossil_system(blob_str(&cmd)); |
| 367 | 367 | |
| 368 | 368 | /* Delete the temporary file and clean up memory used */ |
| 369 | 369 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -271,15 +271,15 @@ | |
| 271 | |
| 272 | /* Construct the external diff command */ |
| 273 | blob_zero(&cmd); |
| 274 | blob_append(&cmd, zDiffCmd, -1); |
| 275 | if( fSwapDiff ){ |
| 276 | blob_append_escaped_arg(&cmd, zFile2); |
| 277 | blob_append_escaped_arg(&cmd, blob_str(&nameFile1)); |
| 278 | }else{ |
| 279 | blob_append_escaped_arg(&cmd, blob_str(&nameFile1)); |
| 280 | blob_append_escaped_arg(&cmd, zFile2); |
| 281 | } |
| 282 | |
| 283 | /* Run the external diff command */ |
| 284 | fossil_system(blob_str(&cmd)); |
| 285 | |
| @@ -357,12 +357,12 @@ | |
| 357 | blob_write_to_file(pFile2, blob_str(&temp2)); |
| 358 | |
| 359 | /* Construct the external diff command */ |
| 360 | blob_zero(&cmd); |
| 361 | blob_append(&cmd, zDiffCmd, -1); |
| 362 | blob_append_escaped_arg(&cmd, blob_str(&temp1)); |
| 363 | blob_append_escaped_arg(&cmd, blob_str(&temp2)); |
| 364 | |
| 365 | /* Run the external diff command */ |
| 366 | fossil_system(blob_str(&cmd)); |
| 367 | |
| 368 | /* Delete the temporary file and clean up memory used */ |
| 369 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -271,15 +271,15 @@ | |
| 271 | |
| 272 | /* Construct the external diff command */ |
| 273 | blob_zero(&cmd); |
| 274 | blob_append(&cmd, zDiffCmd, -1); |
| 275 | if( fSwapDiff ){ |
| 276 | blob_append_escaped_arg(&cmd, zFile2, 1); |
| 277 | blob_append_escaped_arg(&cmd, blob_str(&nameFile1), 1); |
| 278 | }else{ |
| 279 | blob_append_escaped_arg(&cmd, blob_str(&nameFile1), 1); |
| 280 | blob_append_escaped_arg(&cmd, zFile2, 1); |
| 281 | } |
| 282 | |
| 283 | /* Run the external diff command */ |
| 284 | fossil_system(blob_str(&cmd)); |
| 285 | |
| @@ -357,12 +357,12 @@ | |
| 357 | blob_write_to_file(pFile2, blob_str(&temp2)); |
| 358 | |
| 359 | /* Construct the external diff command */ |
| 360 | blob_zero(&cmd); |
| 361 | blob_append(&cmd, zDiffCmd, -1); |
| 362 | blob_append_escaped_arg(&cmd, blob_str(&temp1), 1); |
| 363 | blob_append_escaped_arg(&cmd, blob_str(&temp2), 1); |
| 364 | |
| 365 | /* Run the external diff command */ |
| 366 | fossil_system(blob_str(&cmd)); |
| 367 | |
| 368 | /* Delete the temporary file and clean up memory used */ |
| 369 |
+5
-4
| --- src/http_transport.c | ||
| +++ src/http_transport.c | ||
| @@ -122,25 +122,26 @@ | ||
| 122 | 122 | socket_ssh_resolve_addr(pUrlData); |
| 123 | 123 | transport_ssh_command(&zCmd); |
| 124 | 124 | if( pUrlData->port!=pUrlData->dfltPort && pUrlData->port ){ |
| 125 | 125 | blob_appendf(&zCmd, " -p %d", pUrlData->port); |
| 126 | 126 | } |
| 127 | + blob_appendf(&zCmd, " --"); /* End of switches */ | |
| 127 | 128 | if( pUrlData->user && pUrlData->user[0] ){ |
| 128 | 129 | zHost = mprintf("%s@%s", pUrlData->user, pUrlData->name); |
| 129 | - blob_append_escaped_arg(&zCmd, zHost); | |
| 130 | + blob_append_escaped_arg(&zCmd, zHost, 0); | |
| 130 | 131 | fossil_free(zHost); |
| 131 | 132 | }else{ |
| 132 | - blob_append_escaped_arg(&zCmd, pUrlData->name); | |
| 133 | + blob_append_escaped_arg(&zCmd, pUrlData->name, 0); | |
| 133 | 134 | } |
| 134 | 135 | if( !is_safe_fossil_command(pUrlData->fossil) ){ |
| 135 | 136 | fossil_fatal("the ssh:// URL is asking to run an unsafe command [%s] on " |
| 136 | 137 | "the server.", pUrlData->fossil); |
| 137 | 138 | } |
| 138 | - blob_append_escaped_arg(&zCmd, pUrlData->fossil); | |
| 139 | + blob_append_escaped_arg(&zCmd, pUrlData->fossil, 1); | |
| 139 | 140 | blob_append(&zCmd, " test-http", 10); |
| 140 | 141 | if( pUrlData->path && pUrlData->path[0] ){ |
| 141 | - blob_append_escaped_arg(&zCmd, pUrlData->path); | |
| 142 | + blob_append_escaped_arg(&zCmd, pUrlData->path, 1); | |
| 142 | 143 | }else{ |
| 143 | 144 | fossil_fatal("ssh:// URI does not specify a path to the repository"); |
| 144 | 145 | } |
| 145 | 146 | if( g.fSshTrace ){ |
| 146 | 147 | fossil_print("%s\n", blob_str(&zCmd)); /* Show the whole SSH command */ |
| 147 | 148 |
| --- src/http_transport.c | |
| +++ src/http_transport.c | |
| @@ -122,25 +122,26 @@ | |
| 122 | socket_ssh_resolve_addr(pUrlData); |
| 123 | transport_ssh_command(&zCmd); |
| 124 | if( pUrlData->port!=pUrlData->dfltPort && pUrlData->port ){ |
| 125 | blob_appendf(&zCmd, " -p %d", pUrlData->port); |
| 126 | } |
| 127 | if( pUrlData->user && pUrlData->user[0] ){ |
| 128 | zHost = mprintf("%s@%s", pUrlData->user, pUrlData->name); |
| 129 | blob_append_escaped_arg(&zCmd, zHost); |
| 130 | fossil_free(zHost); |
| 131 | }else{ |
| 132 | blob_append_escaped_arg(&zCmd, pUrlData->name); |
| 133 | } |
| 134 | if( !is_safe_fossil_command(pUrlData->fossil) ){ |
| 135 | fossil_fatal("the ssh:// URL is asking to run an unsafe command [%s] on " |
| 136 | "the server.", pUrlData->fossil); |
| 137 | } |
| 138 | blob_append_escaped_arg(&zCmd, pUrlData->fossil); |
| 139 | blob_append(&zCmd, " test-http", 10); |
| 140 | if( pUrlData->path && pUrlData->path[0] ){ |
| 141 | blob_append_escaped_arg(&zCmd, pUrlData->path); |
| 142 | }else{ |
| 143 | fossil_fatal("ssh:// URI does not specify a path to the repository"); |
| 144 | } |
| 145 | if( g.fSshTrace ){ |
| 146 | fossil_print("%s\n", blob_str(&zCmd)); /* Show the whole SSH command */ |
| 147 |
| --- src/http_transport.c | |
| +++ src/http_transport.c | |
| @@ -122,25 +122,26 @@ | |
| 122 | socket_ssh_resolve_addr(pUrlData); |
| 123 | transport_ssh_command(&zCmd); |
| 124 | if( pUrlData->port!=pUrlData->dfltPort && pUrlData->port ){ |
| 125 | blob_appendf(&zCmd, " -p %d", pUrlData->port); |
| 126 | } |
| 127 | blob_appendf(&zCmd, " --"); /* End of switches */ |
| 128 | if( pUrlData->user && pUrlData->user[0] ){ |
| 129 | zHost = mprintf("%s@%s", pUrlData->user, pUrlData->name); |
| 130 | blob_append_escaped_arg(&zCmd, zHost, 0); |
| 131 | fossil_free(zHost); |
| 132 | }else{ |
| 133 | blob_append_escaped_arg(&zCmd, pUrlData->name, 0); |
| 134 | } |
| 135 | if( !is_safe_fossil_command(pUrlData->fossil) ){ |
| 136 | fossil_fatal("the ssh:// URL is asking to run an unsafe command [%s] on " |
| 137 | "the server.", pUrlData->fossil); |
| 138 | } |
| 139 | blob_append_escaped_arg(&zCmd, pUrlData->fossil, 1); |
| 140 | blob_append(&zCmd, " test-http", 10); |
| 141 | if( pUrlData->path && pUrlData->path[0] ){ |
| 142 | blob_append_escaped_arg(&zCmd, pUrlData->path, 1); |
| 143 | }else{ |
| 144 | fossil_fatal("ssh:// URI does not specify a path to the repository"); |
| 145 | } |
| 146 | if( g.fSshTrace ){ |
| 147 | fossil_print("%s\n", blob_str(&zCmd)); /* Show the whole SSH command */ |
| 148 |
+8
-8
| --- src/patch.c | ||
| +++ src/patch.c | ||
| @@ -396,11 +396,11 @@ | ||
| 396 | 396 | " WHERE patch.cfg.key='baseline'" |
| 397 | 397 | " AND localdb.vvar.name='checkout-hash'" |
| 398 | 398 | " AND patch.cfg.key<>localdb.vvar.name" |
| 399 | 399 | ); |
| 400 | 400 | if( db_step(&q)==SQLITE_ROW ){ |
| 401 | - blob_append_escaped_arg(&cmd, g.nameOfExe); | |
| 401 | + blob_append_escaped_arg(&cmd, g.nameOfExe, 1); | |
| 402 | 402 | blob_appendf(&cmd, " update %s", db_column_text(&q, 0)); |
| 403 | 403 | if( mFlags & PATCH_VERBOSE ){ |
| 404 | 404 | fossil_print("%-10s %s\n", "BASELINE", db_column_text(&q,0)); |
| 405 | 405 | } |
| 406 | 406 | } |
| @@ -423,11 +423,11 @@ | ||
| 423 | 423 | " WHERE type IN ('merge','cherrypick','backout','integrate')" |
| 424 | 424 | " AND mhash NOT GLOB '*[^a-fA-F0-9]*';" |
| 425 | 425 | ); |
| 426 | 426 | while( db_step(&q)==SQLITE_ROW ){ |
| 427 | 427 | const char *zType = db_column_text(&q,0); |
| 428 | - blob_append_escaped_arg(&cmd, g.nameOfExe); | |
| 428 | + blob_append_escaped_arg(&cmd, g.nameOfExe, 1); | |
| 429 | 429 | if( strcmp(zType,"merge")==0 ){ |
| 430 | 430 | blob_appendf(&cmd, " merge %s\n", db_column_text(&q,1)); |
| 431 | 431 | }else{ |
| 432 | 432 | blob_appendf(&cmd, " merge --%s %s\n", zType, db_column_text(&q,1)); |
| 433 | 433 | } |
| @@ -451,11 +451,11 @@ | ||
| 451 | 451 | |
| 452 | 452 | /* Deletions */ |
| 453 | 453 | db_prepare(&q, "SELECT pathname FROM patch.chng" |
| 454 | 454 | " WHERE origname IS NULL AND delta IS NULL"); |
| 455 | 455 | while( db_step(&q)==SQLITE_ROW ){ |
| 456 | - blob_append_escaped_arg(&cmd, g.nameOfExe); | |
| 456 | + blob_append_escaped_arg(&cmd, g.nameOfExe, 1); | |
| 457 | 457 | blob_appendf(&cmd, " rm --hard %$\n", db_column_text(&q,0)); |
| 458 | 458 | if( mFlags & PATCH_VERBOSE ){ |
| 459 | 459 | fossil_print("%-10s %s\n", "DELETE", db_column_text(&q,0)); |
| 460 | 460 | } |
| 461 | 461 | } |
| @@ -478,11 +478,11 @@ | ||
| 478 | 478 | "SELECT origname, pathname FROM patch.chng" |
| 479 | 479 | " WHERE origname IS NOT NULL" |
| 480 | 480 | " AND origname<>pathname" |
| 481 | 481 | ); |
| 482 | 482 | while( db_step(&q)==SQLITE_ROW ){ |
| 483 | - blob_append_escaped_arg(&cmd, g.nameOfExe); | |
| 483 | + blob_append_escaped_arg(&cmd, g.nameOfExe, 1); | |
| 484 | 484 | blob_appendf(&cmd, " mv --hard %$ %$\n", |
| 485 | 485 | db_column_text(&q,0), db_column_text(&q,1)); |
| 486 | 486 | if( mFlags & PATCH_VERBOSE ){ |
| 487 | 487 | fossil_print("%-10s %s -> %s\n", "RENAME", |
| 488 | 488 | db_column_text(&q,0), db_column_text(&q,1)); |
| @@ -552,11 +552,11 @@ | ||
| 552 | 552 | sqlite3_free(aOut); |
| 553 | 553 | if( mFlags & PATCH_VERBOSE ){ |
| 554 | 554 | fossil_print("%-10s %s\n", "EDIT", zPathname); |
| 555 | 555 | } |
| 556 | 556 | }else{ |
| 557 | - blob_append_escaped_arg(&cmd, g.nameOfExe); | |
| 557 | + blob_append_escaped_arg(&cmd, g.nameOfExe, 1); | |
| 558 | 558 | blob_appendf(&cmd, " add %$\n", zPathname); |
| 559 | 559 | if( mFlags & PATCH_VERBOSE ){ |
| 560 | 560 | fossil_print("%-10s %s\n", "NEW", zPathname); |
| 561 | 561 | } |
| 562 | 562 | } |
| @@ -673,22 +673,22 @@ | ||
| 673 | 673 | zRemote = fossil_strdup(g.argv[3]); |
| 674 | 674 | zDir = strchr(zRemote,':'); |
| 675 | 675 | if( zDir==0 ){ |
| 676 | 676 | zDir = zRemote; |
| 677 | 677 | blob_init(&cmd, 0, 0); |
| 678 | - blob_append_escaped_arg(&cmd, g.nameOfExe); | |
| 678 | + blob_append_escaped_arg(&cmd, g.nameOfExe, 1); | |
| 679 | 679 | blob_appendf(&cmd, " patch %s%s %$ -", zRemoteCmd, zForce, zDir); |
| 680 | 680 | }else{ |
| 681 | 681 | Blob remote; |
| 682 | 682 | zDir[0] = 0; |
| 683 | 683 | zDir++; |
| 684 | 684 | transport_ssh_command(&cmd); |
| 685 | - blob_append_escaped_arg(&cmd, zRemote); | |
| 685 | + blob_append_escaped_arg(&cmd, zRemote, 0); | |
| 686 | 686 | blob_init(&remote, 0, 0); |
| 687 | 687 | blob_appendf(&remote, "fossil patch %s%s --dir64 %z -", |
| 688 | 688 | zRemoteCmd, zForce, encode64(zDir, -1)); |
| 689 | - blob_append_escaped_arg(&cmd, blob_str(&remote)); | |
| 689 | + blob_append_escaped_arg(&cmd, blob_str(&remote), 0); | |
| 690 | 690 | blob_reset(&remote); |
| 691 | 691 | } |
| 692 | 692 | if( mFlags & PATCH_VERBOSE ){ |
| 693 | 693 | fossil_print("# %s\n", blob_str(&cmd)); |
| 694 | 694 | fflush(stdout); |
| 695 | 695 |
| --- src/patch.c | |
| +++ src/patch.c | |
| @@ -396,11 +396,11 @@ | |
| 396 | " WHERE patch.cfg.key='baseline'" |
| 397 | " AND localdb.vvar.name='checkout-hash'" |
| 398 | " AND patch.cfg.key<>localdb.vvar.name" |
| 399 | ); |
| 400 | if( db_step(&q)==SQLITE_ROW ){ |
| 401 | blob_append_escaped_arg(&cmd, g.nameOfExe); |
| 402 | blob_appendf(&cmd, " update %s", db_column_text(&q, 0)); |
| 403 | if( mFlags & PATCH_VERBOSE ){ |
| 404 | fossil_print("%-10s %s\n", "BASELINE", db_column_text(&q,0)); |
| 405 | } |
| 406 | } |
| @@ -423,11 +423,11 @@ | |
| 423 | " WHERE type IN ('merge','cherrypick','backout','integrate')" |
| 424 | " AND mhash NOT GLOB '*[^a-fA-F0-9]*';" |
| 425 | ); |
| 426 | while( db_step(&q)==SQLITE_ROW ){ |
| 427 | const char *zType = db_column_text(&q,0); |
| 428 | blob_append_escaped_arg(&cmd, g.nameOfExe); |
| 429 | if( strcmp(zType,"merge")==0 ){ |
| 430 | blob_appendf(&cmd, " merge %s\n", db_column_text(&q,1)); |
| 431 | }else{ |
| 432 | blob_appendf(&cmd, " merge --%s %s\n", zType, db_column_text(&q,1)); |
| 433 | } |
| @@ -451,11 +451,11 @@ | |
| 451 | |
| 452 | /* Deletions */ |
| 453 | db_prepare(&q, "SELECT pathname FROM patch.chng" |
| 454 | " WHERE origname IS NULL AND delta IS NULL"); |
| 455 | while( db_step(&q)==SQLITE_ROW ){ |
| 456 | blob_append_escaped_arg(&cmd, g.nameOfExe); |
| 457 | blob_appendf(&cmd, " rm --hard %$\n", db_column_text(&q,0)); |
| 458 | if( mFlags & PATCH_VERBOSE ){ |
| 459 | fossil_print("%-10s %s\n", "DELETE", db_column_text(&q,0)); |
| 460 | } |
| 461 | } |
| @@ -478,11 +478,11 @@ | |
| 478 | "SELECT origname, pathname FROM patch.chng" |
| 479 | " WHERE origname IS NOT NULL" |
| 480 | " AND origname<>pathname" |
| 481 | ); |
| 482 | while( db_step(&q)==SQLITE_ROW ){ |
| 483 | blob_append_escaped_arg(&cmd, g.nameOfExe); |
| 484 | blob_appendf(&cmd, " mv --hard %$ %$\n", |
| 485 | db_column_text(&q,0), db_column_text(&q,1)); |
| 486 | if( mFlags & PATCH_VERBOSE ){ |
| 487 | fossil_print("%-10s %s -> %s\n", "RENAME", |
| 488 | db_column_text(&q,0), db_column_text(&q,1)); |
| @@ -552,11 +552,11 @@ | |
| 552 | sqlite3_free(aOut); |
| 553 | if( mFlags & PATCH_VERBOSE ){ |
| 554 | fossil_print("%-10s %s\n", "EDIT", zPathname); |
| 555 | } |
| 556 | }else{ |
| 557 | blob_append_escaped_arg(&cmd, g.nameOfExe); |
| 558 | blob_appendf(&cmd, " add %$\n", zPathname); |
| 559 | if( mFlags & PATCH_VERBOSE ){ |
| 560 | fossil_print("%-10s %s\n", "NEW", zPathname); |
| 561 | } |
| 562 | } |
| @@ -673,22 +673,22 @@ | |
| 673 | zRemote = fossil_strdup(g.argv[3]); |
| 674 | zDir = strchr(zRemote,':'); |
| 675 | if( zDir==0 ){ |
| 676 | zDir = zRemote; |
| 677 | blob_init(&cmd, 0, 0); |
| 678 | blob_append_escaped_arg(&cmd, g.nameOfExe); |
| 679 | blob_appendf(&cmd, " patch %s%s %$ -", zRemoteCmd, zForce, zDir); |
| 680 | }else{ |
| 681 | Blob remote; |
| 682 | zDir[0] = 0; |
| 683 | zDir++; |
| 684 | transport_ssh_command(&cmd); |
| 685 | blob_append_escaped_arg(&cmd, zRemote); |
| 686 | blob_init(&remote, 0, 0); |
| 687 | blob_appendf(&remote, "fossil patch %s%s --dir64 %z -", |
| 688 | zRemoteCmd, zForce, encode64(zDir, -1)); |
| 689 | blob_append_escaped_arg(&cmd, blob_str(&remote)); |
| 690 | blob_reset(&remote); |
| 691 | } |
| 692 | if( mFlags & PATCH_VERBOSE ){ |
| 693 | fossil_print("# %s\n", blob_str(&cmd)); |
| 694 | fflush(stdout); |
| 695 |
| --- src/patch.c | |
| +++ src/patch.c | |
| @@ -396,11 +396,11 @@ | |
| 396 | " WHERE patch.cfg.key='baseline'" |
| 397 | " AND localdb.vvar.name='checkout-hash'" |
| 398 | " AND patch.cfg.key<>localdb.vvar.name" |
| 399 | ); |
| 400 | if( db_step(&q)==SQLITE_ROW ){ |
| 401 | blob_append_escaped_arg(&cmd, g.nameOfExe, 1); |
| 402 | blob_appendf(&cmd, " update %s", db_column_text(&q, 0)); |
| 403 | if( mFlags & PATCH_VERBOSE ){ |
| 404 | fossil_print("%-10s %s\n", "BASELINE", db_column_text(&q,0)); |
| 405 | } |
| 406 | } |
| @@ -423,11 +423,11 @@ | |
| 423 | " WHERE type IN ('merge','cherrypick','backout','integrate')" |
| 424 | " AND mhash NOT GLOB '*[^a-fA-F0-9]*';" |
| 425 | ); |
| 426 | while( db_step(&q)==SQLITE_ROW ){ |
| 427 | const char *zType = db_column_text(&q,0); |
| 428 | blob_append_escaped_arg(&cmd, g.nameOfExe, 1); |
| 429 | if( strcmp(zType,"merge")==0 ){ |
| 430 | blob_appendf(&cmd, " merge %s\n", db_column_text(&q,1)); |
| 431 | }else{ |
| 432 | blob_appendf(&cmd, " merge --%s %s\n", zType, db_column_text(&q,1)); |
| 433 | } |
| @@ -451,11 +451,11 @@ | |
| 451 | |
| 452 | /* Deletions */ |
| 453 | db_prepare(&q, "SELECT pathname FROM patch.chng" |
| 454 | " WHERE origname IS NULL AND delta IS NULL"); |
| 455 | while( db_step(&q)==SQLITE_ROW ){ |
| 456 | blob_append_escaped_arg(&cmd, g.nameOfExe, 1); |
| 457 | blob_appendf(&cmd, " rm --hard %$\n", db_column_text(&q,0)); |
| 458 | if( mFlags & PATCH_VERBOSE ){ |
| 459 | fossil_print("%-10s %s\n", "DELETE", db_column_text(&q,0)); |
| 460 | } |
| 461 | } |
| @@ -478,11 +478,11 @@ | |
| 478 | "SELECT origname, pathname FROM patch.chng" |
| 479 | " WHERE origname IS NOT NULL" |
| 480 | " AND origname<>pathname" |
| 481 | ); |
| 482 | while( db_step(&q)==SQLITE_ROW ){ |
| 483 | blob_append_escaped_arg(&cmd, g.nameOfExe, 1); |
| 484 | blob_appendf(&cmd, " mv --hard %$ %$\n", |
| 485 | db_column_text(&q,0), db_column_text(&q,1)); |
| 486 | if( mFlags & PATCH_VERBOSE ){ |
| 487 | fossil_print("%-10s %s -> %s\n", "RENAME", |
| 488 | db_column_text(&q,0), db_column_text(&q,1)); |
| @@ -552,11 +552,11 @@ | |
| 552 | sqlite3_free(aOut); |
| 553 | if( mFlags & PATCH_VERBOSE ){ |
| 554 | fossil_print("%-10s %s\n", "EDIT", zPathname); |
| 555 | } |
| 556 | }else{ |
| 557 | blob_append_escaped_arg(&cmd, g.nameOfExe, 1); |
| 558 | blob_appendf(&cmd, " add %$\n", zPathname); |
| 559 | if( mFlags & PATCH_VERBOSE ){ |
| 560 | fossil_print("%-10s %s\n", "NEW", zPathname); |
| 561 | } |
| 562 | } |
| @@ -673,22 +673,22 @@ | |
| 673 | zRemote = fossil_strdup(g.argv[3]); |
| 674 | zDir = strchr(zRemote,':'); |
| 675 | if( zDir==0 ){ |
| 676 | zDir = zRemote; |
| 677 | blob_init(&cmd, 0, 0); |
| 678 | blob_append_escaped_arg(&cmd, g.nameOfExe, 1); |
| 679 | blob_appendf(&cmd, " patch %s%s %$ -", zRemoteCmd, zForce, zDir); |
| 680 | }else{ |
| 681 | Blob remote; |
| 682 | zDir[0] = 0; |
| 683 | zDir++; |
| 684 | transport_ssh_command(&cmd); |
| 685 | blob_append_escaped_arg(&cmd, zRemote, 0); |
| 686 | blob_init(&remote, 0, 0); |
| 687 | blob_appendf(&remote, "fossil patch %s%s --dir64 %z -", |
| 688 | zRemoteCmd, zForce, encode64(zDir, -1)); |
| 689 | blob_append_escaped_arg(&cmd, blob_str(&remote), 0); |
| 690 | blob_reset(&remote); |
| 691 | } |
| 692 | if( mFlags & PATCH_VERBOSE ){ |
| 693 | fossil_print("# %s\n", blob_str(&cmd)); |
| 694 | fflush(stdout); |
| 695 |
+4
-2
| --- src/printf.c | ||
| +++ src/printf.c | ||
| @@ -102,11 +102,13 @@ | ||
| 102 | 102 | #define etSTRINGID 23 /* String with length limit for a hash prefix: %S */ |
| 103 | 103 | #define etROOT 24 /* String value of g.zTop: %R */ |
| 104 | 104 | #define etJSONSTR 25 /* String encoded as a JSON string literal: %j |
| 105 | 105 | Use %!j to include double-quotes around it. */ |
| 106 | 106 | #define etSHELLESC 26 /* Escape a filename for use in a shell command: %$ |
| 107 | - See blob_append_escaped_arg() for details */ | |
| 107 | + See blob_append_escaped_arg() for details | |
| 108 | + "%$" -> adds "./" prefix if necessary. | |
| 109 | + "%!$" -> omits the "./" prefix. */ | |
| 108 | 110 | |
| 109 | 111 | |
| 110 | 112 | /* |
| 111 | 113 | ** An "etByte" is an 8-bit unsigned value. |
| 112 | 114 | */ |
| @@ -838,11 +840,11 @@ | ||
| 838 | 840 | length = width = 0; |
| 839 | 841 | break; |
| 840 | 842 | } |
| 841 | 843 | case etSHELLESC: { |
| 842 | 844 | char *zArg = va_arg(ap, char*); |
| 843 | - blob_append_escaped_arg(pBlob, zArg); | |
| 845 | + blob_append_escaped_arg(pBlob, zArg, !flag_altform2); | |
| 844 | 846 | length = width = 0; |
| 845 | 847 | break; |
| 846 | 848 | } |
| 847 | 849 | case etERROR: |
| 848 | 850 | buf[0] = '%'; |
| 849 | 851 |
| --- src/printf.c | |
| +++ src/printf.c | |
| @@ -102,11 +102,13 @@ | |
| 102 | #define etSTRINGID 23 /* String with length limit for a hash prefix: %S */ |
| 103 | #define etROOT 24 /* String value of g.zTop: %R */ |
| 104 | #define etJSONSTR 25 /* String encoded as a JSON string literal: %j |
| 105 | Use %!j to include double-quotes around it. */ |
| 106 | #define etSHELLESC 26 /* Escape a filename for use in a shell command: %$ |
| 107 | See blob_append_escaped_arg() for details */ |
| 108 | |
| 109 | |
| 110 | /* |
| 111 | ** An "etByte" is an 8-bit unsigned value. |
| 112 | */ |
| @@ -838,11 +840,11 @@ | |
| 838 | length = width = 0; |
| 839 | break; |
| 840 | } |
| 841 | case etSHELLESC: { |
| 842 | char *zArg = va_arg(ap, char*); |
| 843 | blob_append_escaped_arg(pBlob, zArg); |
| 844 | length = width = 0; |
| 845 | break; |
| 846 | } |
| 847 | case etERROR: |
| 848 | buf[0] = '%'; |
| 849 |
| --- src/printf.c | |
| +++ src/printf.c | |
| @@ -102,11 +102,13 @@ | |
| 102 | #define etSTRINGID 23 /* String with length limit for a hash prefix: %S */ |
| 103 | #define etROOT 24 /* String value of g.zTop: %R */ |
| 104 | #define etJSONSTR 25 /* String encoded as a JSON string literal: %j |
| 105 | Use %!j to include double-quotes around it. */ |
| 106 | #define etSHELLESC 26 /* Escape a filename for use in a shell command: %$ |
| 107 | See blob_append_escaped_arg() for details |
| 108 | "%$" -> adds "./" prefix if necessary. |
| 109 | "%!$" -> omits the "./" prefix. */ |
| 110 | |
| 111 | |
| 112 | /* |
| 113 | ** An "etByte" is an 8-bit unsigned value. |
| 114 | */ |
| @@ -838,11 +840,11 @@ | |
| 840 | length = width = 0; |
| 841 | break; |
| 842 | } |
| 843 | case etSHELLESC: { |
| 844 | char *zArg = va_arg(ap, char*); |
| 845 | blob_append_escaped_arg(pBlob, zArg, !flag_altform2); |
| 846 | length = width = 0; |
| 847 | break; |
| 848 | } |
| 849 | case etERROR: |
| 850 | buf[0] = '%'; |
| 851 |
+5
-5
| --- src/winhttp.c | ||
| +++ src/winhttp.c | ||
| @@ -540,19 +540,19 @@ | ||
| 540 | 540 | if( PB("HTTPS") ){ |
| 541 | 541 | blob_appendf(&options, " --https"); |
| 542 | 542 | } |
| 543 | 543 | if( zBaseUrl ){ |
| 544 | 544 | blob_appendf(&options, " --baseurl "); |
| 545 | - blob_append_escaped_arg(&options, zBaseUrl); | |
| 545 | + blob_append_escaped_arg(&options, zBaseUrl, 0); | |
| 546 | 546 | } |
| 547 | 547 | if( zNotFound ){ |
| 548 | 548 | blob_appendf(&options, " --notfound "); |
| 549 | - blob_append_escaped_arg(&options, zNotFound); | |
| 549 | + blob_append_escaped_arg(&options, zNotFound, 1); | |
| 550 | 550 | } |
| 551 | 551 | if( g.zCkoutAlias ){ |
| 552 | 552 | blob_appendf(&options, " --ckout-alias "); |
| 553 | - blob_append_escaped_arg(&options, g.zCkoutAlias); | |
| 553 | + blob_append_escaped_arg(&options, g.zCkoutAlias, 0); | |
| 554 | 554 | } |
| 555 | 555 | if( zFileGlob ){ |
| 556 | 556 | blob_appendf(&options, " --files-urlenc %T", zFileGlob); |
| 557 | 557 | } |
| 558 | 558 | if( g.useLocalauth ){ |
| @@ -564,19 +564,19 @@ | ||
| 564 | 564 | if( flags & HTTP_SERVER_REPOLIST ){ |
| 565 | 565 | blob_appendf(&options, " --repolist"); |
| 566 | 566 | } |
| 567 | 567 | if( g.zExtRoot && g.zExtRoot[0] ){ |
| 568 | 568 | blob_appendf(&options, " --extroot"); |
| 569 | - blob_append_escaped_arg(&options, g.zExtRoot); | |
| 569 | + blob_append_escaped_arg(&options, g.zExtRoot, 1); | |
| 570 | 570 | } |
| 571 | 571 | zSkin = skin_in_use(); |
| 572 | 572 | if( zSkin ){ |
| 573 | 573 | blob_appendf(&options, " --skin %s", zSkin); |
| 574 | 574 | } |
| 575 | 575 | if( g.zMainMenuFile ){ |
| 576 | 576 | blob_appendf(&options, " --mainmenu "); |
| 577 | - blob_append_escaped_arg(&options, g.zMainMenuFile); | |
| 577 | + blob_append_escaped_arg(&options, g.zMainMenuFile, 1); | |
| 578 | 578 | } |
| 579 | 579 | #if USE_SEE |
| 580 | 580 | zSavedKey = db_get_saved_encryption_key(); |
| 581 | 581 | savedKeySize = db_get_saved_encryption_key_size(); |
| 582 | 582 | if( zSavedKey!=0 && savedKeySize>0 ){ |
| 583 | 583 |
| --- src/winhttp.c | |
| +++ src/winhttp.c | |
| @@ -540,19 +540,19 @@ | |
| 540 | if( PB("HTTPS") ){ |
| 541 | blob_appendf(&options, " --https"); |
| 542 | } |
| 543 | if( zBaseUrl ){ |
| 544 | blob_appendf(&options, " --baseurl "); |
| 545 | blob_append_escaped_arg(&options, zBaseUrl); |
| 546 | } |
| 547 | if( zNotFound ){ |
| 548 | blob_appendf(&options, " --notfound "); |
| 549 | blob_append_escaped_arg(&options, zNotFound); |
| 550 | } |
| 551 | if( g.zCkoutAlias ){ |
| 552 | blob_appendf(&options, " --ckout-alias "); |
| 553 | blob_append_escaped_arg(&options, g.zCkoutAlias); |
| 554 | } |
| 555 | if( zFileGlob ){ |
| 556 | blob_appendf(&options, " --files-urlenc %T", zFileGlob); |
| 557 | } |
| 558 | if( g.useLocalauth ){ |
| @@ -564,19 +564,19 @@ | |
| 564 | if( flags & HTTP_SERVER_REPOLIST ){ |
| 565 | blob_appendf(&options, " --repolist"); |
| 566 | } |
| 567 | if( g.zExtRoot && g.zExtRoot[0] ){ |
| 568 | blob_appendf(&options, " --extroot"); |
| 569 | blob_append_escaped_arg(&options, g.zExtRoot); |
| 570 | } |
| 571 | zSkin = skin_in_use(); |
| 572 | if( zSkin ){ |
| 573 | blob_appendf(&options, " --skin %s", zSkin); |
| 574 | } |
| 575 | if( g.zMainMenuFile ){ |
| 576 | blob_appendf(&options, " --mainmenu "); |
| 577 | blob_append_escaped_arg(&options, g.zMainMenuFile); |
| 578 | } |
| 579 | #if USE_SEE |
| 580 | zSavedKey = db_get_saved_encryption_key(); |
| 581 | savedKeySize = db_get_saved_encryption_key_size(); |
| 582 | if( zSavedKey!=0 && savedKeySize>0 ){ |
| 583 |
| --- src/winhttp.c | |
| +++ src/winhttp.c | |
| @@ -540,19 +540,19 @@ | |
| 540 | if( PB("HTTPS") ){ |
| 541 | blob_appendf(&options, " --https"); |
| 542 | } |
| 543 | if( zBaseUrl ){ |
| 544 | blob_appendf(&options, " --baseurl "); |
| 545 | blob_append_escaped_arg(&options, zBaseUrl, 0); |
| 546 | } |
| 547 | if( zNotFound ){ |
| 548 | blob_appendf(&options, " --notfound "); |
| 549 | blob_append_escaped_arg(&options, zNotFound, 1); |
| 550 | } |
| 551 | if( g.zCkoutAlias ){ |
| 552 | blob_appendf(&options, " --ckout-alias "); |
| 553 | blob_append_escaped_arg(&options, g.zCkoutAlias, 0); |
| 554 | } |
| 555 | if( zFileGlob ){ |
| 556 | blob_appendf(&options, " --files-urlenc %T", zFileGlob); |
| 557 | } |
| 558 | if( g.useLocalauth ){ |
| @@ -564,19 +564,19 @@ | |
| 564 | if( flags & HTTP_SERVER_REPOLIST ){ |
| 565 | blob_appendf(&options, " --repolist"); |
| 566 | } |
| 567 | if( g.zExtRoot && g.zExtRoot[0] ){ |
| 568 | blob_appendf(&options, " --extroot"); |
| 569 | blob_append_escaped_arg(&options, g.zExtRoot, 1); |
| 570 | } |
| 571 | zSkin = skin_in_use(); |
| 572 | if( zSkin ){ |
| 573 | blob_appendf(&options, " --skin %s", zSkin); |
| 574 | } |
| 575 | if( g.zMainMenuFile ){ |
| 576 | blob_appendf(&options, " --mainmenu "); |
| 577 | blob_append_escaped_arg(&options, g.zMainMenuFile, 1); |
| 578 | } |
| 579 | #if USE_SEE |
| 580 | zSavedKey = db_get_saved_encryption_key(); |
| 581 | savedKeySize = db_get_saved_encryption_key_size(); |
| 582 | if( zSavedKey!=0 && savedKeySize>0 ){ |
| 583 |