dir: convert to strbuf
The functions read_directory_recursive() and treat_leading_path() both use buffers sized to fit PATH_MAX characters. The latter can be made to overrun its buffer, e.g. like this: $ a=0123456789abcdef $ a=$a$a$a$a$a$a$a$a $ a=$a$a$a$a$a$a$a$a $ a=$a$a$a$a$a$a$a$a $ git add $a/a Instead of trying to add a check and potentionally forgetting to address similar cases, convert the involved functions and their helpers to use struct strbuf. The patch is suprisingly large because the helpers treat_path() and treat_one_path() modify the buffer as well and thus need to be converted, too. Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx> Signed-off-by: Junio C Hamano <gitster@pobox.com>
René Scharfe committed
May 1, 2012 at 13:25 UTC
49dc2cc2c97cd76435d7f1609f2c573b64efd5b6
1 file changed
+36
-39
dir.c
+36
-39
@@ -866,14 +866,14 @@ enum path_treatment {
866
};
867
868
static enum path_treatment treat_one_path(struct dir_struct *dir,
869
- char *path, int *len,
869
+ struct strbuf *path,
870
const struct path_simplify *simplify,
871
int dtype, struct dirent *de)
872
{
873
- int exclude = excluded(dir, path, &dtype);
873
+ int exclude = excluded(dir, path->buf, &dtype);
874
if (exclude && (dir->flags & DIR_COLLECT_IGNORED)
875
- && exclude_matches_pathspec(path, *len, simplify))
876
- dir_add_ignored(dir, path, *len);
875
+ && exclude_matches_pathspec(path->buf, path->len, simplify))
876
+ dir_add_ignored(dir, path->buf, path->len);
877
878
/*
879
* Excluded? If we don't explicitly want to show
@@ -883,7 +883,7 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
883
return path_ignored;
884
885
if (dtype == DT_UNKNOWN)
886
- dtype = get_dtype(de, path, *len);
886
+ dtype = get_dtype(de, path->buf, path->len);
887
888
/*
889
* Do we want to see just the ignored files?
@@ -900,9 +900,8 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
900
default:
901
return path_ignored;
902
case DT_DIR:
903
- memcpy(path + *len, "/", 2);
904
- (*len)++;
905
- switch (treat_directory(dir, path, *len, simplify)) {
903
+ strbuf_addch(path, '/');
904
+ switch (treat_directory(dir, path->buf, path->len, simplify)) {
905
case show_directory:
906
if (exclude != !!(dir->flags
907
& DIR_SHOW_IGNORED))
@@ -923,26 +922,21 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
922
923
static enum path_treatment treat_path(struct dir_struct *dir,
924
struct dirent *de,
926
- char *path, int path_max,
925
+ struct strbuf *path,
926
int baselen,
928
- const struct path_simplify *simplify,
929
- int *len)
927
+ const struct path_simplify *simplify)
928
{
929
int dtype;
930
931
if (is_dot_or_dotdot(de->d_name) || !strcmp(de->d_name, ".git"))
932
return path_ignored;
935
- *len = strlen(de->d_name);
936
- /* Ignore overly long pathnames! */
937
- if (*len + baselen + 8 > path_max)
938
- return path_ignored;
939
- memcpy(path + baselen, de->d_name, *len + 1);
940
- *len += baselen;
941
- if (simplify_away(path, *len, simplify))
933
+ strbuf_setlen(path, baselen);
934
+ strbuf_addstr(path, de->d_name);
935
+ if (simplify_away(path->buf, path->len, simplify))
936
return path_ignored;
937
938
dtype = DTYPE(de);
945
- return treat_one_path(dir, path, len, simplify, dtype, de);
939
+ return treat_one_path(dir, path, simplify, dtype, de);
940
}
941
942
/*
@@ -964,16 +958,15 @@ static int read_directory_recursive(struct dir_struct *dir,
958
959
if (fdir) {
960
struct dirent *de;
967
- char path[PATH_MAX + 1];
968
- memcpy(path, base, baselen);
961
+ struct strbuf path = STRBUF_INIT;
962
+
963
+ strbuf_add(&path, base, baselen);
964
965
while ((de = readdir(fdir)) != NULL) {
971
- int len;
972
- switch (treat_path(dir, de, path, sizeof(path),
973
- baselen, simplify, &len)) {
966
+ switch (treat_path(dir, de, &path, baselen, simplify)) {
967
case path_recurse:
968
contents += read_directory_recursive
976
- (dir, path, len, 0, simplify);
969
+ (dir, path.buf, path.len, 0, simplify);
970
continue;
971
case path_ignored:
972
continue;
@@ -984,10 +977,11 @@ static int read_directory_recursive(struct dir_struct *dir,
977
if (check_only)
978
goto exit_early;
979
else
987
- dir_add_name(dir, path, len);
980
+ dir_add_name(dir, path.buf, path.len);
981
}
982
exit_early:
983
closedir(fdir);
984
+ strbuf_release(&path);
985
}
986
987
return contents;
@@ -1051,8 +1045,8 @@ static int treat_leading_path(struct dir_struct *dir,
1045
const char *path, int len,
1046
const struct path_simplify *simplify)
1047
{
1054
- char pathbuf[PATH_MAX];
1055
- int baselen, blen;
1048
+ struct strbuf sb = STRBUF_INIT;
1049
+ int baselen, rc = 0;
1050
const char *cp;
1051
1052
while (len && path[len - 1] == '/')
@@ -1067,19 +1061,22 @@ static int treat_leading_path(struct dir_struct *dir,
1061
baselen = len;
1062
else
1063
baselen = cp - path;
1070
- memcpy(pathbuf, path, baselen);
1071
- pathbuf[baselen] = '\0';
1072
- if (!is_directory(pathbuf))
1073
- return 0;
1074
- if (simplify_away(pathbuf, baselen, simplify))
1075
- return 0;
1076
- blen = baselen;
1077
- if (treat_one_path(dir, pathbuf, &blen, simplify,
1064
+ strbuf_setlen(&sb, 0);
1065
+ strbuf_add(&sb, path, baselen);
1066
+ if (!is_directory(sb.buf))
1067
+ break;
1068
+ if (simplify_away(sb.buf, sb.len, simplify))
1069
+ break;
1070
+ if (treat_one_path(dir, &sb, simplify,
1071
DT_DIR, NULL) == path_ignored)
1079
- return 0; /* do not recurse into it */
1080
- if (len <= baselen)
1081
- return 1; /* finished checking */
1072
+ break; /* do not recurse into it */
1073
+ if (len <= baselen) {
1074
+ rc = 1;
1075
+ break; /* finished checking */
1076
+ }
1077
}
1078
+ strbuf_release(&sb);
1079
+ return rc;
1080
}
1081
1082
int read_directory(struct dir_struct *dir, const char *path, int len, const char **pathspec)