On 21 October 2014 10:02, Yousong Zhou <yszhou4t...@gmail.com> wrote: > Hi, Pär. I got a few comments inline. > > On 21 October 2014 05:47, Pär Karlsson <feino...@gmail.com> wrote: >> Whoops, I realised I failed on the GNU coding standards, please disregard >> the last one; the patch below should be better. >> >> My apologies :-/ >> >> /Pär >> >> diff --git a/src/ChangeLog b/src/ChangeLog >> index d5aeca0..87abd85 100644 >> --- a/src/ChangeLog >> +++ b/src/ChangeLog >> @@ -1,3 +1,8 @@ >> +2014-10-20 Pär Karlsson <feino...@gmail.com> >> + >> + * utils.c (concat_strings): got rid of double loop, cleaned up >> potential >> + memory corruption if concat_strings was called with more than five >> args >> + >> 2014-10-16 Tim Ruehsen <tim.rueh...@gmx.de> >> >> * url.c (url_parse): little code cleanup >> diff --git a/src/utils.c b/src/utils.c >> index 78c282e..5f359e0 100644 >> --- a/src/utils.c >> +++ b/src/utils.c >> @@ -356,42 +356,36 @@ char * >> concat_strings (const char *str0, ...) >> { >> va_list args; >> - int saved_lengths[5]; /* inspired by Apache's apr_pstrcat */ >> char *ret, *p; >> >> const char *next_str; >> - int total_length = 0; >> - size_t argcount; >> + size_t len; >> + size_t total_length = 0; >> + size_t charsize = sizeof (char); > > I am not sure here. Do we always assume sizeof(char) to be 1 for > platforms supported by wget? > >> + size_t chunksize = 64; >> + size_t bufsize = 64; >> + >> + p = ret = xmalloc (charsize * bufsize); >> >> /* Calculate the length of and allocate the resulting string. */ >> >> - argcount = 0; >> va_start (args, str0); >> for (next_str = str0; next_str != NULL; next_str = va_arg (args, char *)) >> { >> - int len = strlen (next_str); >> - if (argcount < countof (saved_lengths)) >> - saved_lengths[argcount++] = len; >> + len = strlen (next_str); >> + if (len == 0) >> + continue; >> total_length += len; >> - } >> - va_end (args); >> - p = ret = xmalloc (total_length + 1); >> - >> - /* Copy the strings into the allocated space. */ >> - >> - argcount = 0; >> - va_start (args, str0); >> - for (next_str = str0; next_str != NULL; next_str = va_arg (args, char *)) >> - { >> - int len; >> - if (argcount < countof (saved_lengths)) >> - len = saved_lengths[argcount++]; >> - else >> - len = strlen (next_str); >> + if (total_length > bufsize) >> + { >> + bufsize += chunksize; > > Should be `bufsize = total_length` ? > >> + ret = xrealloc (ret, charsize * bufsize); >> + } >> memcpy (p, next_str, len); > > Xrealloc may return a new block different from p, so memcpy(p, ...) > may not be what you want. > >> p += len; >> } >> va_end (args); >> + ret = xrealloc (ret, charsize * total_length + 1); >> *p = '\0'; > > Malloc takes time. How about counting total_length in one loop and > doing the copy in another?
I mean, we can skip the strlen part and just do strcpy in the second loop as we already know we have enough space in the dest buffer for all those null-terminated arguments. yousong