[PATCH v3 2/2] stop_progress_msg(): simplification function

2017-02-16 Thread Maxim Moseychuk
stop_progress_msg() is rarely used and is not demanding to
performance. Use dynamically allocates memory.

Signed-off-by: Maxim Moseychuk <franchesko.salias.hudro.ped...@gmail.com>
---
 progress.c | 11 ---
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/progress.c b/progress.c
index 76a88c573..29378caa0 100644
--- a/progress.c
+++ b/progress.c
@@ -243,21 +243,18 @@ void stop_progress_msg(struct progress **p_progress, 
const char *msg)
*p_progress = NULL;
if (progress->last_value != -1) {
/* Force the last update */
-   char buf[128], *bufp;
-   size_t len = strlen(msg) + 5;
+   char *buf;
struct throughput *tp = progress->throughput;
 
-   bufp = (len < sizeof(buf)) ? buf : xmallocz(len);
if (tp) {
unsigned int rate = !tp->avg_misecs ? 0 :
tp->avg_bytes / tp->avg_misecs;
throughput_string(>display, tp->curr_total, rate);
}
progress_update = 1;
-   xsnprintf(bufp, len + 1, ", %s.\n", msg);
-   display(progress, progress->last_value, bufp);
-   if (buf != bufp)
-   free(bufp);
+   buf = xstrfmt(", %s.\n", msg);
+   display(progress, progress->last_value, buf);
+   free(buf);
}
clear_progress_signal();
if (progress->throughput)
-- 
2.11.1



[PATCH v3 0/2] Fix l10n

2017-02-16 Thread Maxim Moseychuk
In some places fixed-size buffers can't store formatted string.
If it be happen then git die.

Jonathan Tan, Jeff King thanks a lot for your help.
This is really my first patches. Your help is invaluable.

Maxim Moseychuk (2):
  bisect_next_all(): fix bisect crash when used the gettext translation
  stop_progress_msg(): simplification function

 bisect.c   |  9 +
 progress.c | 11 ---
 2 files changed, 9 insertions(+), 11 deletions(-)

--
2.11.1



[PATCH v3 1/2] bisect_next_all(): fix bisect crash when used the gettext translation

2017-02-16 Thread Maxim Moseychuk
The buffer steps_msg[32] is too small.
Translated "(roughly %d step)" string can not be located in the buffer.

Solution: using xstrfmt which dynamically allocates memory.

Dummy solution: just increase steps_msg size but is not safe.
That feels pretty hacky, though. In practice the set of translations is
contained, but it doesn't have to be (and certainly nobody would notice
if a new translation was added with a longer name until a user
complained).

Reproduce bug: "LANG=ru_RU.UTF8 git bisect start v4.9 v4.8" on linux sources.

Signed-off-by: Maxim Moseychuk <franchesko.salias.hudro.ped...@gmail.com>
---
 bisect.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/bisect.c b/bisect.c
index 21bc6daa4..787543cad 100644
--- a/bisect.c
+++ b/bisect.c
@@ -940,7 +940,7 @@ int bisect_next_all(const char *prefix, int no_checkout)
struct commit_list *tried;
int reaches = 0, all = 0, nr, steps;
const unsigned char *bisect_rev;
-   char steps_msg[32];
+   char *steps_msg;
 
read_bisect_terms(_bad, _good);
if (read_bisect_refs())
@@ -990,14 +990,15 @@ int bisect_next_all(const char *prefix, int no_checkout)
 
nr = all - reaches - 1;
steps = estimate_bisect_steps(all);
-   xsnprintf(steps_msg, sizeof(steps_msg),
- Q_("(roughly %d step)", "(roughly %d steps)", steps),
- steps);
+
+   steps_msg = xstrfmt(Q_("(roughly %d step)", "(roughly %d steps)",
+ steps), steps);
/* TRANSLATORS: the last %s will be replaced with
   "(roughly %d steps)" translation */
printf(Q_("Bisecting: %d revision left to test after this %s\n",
  "Bisecting: %d revisions left to test after this %s\n",
  nr), nr, steps_msg);
+   free(steps_msg);
 
return bisect_checkout(bisect_rev, no_checkout);
 }
-- 
2.11.1



[PATCH V2 0/2] Fix l10n

2017-02-16 Thread Maxim Moseychuk
In some places static size buffers can't store formatted string.
If it be happen then git die.

Jonathan Tan: Thanks a lot for your help.

Maxim Moseychuk (2):
  bisect_next_all: convert xsnprintf to xstrfmt
  stop_progress_msg: convert xsnprintf to xstrfmt

 bisect.c   | 9 +
 progress.c | 9 +++--
 2 files changed, 8 insertions(+), 10 deletions(-)

--
2.11.1



[PATCH V2 1/2] bisect_next_all: convert xsnprintf to xstrfmt

2017-02-16 Thread Maxim Moseychuk
Git can't run bisect between 2048+ commits if use russian translation.
Reproduce "LANG=ru_RU.UTF8 git bisect start v4.9 v4.8" on linux sources.

Dummy solution: just increase buffer size but is not safe.
Size gettext string is a runtime value.

Signed-off-by: Maxim Moseychuk <franchesko.salias.hudro.ped...@gmail.com>
---
 bisect.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/bisect.c b/bisect.c
index 21bc6daa4..787543cad 100644
--- a/bisect.c
+++ b/bisect.c
@@ -940,7 +940,7 @@ int bisect_next_all(const char *prefix, int no_checkout)
struct commit_list *tried;
int reaches = 0, all = 0, nr, steps;
const unsigned char *bisect_rev;
-   char steps_msg[32];
+   char *steps_msg;
 
read_bisect_terms(_bad, _good);
if (read_bisect_refs())
@@ -990,14 +990,15 @@ int bisect_next_all(const char *prefix, int no_checkout)
 
nr = all - reaches - 1;
steps = estimate_bisect_steps(all);
-   xsnprintf(steps_msg, sizeof(steps_msg),
- Q_("(roughly %d step)", "(roughly %d steps)", steps),
- steps);
+
+   steps_msg = xstrfmt(Q_("(roughly %d step)", "(roughly %d steps)",
+ steps), steps);
/* TRANSLATORS: the last %s will be replaced with
   "(roughly %d steps)" translation */
printf(Q_("Bisecting: %d revision left to test after this %s\n",
  "Bisecting: %d revisions left to test after this %s\n",
  nr), nr, steps_msg);
+   free(steps_msg);
 
return bisect_checkout(bisect_rev, no_checkout);
 }
-- 
2.11.1



[PATCH V2 2/2] stop_progress_msg: convert xsnprintf to xstrfmt

2017-02-16 Thread Maxim Moseychuk
Replace local safe string buffer allocation by xstrfmt.

Signed-off-by: Maxim Moseychuk <franchesko.salias.hudro.ped...@gmail.com>
---
 progress.c | 9 +++--
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/progress.c b/progress.c
index 76a88c573..29d0dad58 100644
--- a/progress.c
+++ b/progress.c
@@ -243,21 +243,18 @@ void stop_progress_msg(struct progress **p_progress, 
const char *msg)
*p_progress = NULL;
if (progress->last_value != -1) {
/* Force the last update */
-   char buf[128], *bufp;
-   size_t len = strlen(msg) + 5;
+   char *bufp;
struct throughput *tp = progress->throughput;
 
-   bufp = (len < sizeof(buf)) ? buf : xmallocz(len);
if (tp) {
unsigned int rate = !tp->avg_misecs ? 0 :
tp->avg_bytes / tp->avg_misecs;
throughput_string(>display, tp->curr_total, rate);
}
progress_update = 1;
-   xsnprintf(bufp, len + 1, ", %s.\n", msg);
+   bufp = xstrfmt(", %s.\n", msg);
display(progress, progress->last_value, bufp);
-   if (buf != bufp)
-   free(bufp);
+   free(bufp);
}
clear_progress_signal();
if (progress->throughput)
-- 
2.11.1



[PATCH 0/3] Fix l10n

2017-02-16 Thread Maxim Moseychuk
In some places static size buffers can't store formatted string.
If it be happen then git die.

Maxim Moseychuk (3):
  add git_psprintf helper function
  bisect_next_all: convert xsnprintf to git_psprintf
  stop_progress_msg: convert xsnprintf to git_psprintf

 bisect.c  |  9 +
 git-compat-util.h |  3 +++
 progress.c|  9 +++--
 wrapper.c | 19 +++
 4 files changed, 30 insertions(+), 10 deletions(-)

-- 
2.11.1



[PATCH 2/3] bisect_next_all: convert xsnprintf to git_psprintf

2017-02-16 Thread Maxim Moseychuk
Git can't run bisect between 2048+ commits if use russian translation.
Reproduce "LANG=ru_RU.UTF8 git bisect start v4.9 v4.8" on linux sources.

Dummy solution: just increase buffer size but is not safe.
Size gettext string is a runtime value.

Signed-off-by: Maxim Moseychuk <franchesko.salias.hudro.ped...@gmail.com>
---
 bisect.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/bisect.c b/bisect.c
index 21bc6daa4..8670cc97a 100644
--- a/bisect.c
+++ b/bisect.c
@@ -940,7 +940,7 @@ int bisect_next_all(const char *prefix, int no_checkout)
struct commit_list *tried;
int reaches = 0, all = 0, nr, steps;
const unsigned char *bisect_rev;
-   char steps_msg[32];
+   char *steps_msg;
 
read_bisect_terms(_bad, _good);
if (read_bisect_refs())
@@ -990,14 +990,15 @@ int bisect_next_all(const char *prefix, int no_checkout)
 
nr = all - reaches - 1;
steps = estimate_bisect_steps(all);
-   xsnprintf(steps_msg, sizeof(steps_msg),
- Q_("(roughly %d step)", "(roughly %d steps)", steps),
- steps);
+
+   steps_msg = git_psprintf(Q_("(roughly %d step)", "(roughly %d steps)",
+ steps), steps);
/* TRANSLATORS: the last %s will be replaced with
   "(roughly %d steps)" translation */
printf(Q_("Bisecting: %d revision left to test after this %s\n",
  "Bisecting: %d revisions left to test after this %s\n",
  nr), nr, steps_msg);
+   free(steps_msg);
 
return bisect_checkout(bisect_rev, no_checkout);
 }
-- 
2.11.1



[PATCH 3/3] stop_progress_msg: convert xsnprintf to git_psprintf

2017-02-16 Thread Maxim Moseychuk
Replace local safe string buffer allocation by git_psprintf.

Signed-off-by: Maxim Moseychuk <franchesko.salias.hudro.ped...@gmail.com>
---
 progress.c | 9 +++--
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/progress.c b/progress.c
index 76a88c573..989d65504 100644
--- a/progress.c
+++ b/progress.c
@@ -243,21 +243,18 @@ void stop_progress_msg(struct progress **p_progress, 
const char *msg)
*p_progress = NULL;
if (progress->last_value != -1) {
/* Force the last update */
-   char buf[128], *bufp;
-   size_t len = strlen(msg) + 5;
+   char *bufp;
struct throughput *tp = progress->throughput;
 
-   bufp = (len < sizeof(buf)) ? buf : xmallocz(len);
if (tp) {
unsigned int rate = !tp->avg_misecs ? 0 :
tp->avg_bytes / tp->avg_misecs;
throughput_string(>display, tp->curr_total, rate);
}
progress_update = 1;
-   xsnprintf(bufp, len + 1, ", %s.\n", msg);
+   bufp = git_psprintf(", %s.\n", msg);
display(progress, progress->last_value, bufp);
-   if (buf != bufp)
-   free(bufp);
+   free(bufp);
}
clear_progress_signal();
if (progress->throughput)
-- 
2.11.1



[PATCH 1/3] add git_psprintf helper function

2017-02-16 Thread Maxim Moseychuk
There are a number of places in the code where we call
xsnprintf(), with the assumption that the output will fit into
the buffer. If the buffer is small, then git die.
In many places buffers have compile-time size, but generated string
depends from current system locale (gettext)and can have size
greater the buffer.
Just run "LANG=ru_RU.UTF8 git bisect start v4.9 v4.8"
on linux sources - it impossible.

git_psprintf is similar to the standard C sprintf() function
but safer, since it calculates the maximum space required
and allocates memory to hold the result.
The returned string should be freed with free() when no longer needed.

Signed-off-by: Maxim Moseychuk <franchesko.salias.hudro.ped...@gmail.com>
---
 git-compat-util.h |  3 +++
 wrapper.c | 19 +++
 2 files changed, 22 insertions(+)

diff --git a/git-compat-util.h b/git-compat-util.h
index 87237b092..fa98705d0 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -878,6 +878,9 @@ static inline size_t xsize_t(off_t len)
return (size_t)len;
 }
 
+__attribute__((format (printf, 1, 2)))
+extern char *git_psprintf(const char *fmt, ...);
+
 __attribute__((format (printf, 3, 4)))
 extern int xsnprintf(char *dst, size_t max, const char *fmt, ...);
 
diff --git a/wrapper.c b/wrapper.c
index e7f197996..deee46d2d 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -635,6 +635,25 @@ char *xgetcwd(void)
return strbuf_detach(, NULL);
 }
 
+char *git_psprintf(const char *fmt, ...)
+{
+   va_list ap;
+   int len;
+   char *dst;
+
+   va_start(ap, fmt);
+   len = vsnprintf(NULL, 0, fmt, ap);
+   va_end(ap);
+
+   dst = xmallocz(len);
+
+   va_start(ap, fmt);
+   vsprintf(dst, fmt, ap);
+   va_end(ap);
+
+   return dst;
+}
+
 int xsnprintf(char *dst, size_t max, const char *fmt, ...)
 {
va_list ap;
-- 
2.11.1