{"thread":{"id":"30379","subject":"[PATCH] dir: convert to strbuf","startedAt":"2012-05-01T11:25:24Z","lastAt":"2012-05-01T11:25:24Z","messageCount":1,"participants":["René Scharfe"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"190416","messageId":"4F9FC824.80403@lsrfire.ath.cx","threadId":"30379","inReplyTo":null,"subject":"[PATCH] dir: convert to strbuf","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2012-05-01T11:25:24Z","receivedAt":"2012-05-01T11:25:24Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"The functions read_directory_recursive() and treat_leading_path() both\nuse buffers sized to fit PATH_MAX characters.  The latter can be made to\noverrun its buffer, e.g. like this:\n\n\t$ a=0123456789abcdef\n\t$ a=$a$a$a$a$a$a$a$a\n\t$ a=$a$a$a$a$a$a$a$a\n\t$ a=$a$a$a$a$a$a$a$a\n\t$ git add $a/a\n\nInstead of trying to add a check and potentionally forgetting to address\nsimilar cases, convert the involved functions and their helpers to use\nstruct strbuf.  The patch is suprisingly large because the helpers\ntreat_path() and treat_one_path() modify the buffer as well and thus\nneed to be converted, too.\n\nSigned-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>\n---\n dir.c |   76 ++++++++++++++++++++++++++++++++---------------------------------\n 1 file changed, 37 insertions(+), 39 deletions(-)\n\ndiff --git a/dir.c b/dir.c\nindex e98760c..c6a98cc 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -873,14 +873,14 @@ enum path_treatment {\n };\n \n static enum path_treatment treat_one_path(struct dir_struct *dir,\n-\t\t\t\t\t  char *path, int *len,\n+\t\t\t\t\t  struct strbuf *path,\n \t\t\t\t\t  const struct path_simplify *simplify,\n \t\t\t\t\t  int dtype, struct dirent *de)\n {\n-\tint exclude = excluded(dir, path, &dtype);\n+\tint exclude = excluded(dir, path->buf, &dtype);\n \tif (exclude && (dir->flags & DIR_COLLECT_IGNORED)\n-\t    && exclude_matches_pathspec(path, *len, simplify))\n-\t\tdir_add_ignored(dir, path, *len);\n+\t    && exclude_matches_pathspec(path->buf, path->len, simplify))\n+\t\tdir_add_ignored(dir, path->buf, path->len);\n \n \t/*\n \t * Excluded? If we don't explicitly want to show\n@@ -890,7 +890,7 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,\n \t\treturn path_ignored;\n \n \tif (dtype == DT_UNKNOWN)\n-\t\tdtype = get_dtype(de, path, *len);\n+\t\tdtype = get_dtype(de, path->buf, path->len);\n \n \t/*\n \t * Do we want to see just the ignored files?\n@@ -907,9 +907,8 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,\n \tdefault:\n \t\treturn path_ignored;\n \tcase DT_DIR:\n-\t\tmemcpy(path + *len, \"/\", 2);\n-\t\t(*len)++;\n-\t\tswitch (treat_directory(dir, path, *len, simplify)) {\n+\t\tstrbuf_addch(path, '/');\n+\t\tswitch (treat_directory(dir, path->buf, path->len, simplify)) {\n \t\tcase show_directory:\n \t\t\tif (exclude != !!(dir->flags\n \t\t\t\t\t  & DIR_SHOW_IGNORED))\n@@ -930,26 +929,21 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,\n \n static enum path_treatment treat_path(struct dir_struct *dir,\n \t\t\t\t      struct dirent *de,\n-\t\t\t\t      char *path, int path_max,\n+\t\t\t\t      struct strbuf *path,\n \t\t\t\t      int baselen,\n-\t\t\t\t      const struct path_simplify *simplify,\n-\t\t\t\t      int *len)\n+\t\t\t\t      const struct path_simplify *simplify)\n {\n \tint dtype;\n \n \tif (is_dot_or_dotdot(de->d_name) || !strcmp(de->d_name, \".git\"))\n \t\treturn path_ignored;\n-\t*len = strlen(de->d_name);\n-\t/* Ignore overly long pathnames! */\n-\tif (*len + baselen + 8 > path_max)\n-\t\treturn path_ignored;\n-\tmemcpy(path + baselen, de->d_name, *len + 1);\n-\t*len += baselen;\n-\tif (simplify_away(path, *len, simplify))\n+\tstrbuf_setlen(path, baselen);\n+\tstrbuf_addstr(path, de->d_name);\n+\tif (simplify_away(path->buf, path->len, simplify))\n \t\treturn path_ignored;\n \n \tdtype = DTYPE(de);\n-\treturn treat_one_path(dir, path, len, simplify, dtype, de);\n+\treturn treat_one_path(dir, path, simplify, dtype, de);\n }\n \n /*\n@@ -969,19 +963,19 @@ static int read_directory_recursive(struct dir_struct *dir,\n \tDIR *fdir = opendir(*base ? base : \".\");\n \tint contents = 0;\n \tstruct dirent *de;\n-\tchar path[PATH_MAX + 1];\n+\tstruct strbuf path = STRBUF_INIT;\n \n \tif (!fdir)\n \t\treturn 0;\n \n-\tmemcpy(path, base, baselen);\n+\tstrbuf_add(&path, base, baselen);\n \n \twhile ((de = readdir(fdir)) != NULL) {\n-\t\tint len;\n-\t\tswitch (treat_path(dir, de, path, sizeof(path),\n-\t\t\t\t   baselen, simplify, &len)) {\n+\t\tswitch (treat_path(dir, de, &path, baselen, simplify)) {\n \t\tcase path_recurse:\n-\t\t\tcontents += read_directory_recursive(dir, path, len, 0, simplify);\n+\t\t\tcontents += read_directory_recursive(dir, path.buf,\n+\t\t\t\t\t\t\t     path.len, 0,\n+\t\t\t\t\t\t\t     simplify);\n \t\t\tcontinue;\n \t\tcase path_ignored:\n \t\t\tcontinue;\n@@ -992,10 +986,11 @@ static int read_directory_recursive(struct dir_struct *dir,\n \t\tif (check_only)\n \t\t\tgoto exit_early;\n \t\telse\n-\t\t\tdir_add_name(dir, path, len);\n+\t\t\tdir_add_name(dir, path.buf, path.len);\n \t}\n exit_early:\n \tclosedir(fdir);\n+\tstrbuf_release(&path);\n \n \treturn contents;\n }\n@@ -1058,8 +1053,8 @@ static int treat_leading_path(struct dir_struct *dir,\n \t\t\t      const char *path, int len,\n \t\t\t      const struct path_simplify *simplify)\n {\n-\tchar pathbuf[PATH_MAX];\n-\tint baselen, blen;\n+\tstruct strbuf sb = STRBUF_INIT;\n+\tint baselen, rc = 0;\n \tconst char *cp;\n \n \twhile (len && path[len - 1] == '/')\n@@ -1074,19 +1069,22 @@ static int treat_leading_path(struct dir_struct *dir,\n \t\t\tbaselen = len;\n \t\telse\n \t\t\tbaselen = cp - path;\n-\t\tmemcpy(pathbuf, path, baselen);\n-\t\tpathbuf[baselen] = '\\0';\n-\t\tif (!is_directory(pathbuf))\n-\t\t\treturn 0;\n-\t\tif (simplify_away(pathbuf, baselen, simplify))\n-\t\t\treturn 0;\n-\t\tblen = baselen;\n-\t\tif (treat_one_path(dir, pathbuf, &blen, simplify,\n+\t\tstrbuf_setlen(&sb, 0);\n+\t\tstrbuf_add(&sb, path, baselen);\n+\t\tif (!is_directory(sb.buf))\n+\t\t\tbreak;\n+\t\tif (simplify_away(sb.buf, sb.len, simplify))\n+\t\t\tbreak;\n+\t\tif (treat_one_path(dir, &sb, simplify,\n \t\t\t\t   DT_DIR, NULL) == path_ignored)\n-\t\t\treturn 0; /* do not recurse into it */\n-\t\tif (len <= baselen)\n-\t\t\treturn 1; /* finished checking */\n+\t\t\tbreak; /* do not recurse into it */\n+\t\tif (len <= baselen) {\n+\t\t\trc = 1;\n+\t\t\tbreak; /* finished checking */\n+\t\t}\n \t}\n+\tstrbuf_release(&sb);\n+\treturn rc;\n }\n \n int read_directory(struct dir_struct *dir, const char *path, int len, const char **pathspec)\n-- \n1.7.10\n"}]}