git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v3 0/4] setup: Don't dereference in-tree symlinks for absolute paths

From
Martin Erik Werner <martinerikwerner@gmail.com>
Date
Jan 31, 2014, 20:21 UTC
Message-ID
<20140131202142.GA9731@mule>
In-Reply-To
<1390781250-20389-2-git-send-email-martinerikwerner@gmail.com>
On Mon, Jan 27, 2014 at 08:31:37AM -0800, Junio C Hamano wrote:
Show 125 quoted lines
> Martin Erik Werner <martinerikwerner@gmail.com> writes:
> 
> > In order to manipulate symliks in the
> > work tree using absolute paths, symlinks should only be dereferenced
> > outside the work tree.
> 
> I agree 100% with this reasoning (modulo s/symliks/symlinks/).
> 
> As to the implementation, it looks a bit overly complicated,
> though.  I haven't tried writing the same myself, but 
> 
>  * I suspect that strbuf would help simplifying the allocation and
>    deallocation;
> 
>  * Also I suspect that use of string-list to split and then join is
>    making the code unnecessarily complex. In Python/Perl, that would
>    be a normal approach, but in C, it would be a lot simpler if you
>    prepare a writable temporary in wtpart[], walk from left to right
>    finding '/' and replacing it temporarily with NUL to terminate in
>    order to check with real_path(), restore the NUL back to '/' to
>    check deeper, and rinse and repeat.
> 
>    Having said that, I am not absolutely sure if the repeated
>    calls to real_path() are doing the right thing, though ;-)
> 
> > diff --git a/setup.c b/setup.c
> > index 5432a31..0789a96 100644
> > --- a/setup.c
> > +++ b/setup.c
> > @@ -22,11 +22,51 @@ char *prefix_path_gently(const char *prefix, int len,
> >     const char *orig = path;
> >     char *sanitized;
> >     if (is_absolute_path(orig)) {
> > -           const char *temp = real_path(path);
> > -           sanitized = xmalloc(len + strlen(temp) + 1);
> > -           strcpy(sanitized, temp);
> > +           int i, match;
> > +           size_t wtpartlen;
> > +           char *npath, *wtpart;
> > +           struct string_list list = STRING_LIST_INIT_DUP;
> > +           const char *work_tree = get_git_work_tree();
> > +           if (!work_tree)
> > +                   return NULL;
> > +           npath = xmalloc(strlen(path) + 1);
> >             if (remaining_prefix)
> >                     *remaining_prefix = 0;
> > +           if (normalize_path_copy_len(npath, path, remaining_prefix)) {
> > +                   free(npath);
> > +                   return NULL;
> > +           }
> > +
> > +           string_list_split(&list, npath, '/', -1);
> > +           wtpart = xmalloc(strlen(npath) + 1);
> > +           i = 0;
> > +           match = 0;
> > +           strcpy(wtpart, list.items[i++].string);
> > +           strcat(wtpart, "/");
> > +           if (strcmp(real_path(wtpart), work_tree) == 0) {
> > +                   match = 1;
> > +           } else {
> > +                   while (i < list.nr) {
> > +                           strcat(wtpart, list.items[i++].string);
> > +                           if (strcmp(real_path(wtpart), work_tree) == 0) {
> > +                                   match = 1;
> > +                                   break;
> > +                           }
> > +                           strcat(wtpart, "/");
> > +                   }
> > +           }
> > +           string_list_clear(&list, 0);
> > +           if (!match) {
> > +                   free(npath);
> > +                   free(wtpart);
> > +                   return NULL;
> > +           }
> > +
> > +           wtpartlen = strlen(wtpart);
> > +           sanitized = xmalloc(strlen(npath) - wtpartlen);
> > +           strcpy(sanitized, npath + wtpartlen + 1);
> > +           free(npath);
> > +           free(wtpart);
> >     } else {
> >             sanitized = xmalloc(len + strlen(path) + 1);
> >             if (len)
> > @@ -34,26 +74,10 @@ char *prefix_path_gently(const char *prefix, int len,
> >             strcpy(sanitized + len, path);
> >             if (remaining_prefix)
> >                     *remaining_prefix = len;
> > -   }
> > -   if (normalize_path_copy_len(sanitized, sanitized, remaining_prefix))
> > -           goto error_out;
> > -   if (is_absolute_path(orig)) {
> > -           size_t root_len, len, total;
> > -           const char *work_tree = get_git_work_tree();
> > -           if (!work_tree)
> > -                   goto error_out;
> > -           len = strlen(work_tree);
> > -           root_len = offset_1st_component(work_tree);
> > -           total = strlen(sanitized) + 1;
> > -           if (strncmp(sanitized, work_tree, len) ||
> > -               (len > root_len && sanitized[len] != '\0' && sanitized[len] != '/')) {
> > -           error_out:
> > +           if (normalize_path_copy_len(sanitized, sanitized, remaining_prefix)) {
> >                     free(sanitized);
> >                     return NULL;
> >             }
> > -           if (sanitized[len] == '/')
> > -                   len++;
> > -           memmove(sanitized, sanitized + len, total - len);
> >     }
> >     return sanitized;
> >  }
> > diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
> > index 3a0677a..03a12ac 100755
> > --- a/t/t0060-path-utils.sh
> > +++ b/t/t0060-path-utils.sh
> > @@ -190,7 +190,7 @@ test_expect_success SYMLINKS 'real path works on symlinks' '
> >     test "$sym" = "$(test-path-utils real_path "$dir2/syml")"
> >  '
> >  
> > -test_expect_failure SYMLINKS 'prefix_path works with work tree symlinks' '
> > +test_expect_success SYMLINKS 'prefix_path works with work tree symlinks' '
> >  
> >     ln -s target symlink &&
> >     test "$(test-path-utils prefix_path prefix "$(pwd)/symlink")" = "symlink"

On Mon, Jan 27, 2014 at 07:49:42AM +0700, Duy Nguyen wrote: (...)

Show 5 quoted lines
> All this new code looks long enough to be a separate function with a
> meaningful name. And we could travese through each path component in
> npath without wtpart (replacing '/' with '\0' to terminate the string
> temporarily for real_path()). But it's up to you. Whichever way is
> easier to read to you.
(...)

I've reworked my patchset to add a specialised 'abspath_part_inside_repo' function which does traversing and temporary NUL-separation as suggested.

I've also added a new test for a regression which I managed to hit.

I'm not particularly happy with the name of the function, but since path_inside_repo already exists for something quite different, it seemed important to distinguish it.

I've not added any test cases specific to the function, since some of it is already covered thought prefix_path, and some things I'm unsure if possible to test sanely (e.g. work tree is /).

Repeatedly calling 'real_path' feels somewhat clunky, but I haven't managed to come up with an alternative method that would work, since symlinks change the path arbitrarily there's no way to separate the result of dereferencing two symlinks at once.

Martin Erik Werner (4):
  t0060: Add test for manipulating symlinks via absolute paths
  t0060: Add test for prefix_path when path == work tree
  setup: Add 'abspath_part_inside_repo' function
  setup: Don't dereference in-tree symlinks for absolute paths
 cache.h               |  1 +
 setup.c               | 99 ++++++++++++++++++++++++++++++++++++++++-----------
 t/t0060-path-utils.sh | 11 ++++++
 3 files changed, 91 insertions(+), 20 deletions(-)
-- 
1.8.5.2
Previous: Junio C HamanoNext: Martin Erik Werner
Message 10 of 56 in “git-mv with absolute path derefereces symlinks”
  1. Martin Erik WernerJan 15, 2014
  2. 0/2 in-tree symlink handling with absolute pathsMartin Erik Werner, Jan 26, 2014
  3. 1/2 t0060: Add test for manipulating symlinks via absolute pathsMartin Erik Werner, Jan 26, 2014
  4. 2/2 setup: Don't dereference in-tree symlinks for absolute pathsMartin Erik Werner, Jan 26, 2014
  5. Torsten BögershausenJan 26, 2014
  6. Martin Erik WernerJan 27, 2014
  7. 2/2 setup: Don't dereference in-tree symlinks for absolute pathsMartin Erik Werner, Jan 27, 2014
  8. Duy NguyenJan 27, 2014
  9. Junio C HamanoJan 27, 2014
  10. 0/4 setup: Don't dereference in-tree symlinks for absolute pathsMartin Erik Werner, Jan 31, 2014
  11. 0/4 Handling of in-tree symlinks for absolute pathsMartin Erik Werner, Feb 2, 2014
  12. 1/4 t0060: Add test for manipulating symlinks via absolute pathsMartin Erik Werner, Feb 2, 2014
  13. 2/4 t0060: Add test for prefix_path when path == work treeMartin Erik Werner, Feb 2, 2014
  14. 3/4 setup: Add 'abspath_part_inside_repo' functionMartin Erik Werner, Feb 2, 2014
  15. Duy NguyenFeb 2, 2014
  16. Duy NguyenFeb 2, 2014
  17. Martin Erik WernerFeb 2, 2014
  18. David KastrupFeb 2, 2014
  19. Torsten BögershausenFeb 2, 2014
  20. Martin Erik WernerFeb 2, 2014
  21. Torsten BögershausenFeb 2, 2014
  22. Duy NguyenFeb 2, 2014
  23. 4/4 setup: Don't dereference in-tree symlinks for absolute pathsMartin Erik Werner, Feb 2, 2014
  24. 0/5 Handling of in-tree symlinks for absolute pathsMartin Erik Werner, Feb 2, 2014
  25. 1/5 t0060: Add test for manipulating symlinks via absolute pathsMartin Erik Werner, Feb 2, 2014
  26. Junio C HamanoFeb 3, 2014
  27. Junio C HamanoFeb 3, 2014
  28. Martin Erik WernerFeb 3, 2014
  29. 2/5 t0060: Add test for prefix_path when path == work treeMartin Erik Werner, Feb 2, 2014
  30. 3/5 t0060: Add tests for prefix_path when path begins with work treeMartin Erik Werner, Feb 2, 2014
  31. 4/5 setup: Add 'abspath_part_inside_repo' functionMartin Erik Werner, Feb 2, 2014
  32. Junio C HamanoFeb 3, 2014
  33. Martin Erik WernerFeb 3, 2014
  34. Junio C HamanoFeb 4, 2014
  35. Martin Erik WernerFeb 4, 2014
  36. 5/5 setup: Don't dereference in-tree symlinks for absolute pathsMartin Erik Werner, Feb 2, 2014
  37. Duy NguyenFeb 3, 2014
  38. Martin Erik WernerFeb 3, 2014
  39. Junio C HamanoFeb 4, 2014
  40. 0/6 Handling of in-tree symlinks for absolute pathsMartin Erik Werner, Feb 4, 2014
  41. 1/6 t3004: Add test for ls-files on symlinks via absolute pathsMartin Erik Werner, Feb 4, 2014
  42. 2/6 t0060: Add test for prefix_path on symlinks via absolute pathsMartin Erik Werner, Feb 4, 2014
  43. 3/6 t0060: Add test for prefix_path when path == work treeMartin Erik Werner, Feb 4, 2014
  44. 4/6 t0060: Add tests for prefix_path when path begins with work treeMartin Erik Werner, Feb 4, 2014
  45. Torsten BögershausenFeb 4, 2014
  46. Junio C HamanoFeb 4, 2014
  47. 5/6 setup: Add 'abspath_part_inside_repo' functionMartin Erik Werner, Feb 4, 2014
  48. Junio C HamanoFeb 4, 2014
  49. 6/6 setup: Don't dereference in-tree symlinks for absolute pathsMartin Erik Werner, Feb 4, 2014
  50. 1/4 t0060: Add test for manipulating symlinks via absolute pathsMartin Erik Werner, Jan 31, 2014
  51. 2/4 t0060: Add test for prefix_path when path == work treeMartin Erik Werner, Jan 31, 2014
  52. 3/4 setup: Add 'abspath_part_inside_repo' functionMartin Erik Werner, Jan 31, 2014
  53. Torsten BögershausenJan 31, 2014
  54. Martin Erik WernerFeb 1, 2014
  55. Duy NguyenFeb 1, 2014
  56. 4/4 setup: Don't dereference in-tree symlinks for absolute pathsMartin Erik Werner, Jan 31, 2014

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.