Re: [PATCH v3 01/25] path.c: make get_pathname() return strbuf instead of static buffer

2014-03-03 Thread Junio C Hamano
Duy Nguyen pclo...@gmail.com writes:

 On Thu, Feb 20, 2014 at 6:26 AM, Junio C Hamano gits...@pobox.com wrote:
 Is there a reason not to do just an equivalent of

 #define git_pathdup mkpathdup

 and be done with it?  Am I missing something?

 They have a subtle difference: mkpathdup() calls cleanup_path() while
 git_pathdup() does not. Without auditing all call sites, we can't be
 sure this difference is insignificant. So I keep both functions
 separate for now.

Thanks; that is a very good explanation why #define'ing two to be
the same would not be a workable solution to the ownership issue I
raised.

  char *git_pathdup(const char *fmt, ...)
  {
 - char path[PATH_MAX], *ret;
 + struct strbuf *path = get_pathname();
   va_list args;
   va_start(args, fmt);
 - ret = vsnpath(path, sizeof(path), fmt, args);
 + vsnpath(path, fmt, args);
   va_end(args);
 - return xstrdup(ret);
 + return strbuf_detach(path, NULL);
  }

This feels somewhat wrong.

This function is for callers who are willing to take ownership of
the path buffer and promise to free the returned buffer when they
are done, because you are returning strbuf_detach()'ed piece of
memory, giving the ownership away.

The whole point of using get_pathname() is to allow callers not to
care about allocation issues on the paths they scribble on during
their short-and-simple codepaths that do not have too many uses of
similar temporary path buffers.  Why borrow from that round-robin
pool (which may now cause some codepaths to overflow the number of
such active temporary path buffers---have they been all audited)?
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 01/25] path.c: make get_pathname() return strbuf instead of static buffer

2014-02-28 Thread Duy Nguyen
On Thu, Feb 20, 2014 at 6:26 AM, Junio C Hamano gits...@pobox.com wrote:
 Is there a reason not to do just an equivalent of

 #define git_pathdup mkpathdup

 and be done with it?  Am I missing something?


They have a subtle difference: mkpathdup() calls cleanup_path() while
git_pathdup() does not. Without auditing all call sites, we can't be
sure this difference is insignificant. So I keep both functions
separate for now.
-- 
Duy
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 01/25] path.c: make get_pathname() return strbuf instead of static buffer

2014-02-19 Thread Junio C Hamano
Nguyễn Thái Ngọc Duy  pclo...@gmail.com writes:

(Only nitpicks during this round of review).

 -static char *get_pathname(void)
 +static struct strbuf *get_pathname()

static struct strbuf *get_pathname(void)
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 01/25] path.c: make get_pathname() return strbuf instead of static buffer

2014-02-19 Thread Junio C Hamano
Nguyễn Thái Ngọc Duy  pclo...@gmail.com writes:

 We've been avoiding PATH_MAX whenever possible. This patch makes
 get_pathname() return a strbuf and updates the callers to take
 advantage of this. The code is simplified as we no longer need to
 worry about buffer overflow.

 Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
 ---
  path.c | 119 
 +++--
  1 file changed, 50 insertions(+), 69 deletions(-)

Nice.

  char *git_pathdup(const char *fmt, ...)
  {
 - char path[PATH_MAX], *ret;
 + struct strbuf *path = get_pathname();
   va_list args;
   va_start(args, fmt);
 - ret = vsnpath(path, sizeof(path), fmt, args);
 + vsnpath(path, fmt, args);
   va_end(args);
 - return xstrdup(ret);
 + return strbuf_detach(path, NULL);
  }

This feels somewhat wrong.

This function is for callers who are willing to take ownership of
the path buffer and promise to free the returned buffer when they
are done, because you are returning strbuf_detach()'ed piece of
memory, giving the ownership away.

The whole point of using get_pathname() is to allow callers not to
care about allocation issues on the paths they scribble on during
their short-and-simple codepaths that do not have too many uses of
similar temporary path buffers.  Why borrow from that round-robin
pool (which may now cause some codepaths to overflow the number of
such active temporary path buffers---have they been all audited)?

Is there a reason not to do just an equivalent of

#define git_pathdup mkpathdup

and be done with it?  Am I missing something?

  char *mkpathdup(const char *fmt, ...)
  {
 - char *path;
   struct strbuf sb = STRBUF_INIT;
   va_list args;
 -
   va_start(args, fmt);
   strbuf_vaddf(sb, fmt, args);
   va_end(args);
 - path = xstrdup(cleanup_path(sb.buf));
 -
 - strbuf_release(sb);
 - return path;
 + strbuf_cleanup_path(sb);
 + return strbuf_detach(sb, NULL);
  }
  
  char *mkpath(const char *fmt, ...)
  {
   va_list args;
 - unsigned len;
 - char *pathname = get_pathname();
 -
 + struct strbuf *pathname = get_pathname();
   va_start(args, fmt);
 - len = vsnprintf(pathname, PATH_MAX, fmt, args);
 + strbuf_vaddf(pathname, fmt, args);
   va_end(args);
 - if (len = PATH_MAX)
 - return bad_path;
 - return cleanup_path(pathname);
 + return cleanup_path(pathname-buf);
  }

On the other hand, this one does seem correct.

  char *git_path(const char *fmt, ...)
  {
 - char *pathname = get_pathname();
 + struct strbuf *pathname = get_pathname();
   va_list args;
 - char *ret;
 -
   va_start(args, fmt);
 - ret = vsnpath(pathname, PATH_MAX, fmt, args);
 + vsnpath(pathname, fmt, args);
   va_end(args);
 - return ret;
 + return pathname-buf;
  }

So does this.

Thanks.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 01/25] path.c: make get_pathname() return strbuf instead of static buffer

2014-02-18 Thread Nguyễn Thái Ngọc Duy
We've been avoiding PATH_MAX whenever possible. This patch makes
get_pathname() return a strbuf and updates the callers to take
advantage of this. The code is simplified as we no longer need to
worry about buffer overflow.

Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
---
 path.c | 119 +++--
 1 file changed, 50 insertions(+), 69 deletions(-)

diff --git a/path.c b/path.c
index 24594c4..1a1b784 100644
--- a/path.c
+++ b/path.c
@@ -16,11 +16,15 @@ static int get_st_mode_bits(const char *path, int *mode)
 
 static char bad_path[] = /bad-path/;
 
-static char *get_pathname(void)
+static struct strbuf *get_pathname()
 {
-   static char pathname_array[4][PATH_MAX];
+   static struct strbuf pathname_array[4] = {
+   STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT
+   };
static int index;
-   return pathname_array[3  ++index];
+   struct strbuf *sb = pathname_array[3  ++index];
+   strbuf_reset(sb);
+   return sb;
 }
 
 static char *cleanup_path(char *path)
@@ -34,6 +38,13 @@ static char *cleanup_path(char *path)
return path;
 }
 
+static void strbuf_cleanup_path(struct strbuf *sb)
+{
+   char *path = cleanup_path(sb-buf);
+   if (path  sb-buf)
+   strbuf_remove(sb, 0, path - sb-buf);
+}
+
 char *mksnpath(char *buf, size_t n, const char *fmt, ...)
 {
va_list args;
@@ -49,85 +60,69 @@ char *mksnpath(char *buf, size_t n, const char *fmt, ...)
return cleanup_path(buf);
 }
 
-static char *vsnpath(char *buf, size_t n, const char *fmt, va_list args)
+static void vsnpath(struct strbuf *buf, const char *fmt, va_list args)
 {
const char *git_dir = get_git_dir();
-   size_t len;
-
-   len = strlen(git_dir);
-   if (n  len + 1)
-   goto bad;
-   memcpy(buf, git_dir, len);
-   if (len  !is_dir_sep(git_dir[len-1]))
-   buf[len++] = '/';
-   len += vsnprintf(buf + len, n - len, fmt, args);
-   if (len = n)
-   goto bad;
-   return cleanup_path(buf);
-bad:
-   strlcpy(buf, bad_path, n);
-   return buf;
+   strbuf_addstr(buf, git_dir);
+   if (buf-len  !is_dir_sep(buf-buf[buf-len - 1]))
+   strbuf_addch(buf, '/');
+   strbuf_vaddf(buf, fmt, args);
+   strbuf_cleanup_path(buf);
 }
 
 char *git_snpath(char *buf, size_t n, const char *fmt, ...)
 {
-   char *ret;
+   struct strbuf *sb = get_pathname();
va_list args;
va_start(args, fmt);
-   ret = vsnpath(buf, n, fmt, args);
+   vsnpath(sb, fmt, args);
va_end(args);
-   return ret;
+   if (sb-len = n)
+   strlcpy(buf, bad_path, n);
+   else
+   memcpy(buf, sb-buf, sb-len + 1);
+   return buf;
 }
 
 char *git_pathdup(const char *fmt, ...)
 {
-   char path[PATH_MAX], *ret;
+   struct strbuf *path = get_pathname();
va_list args;
va_start(args, fmt);
-   ret = vsnpath(path, sizeof(path), fmt, args);
+   vsnpath(path, fmt, args);
va_end(args);
-   return xstrdup(ret);
+   return strbuf_detach(path, NULL);
 }
 
 char *mkpathdup(const char *fmt, ...)
 {
-   char *path;
struct strbuf sb = STRBUF_INIT;
va_list args;
-
va_start(args, fmt);
strbuf_vaddf(sb, fmt, args);
va_end(args);
-   path = xstrdup(cleanup_path(sb.buf));
-
-   strbuf_release(sb);
-   return path;
+   strbuf_cleanup_path(sb);
+   return strbuf_detach(sb, NULL);
 }
 
 char *mkpath(const char *fmt, ...)
 {
va_list args;
-   unsigned len;
-   char *pathname = get_pathname();
-
+   struct strbuf *pathname = get_pathname();
va_start(args, fmt);
-   len = vsnprintf(pathname, PATH_MAX, fmt, args);
+   strbuf_vaddf(pathname, fmt, args);
va_end(args);
-   if (len = PATH_MAX)
-   return bad_path;
-   return cleanup_path(pathname);
+   return cleanup_path(pathname-buf);
 }
 
 char *git_path(const char *fmt, ...)
 {
-   char *pathname = get_pathname();
+   struct strbuf *pathname = get_pathname();
va_list args;
-   char *ret;
-
va_start(args, fmt);
-   ret = vsnpath(pathname, PATH_MAX, fmt, args);
+   vsnpath(pathname, fmt, args);
va_end(args);
-   return ret;
+   return pathname-buf;
 }
 
 void home_config_paths(char **global, char **xdg, char *file)
@@ -158,41 +153,27 @@ void home_config_paths(char **global, char **xdg, char 
*file)
 
 char *git_path_submodule(const char *path, const char *fmt, ...)
 {
-   char *pathname = get_pathname();
-   struct strbuf buf = STRBUF_INIT;
+   struct strbuf *buf = get_pathname();
const char *git_dir;
va_list args;
-   unsigned len;
-
-   len = strlen(path);
-   if (len  PATH_MAX-100)
-   return bad_path;
 
-   strbuf_addstr(buf, path);
-   if (len  path[len-1] !=