{"thread":{"id":"8833","subject":"[PATCH] Don't smash stack when $GIT_ALTERNATE_OBJECT_DIRECTORIES is too long","startedAt":"2007-07-03T10:40:20Z","lastAt":"2007-07-04T05:10:39Z","messageCount":2,"participants":["Jim Meyering","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"46350","messageId":"87k5thdb3f.fsf@rho.meyering.net","threadId":"8833","inReplyTo":null,"subject":"[PATCH] Don't smash stack when $GIT_ALTERNATE_OBJECT_DIRECTORIES is too long","fromName":"Jim Meyering","fromEmail":"jim@meyering.net","sentAt":"2007-07-03T10:40:20Z","receivedAt":"2007-07-03T10:40:20Z","isPatch":true,"sender":{"key":"jim@meyering.net","avatar":"https://avatars.githubusercontent.com/u/710630?v=4"},"body":"There is no restriction on the length of the name returned by\nget_object_directory, other than the fact that it must be a stat'able\ngit object directory.  That means its name may have length up to\nPATH_MAX-1 (i.e., often 4095) not counting the trailing NUL.\n\nCombine that with the assumption that the concatenation of that name and\nsuffixes like \"/info/alternates\" and \"/pack/---long-name---.idx\" will fit\nin a buffer of length PATH_MAX, and you see the problem.  Here's a fix:\n\n    sha1_file.c (prepare_packed_git_one): Lengthen \"path\" buffer\n    so we are guaranteed to be able to append \"/pack/\" without checking.\n    Skip any directory entry that is too long to be appended.\n    (read_info_alternates): Protect against a similar buffer overrun.\n\nBefore this change, using the following admittedly contrived environment\nsetting would cause many git commands to clobber their stack and segfault\non a system with PATH_MAX == 4096:\n\n  t=$(perl -e '$s=\".git/objects\";$n=(4096-6-length($s))/2;print \"./\"x$n . $s')\n  export GIT_ALTERNATE_OBJECT_DIRECTORIES=$t\n  touch g\n  ./git-update-index --add g\n\nIf you run the above commands, you'll soon notice that many\ngit commands now segfault, so you'll want to do this:\n\n  unset GIT_ALTERNATE_OBJECT_DIRECTORIES\n\nSigned-off-by: Jim Meyering <jim@meyering.net>\n---\n sha1_file.c |   16 +++++++++++++---\n 1 files changed, 13 insertions(+), 3 deletions(-)\n\ndiff --git a/sha1_file.c b/sha1_file.c\nindex f2b1ae0..1efd9ae 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -352,10 +352,14 @@ static void read_info_alternates(const char * relative_base, int depth)\n \tchar *map;\n \tsize_t mapsz;\n \tstruct stat st;\n-\tchar path[PATH_MAX];\n+\tconst char alt_file_name[] = \"info/alternates\";\n+\t/* Given that relative_base is no longer than PATH_MAX,\n+\t   ensure that \"path\" has enough space to append \"/\", the\n+\t   file name, \"info/alternates\", and a trailing NUL.  */\n+\tchar path[PATH_MAX + 1 + sizeof alt_file_name];\n \tint fd;\n\n-\tsprintf(path, \"%s/info/alternates\", relative_base);\n+\tsprintf(path, \"%s/%s\", relative_base, alt_file_name);\n \tfd = open(path, O_RDONLY);\n \tif (fd < 0)\n \t\treturn;\n@@ -836,7 +840,10 @@ void install_packed_git(struct packed_git *pack)\n\n static void prepare_packed_git_one(char *objdir, int local)\n {\n-\tchar path[PATH_MAX];\n+\t/* Ensure that this buffer is large enough so that we can\n+\t   append \"/pack/\" without clobbering the stack even if\n+\t   strlen(objdir) were PATH_MAX.  */\n+\tchar path[PATH_MAX + 1 + 4 + 1 + 1];\n \tint len;\n \tDIR *dir;\n \tstruct dirent *de;\n@@ -858,6 +865,9 @@ static void prepare_packed_git_one(char *objdir, int local)\n \t\tif (!has_extension(de->d_name, \".idx\"))\n \t\t\tcontinue;\n\n+\t\tif (len + namelen + 1 > sizeof(path))\n+\t\t\tcontinue;\n+\n \t\t/* Don't reopen a pack we already have. */\n \t\tstrcpy(path + len, de->d_name);\n \t\tfor (p = packed_git; p; p = p->next) {\n--\n1.5.2.2.646.g71e55-dirty\n"},{"id":"46436","messageId":"7vhcoklpo0.fsf@assigned-by-dhcp.cox.net","threadId":"8833","inReplyTo":"87k5thdb3f.fsf@rho.meyering.net","subject":"Re: [PATCH] Don't smash stack when $GIT_ALTERNATE_OBJECT_DIRECTORIES is too long","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-07-04T05:10:39Z","receivedAt":"2007-07-04T05:10:39Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Thanks.\n"}]}