Fossil SCM
Fix a corner-case in file_tree_name() - specifically when the input is the name of the root of the local tree, return ".".
Commit
f98114c9e45ef0e6eb8bf04eec4097458d52121a
Parent
2d1a03736ac1043…
1 file changed
+15
-2
+15
-2
| --- src/file.c | ||
| +++ src/file.c | ||
| @@ -429,22 +429,35 @@ | ||
| 429 | 429 | ** The root of the tree is defined by the g.zLocalRoot variable. |
| 430 | 430 | */ |
| 431 | 431 | int file_tree_name(const char *zOrigName, Blob *pOut, int errFatal){ |
| 432 | 432 | int n; |
| 433 | 433 | Blob full; |
| 434 | + int nFull; | |
| 435 | + char *zFull; | |
| 436 | + | |
| 434 | 437 | db_must_be_within_tree(); |
| 435 | 438 | file_canonical_name(zOrigName, &full); |
| 436 | 439 | n = strlen(g.zLocalRoot); |
| 437 | - if( blob_size(&full)<=n || memcmp(g.zLocalRoot, blob_buffer(&full), n) ){ | |
| 440 | + assert( n>0 && g.zLocalRoot[n-1]=='/' ); | |
| 441 | + nFull = blob_size(&full); | |
| 442 | + zFull = blob_buffer(&full); | |
| 443 | + | |
| 444 | + /* Special case. zOrigName refers to g.zLocalRoot directory. */ | |
| 445 | + if( nFull==n-1 && memcmp(g.zLocalRoot, zFull, nFull)==0 ){ | |
| 446 | + blob_append(pOut, ".", 1); | |
| 447 | + return 1; | |
| 448 | + } | |
| 449 | + | |
| 450 | + if( nFull<=n || memcmp(g.zLocalRoot, zFull, n) ){ | |
| 438 | 451 | blob_reset(&full); |
| 439 | 452 | if( errFatal ){ |
| 440 | 453 | fossil_fatal("file outside of checkout tree: %s", zOrigName); |
| 441 | 454 | } |
| 442 | 455 | return 0; |
| 443 | 456 | } |
| 444 | 457 | blob_zero(pOut); |
| 445 | - blob_append(pOut, blob_buffer(&full)+n, blob_size(&full)-n); | |
| 458 | + blob_append(pOut, &zFull[n], nFull-n); | |
| 446 | 459 | return 1; |
| 447 | 460 | } |
| 448 | 461 | |
| 449 | 462 | /* |
| 450 | 463 | ** COMMAND: test-tree-name |
| 451 | 464 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -429,22 +429,35 @@ | |
| 429 | ** The root of the tree is defined by the g.zLocalRoot variable. |
| 430 | */ |
| 431 | int file_tree_name(const char *zOrigName, Blob *pOut, int errFatal){ |
| 432 | int n; |
| 433 | Blob full; |
| 434 | db_must_be_within_tree(); |
| 435 | file_canonical_name(zOrigName, &full); |
| 436 | n = strlen(g.zLocalRoot); |
| 437 | if( blob_size(&full)<=n || memcmp(g.zLocalRoot, blob_buffer(&full), n) ){ |
| 438 | blob_reset(&full); |
| 439 | if( errFatal ){ |
| 440 | fossil_fatal("file outside of checkout tree: %s", zOrigName); |
| 441 | } |
| 442 | return 0; |
| 443 | } |
| 444 | blob_zero(pOut); |
| 445 | blob_append(pOut, blob_buffer(&full)+n, blob_size(&full)-n); |
| 446 | return 1; |
| 447 | } |
| 448 | |
| 449 | /* |
| 450 | ** COMMAND: test-tree-name |
| 451 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -429,22 +429,35 @@ | |
| 429 | ** The root of the tree is defined by the g.zLocalRoot variable. |
| 430 | */ |
| 431 | int file_tree_name(const char *zOrigName, Blob *pOut, int errFatal){ |
| 432 | int n; |
| 433 | Blob full; |
| 434 | int nFull; |
| 435 | char *zFull; |
| 436 | |
| 437 | db_must_be_within_tree(); |
| 438 | file_canonical_name(zOrigName, &full); |
| 439 | n = strlen(g.zLocalRoot); |
| 440 | assert( n>0 && g.zLocalRoot[n-1]=='/' ); |
| 441 | nFull = blob_size(&full); |
| 442 | zFull = blob_buffer(&full); |
| 443 | |
| 444 | /* Special case. zOrigName refers to g.zLocalRoot directory. */ |
| 445 | if( nFull==n-1 && memcmp(g.zLocalRoot, zFull, nFull)==0 ){ |
| 446 | blob_append(pOut, ".", 1); |
| 447 | return 1; |
| 448 | } |
| 449 | |
| 450 | if( nFull<=n || memcmp(g.zLocalRoot, zFull, n) ){ |
| 451 | blob_reset(&full); |
| 452 | if( errFatal ){ |
| 453 | fossil_fatal("file outside of checkout tree: %s", zOrigName); |
| 454 | } |
| 455 | return 0; |
| 456 | } |
| 457 | blob_zero(pOut); |
| 458 | blob_append(pOut, &zFull[n], nFull-n); |
| 459 | return 1; |
| 460 | } |
| 461 | |
| 462 | /* |
| 463 | ** COMMAND: test-tree-name |
| 464 |