{"thread":{"id":"27186","subject":"[PATCH] strbuf: allocate enough space when strbuf_setlen() is called first time","startedAt":"2011-04-26T12:24:20Z","lastAt":"2011-04-28T16:57:58Z","messageCount":11,"participants":["Nguyễn Thái Ngọc Duy","Nguyen Thai Ngoc Duy","Junio C Hamano","René Scharfe"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"166375","messageId":"1303820660-744-1-git-send-email-pclouds@gmail.com","threadId":"27186","inReplyTo":null,"subject":"[PATCH] strbuf: allocate enough space when strbuf_setlen() is called first time","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2011-04-26T12:24:20Z","receivedAt":"2011-04-26T12:24:20Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"strbuf_grow(sb, 0) may allocate less than requested len and violate the\nnext assertion.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n strbuf.h |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\ndiff --git a/strbuf.h b/strbuf.h\nindex 07060ce..ab213da 100644\n--- a/strbuf.h\n+++ b/strbuf.h\n@@ -34,7 +34,7 @@ extern void strbuf_grow(struct strbuf *, size_t);\n \n static inline void strbuf_setlen(struct strbuf *sb, size_t len) {\n \tif (!sb->alloc)\n-\t\tstrbuf_grow(sb, 0);\n+\t\tstrbuf_grow(sb, len);\n \tassert(len < sb->alloc);\n \tsb->len = len;\n \tsb->buf[len] = '\\0';\n-- \n1.7.4.74.g639db\n"},{"id":"166382","messageId":"20110426150933.GA29121@do","threadId":"27186","inReplyTo":"1303820660-744-1-git-send-email-pclouds@gmail.com","subject":"Re: [PATCH] strbuf: allocate enough space when strbuf_setlen() is called first time","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2011-04-26T15:09:33Z","receivedAt":"2011-04-26T15:09:33Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Tue, Apr 26, 2011 at 07:24:20PM +0700, Nguyễn Thái Ngọc Duy wrote:\n>  static inline void strbuf_setlen(struct strbuf *sb, size_t len) {\n>  \tif (!sb->alloc)\n> -\t\tstrbuf_grow(sb, 0);\n> +\t\tstrbuf_grow(sb, len);\n>  \tassert(len < sb->alloc);\n>  \tsb->len = len;\n>  \tsb->buf[len] = '\\0';\n\nThis should be better. But I fail to see why it corrupts memory :(\n\n@@ -33,9 +33,8 @@ static inline size_t strbuf_avail(const struct strbuf *sb) {\n extern void strbuf_grow(struct strbuf *, size_t);\n \n static inline void strbuf_setlen(struct strbuf *sb, size_t len) {\n-\tif (!sb->alloc)\n-\t\tstrbuf_grow(sb, 0);\n-\tassert(len < sb->alloc);\n+\tif (sb->alloc < len + 1)\n+\t\tstrbuf_grow(sb, len - sb->alloc);\n \tsb->len = len;\n \tsb->buf[len] = '\\0';\n }\n\n-- \nDuy\n"},{"id":"166384","messageId":"7v7hahghls.fsf@alter.siamese.dyndns.org","threadId":"27186","inReplyTo":"1303820660-744-1-git-send-email-pclouds@gmail.com","subject":"Re: [PATCH] strbuf: allocate enough space when strbuf_setlen() is called first time","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-04-26T15:25:19Z","receivedAt":"2011-04-26T15:25:19Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes:\n\n> strbuf_grow(sb, 0) may allocate less than requested len and violate the\n> next assertion.\n>\n> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n> ---\n>  strbuf.h |    2 +-\n>  1 files changed, 1 insertions(+), 1 deletions(-)\n>\n> diff --git a/strbuf.h b/strbuf.h\n> index 07060ce..ab213da 100644\n> --- a/strbuf.h\n> +++ b/strbuf.h\n> @@ -34,7 +34,7 @@ extern void strbuf_grow(struct strbuf *, size_t);\n>  \n>  static inline void strbuf_setlen(struct strbuf *sb, size_t len) {\n>  \tif (!sb->alloc)\n> -\t\tstrbuf_grow(sb, 0);\n> +\t\tstrbuf_grow(sb, len);\n>  \tassert(len < sb->alloc);\n\nThis looks so obviously correct that it is scary.\n\nHow could 60 callsites of this function manage to have run without crashes\nso far?  They all happen to use the function on a buffer that already has\nsomething on it?\n\nWell spotted, thanks.\n"},{"id":"166387","messageId":"BANLkTi=ECjmjBLfS=s6fMWXgtxDYmxcP5g@mail.gmail.com","threadId":"27186","inReplyTo":"7v7hahghls.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] strbuf: allocate enough space when strbuf_setlen() is called first time","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2011-04-26T15:32:31Z","receivedAt":"2011-04-26T15:32:31Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"2011/4/26 Junio C Hamano <gitster@pobox.com>:\n> Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes:\n>\n>> strbuf_grow(sb, 0) may allocate less than requested len and violate the\n>> next assertion.\n>>\n>> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n>> ---\n>>  strbuf.h |    2 +-\n>>  1 files changed, 1 insertions(+), 1 deletions(-)\n>>\n>> diff --git a/strbuf.h b/strbuf.h\n>> index 07060ce..ab213da 100644\n>> --- a/strbuf.h\n>> +++ b/strbuf.h\n>> @@ -34,7 +34,7 @@ extern void strbuf_grow(struct strbuf *, size_t);\n>>\n>>  static inline void strbuf_setlen(struct strbuf *sb, size_t len) {\n>>       if (!sb->alloc)\n>> -             strbuf_grow(sb, 0);\n>> +             strbuf_grow(sb, len);\n>>       assert(len < sb->alloc);\n>\n> This looks so obviously correct that it is scary.\n>\n> How could 60 callsites of this function manage to have run without crashes\n> so far?  They all happen to use the function on a buffer that already has\n> something on it?\n\nI guess no current call site does _setlen right after initialization.\nIt's new code that triggers it.\n-- \nDuy\n"},{"id":"166393","messageId":"4DB6F8D3.6040200@lsrfire.ath.cx","threadId":"27186","inReplyTo":"BANLkTi=ECjmjBLfS=s6fMWXgtxDYmxcP5g@mail.gmail.com","subject":"Re: [PATCH] strbuf: allocate enough space when strbuf_setlen() is called first time","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2011-04-26T16:54:43Z","receivedAt":"2011-04-26T16:54:43Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Am 26.04.2011 17:32, schrieb Nguyen Thai Ngoc Duy:\n> 2011/4/26 Junio C Hamano<gitster@pobox.com>:\n>> Nguyễn Thái Ngọc Duy<pclouds@gmail.com>  writes:\n>>\n>>> strbuf_grow(sb, 0) may allocate less than requested len and violate the\n>>> next assertion.\n>>>\n>>> Signed-off-by: Nguyễn Thái Ngọc Duy<pclouds@gmail.com>\n>>> ---\n>>>   strbuf.h |    2 +-\n>>>   1 files changed, 1 insertions(+), 1 deletions(-)\n>>>\n>>> diff --git a/strbuf.h b/strbuf.h\n>>> index 07060ce..ab213da 100644\n>>> --- a/strbuf.h\n>>> +++ b/strbuf.h\n>>> @@ -34,7 +34,7 @@ extern void strbuf_grow(struct strbuf *, size_t);\n>>>\n>>>   static inline void strbuf_setlen(struct strbuf *sb, size_t len) {\n>>>        if (!sb->alloc)\n>>> -             strbuf_grow(sb, 0);\n>>> +             strbuf_grow(sb, len);\n>>>        assert(len<  sb->alloc);\n>>\n>> This looks so obviously correct that it is scary.\n>>\n>> How could 60 callsites of this function manage to have run without crashes\n>> so far?  They all happen to use the function on a buffer that already has\n>> something on it?\n>\n> I guess no current call site does _setlen right after initialization.\n> It's new code that triggers it.\n\nDocumentation/technical/api-strbuf.txt says that you can't use \nstrbuf_setlen() to allocate more space for a strbuf, i.e. you can use it \nonly to shorten a string or set it to its current length.  If the strbuf \nin question hasn't allocated any buffer at all (sb->alloc == 0) then the \nonly valid len is zero.\n\nWhere is it used to extend strbufs, i.e. which is the new code you \nmentioned?\n\nRené\n"},{"id":"166396","messageId":"7vaafdexsp.fsf@alter.siamese.dyndns.org","threadId":"27186","inReplyTo":"1303820660-744-1-git-send-email-pclouds@gmail.com","subject":"Re: [PATCH] strbuf: allocate enough space when strbuf_setlen() is called first time","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-04-26T17:18:30Z","receivedAt":"2011-04-26T17:18:30Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n\n> strbuf_grow(sb, 0) may allocate less than requested len and violate the\n> next assertion.\n>\n> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n> ---\n>  strbuf.h |    2 +-\n>  1 files changed, 1 insertions(+), 1 deletions(-)\n>\n> diff --git a/strbuf.h b/strbuf.h\n> index 07060ce..ab213da 100644\n> --- a/strbuf.h\n> +++ b/strbuf.h\n> @@ -34,7 +34,7 @@ extern void strbuf_grow(struct strbuf *, size_t);\n>  \n>  static inline void strbuf_setlen(struct strbuf *sb, size_t len) {\n>  \tif (!sb->alloc)\n> -\t\tstrbuf_grow(sb, 0);\n> +\t\tstrbuf_grow(sb, len);\n>  \tassert(len < sb->alloc);\n\nWait.  Isn't _setlen() meant to be used only to truncate at the length,\nand isn't that clearly documented?\n\nI don't think we need this patch at all.\n"},{"id":"166413","messageId":"4DB738A1.8020706@lsrfire.ath.cx","threadId":"27186","inReplyTo":"7vaafdexsp.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] strbuf: allocate enough space when strbuf_setlen() is called first time","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2011-04-26T21:26:57Z","receivedAt":"2011-04-26T21:26:57Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Am 26.04.2011 19:18, schrieb Junio C Hamano:\n> Nguyễn Thái Ngọc Duy<pclouds@gmail.com>  writes:\n> \n>> strbuf_grow(sb, 0) may allocate less than requested len and violate the\n>> next assertion.\n>>\n>> Signed-off-by: Nguyễn Thái Ngọc Duy<pclouds@gmail.com>\n>> ---\n>>   strbuf.h |    2 +-\n>>   1 files changed, 1 insertions(+), 1 deletions(-)\n>>\n>> diff --git a/strbuf.h b/strbuf.h\n>> index 07060ce..ab213da 100644\n>> --- a/strbuf.h\n>> +++ b/strbuf.h\n>> @@ -34,7 +34,7 @@ extern void strbuf_grow(struct strbuf *, size_t);\n>>\n>>   static inline void strbuf_setlen(struct strbuf *sb, size_t len) {\n>>   \tif (!sb->alloc)\n>> -\t\tstrbuf_grow(sb, 0);\n>> +\t\tstrbuf_grow(sb, len);\n>>   \tassert(len<  sb->alloc);\n> \n> Wait.  Isn't _setlen() meant to be used only to truncate at the length,\n> and isn't that clearly documented?\n> \n> I don't think we need this patch at all.\n\nHow about something like this instead?  The call to strbuf_grow() was\nintroduced in a8f3e2219 when there was no strbuf_slopbuf buffer that\nnowadays makes sure we always have a place to write an initial NUL.\nWe can take it out again now, simplifying the code and hopefully\navoiding future confusion.\n\n strbuf.h |    4 +---\n 1 files changed, 1 insertions(+), 3 deletions(-)\n\ndiff --git a/strbuf.h b/strbuf.h\nindex 07060ce..b157ede 100644\n--- a/strbuf.h\n+++ b/strbuf.h\n@@ -33,9 +33,7 @@ static inline size_t strbuf_avail(const struct strbuf *sb) {\n extern void strbuf_grow(struct strbuf *, size_t);\n \n static inline void strbuf_setlen(struct strbuf *sb, size_t len) {\n-\tif (!sb->alloc)\n-\t\tstrbuf_grow(sb, 0);\n-\tassert(len < sb->alloc);\n+\tassert(len < (sb->alloc ? sb->alloc : 1));\n \tsb->len = len;\n \tsb->buf[len] = '\\0';\n }\n"},{"id":"166414","messageId":"7vhb9kd6kp.fsf@alter.siamese.dyndns.org","threadId":"27186","inReplyTo":"4DB738A1.8020706@lsrfire.ath.cx","subject":"Re: [PATCH] strbuf: allocate enough space when strbuf_setlen() is called first time","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-04-26T21:51:50Z","receivedAt":"2011-04-26T21:51:50Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"René Scharfe <rene.scharfe@lsrfire.ath.cx> writes:\n\n> How about something like this instead?  The call to strbuf_grow() was\n> introduced in a8f3e2219 when there was no strbuf_slopbuf buffer that\n> nowadays makes sure we always have a place to write an initial NUL.\n> We can take it out again now, simplifying the code and hopefully\n> avoiding future confusion.\n\nThanks; I think that makes sense.\n\nIt further may make sense to turn the assert into BUG() though, to clarify\nwhat kind of programming error we are trying to catch.  Perhaps like:\n\n>  static inline void strbuf_setlen(struct strbuf *sb, size_t len) {\n> +\tassert(len < (sb->alloc ? sb->alloc : 1));\n\n\tif (len < (sb->alloc ? sb->alloc : 1))\n\t\tdie(\"programming error: using strbuf_setlen() to extend a strbuf\");\n\n>  \tsb->len = len;\n>  \tsb->buf[len] = '\\0';\n>  }\n"},{"id":"166422","messageId":"BANLkTi=vqgWgS2D2cD3Qwk1Z7_jqLarR3g@mail.gmail.com","threadId":"27186","inReplyTo":"4DB738A1.8020706@lsrfire.ath.cx","subject":"Re: [PATCH] strbuf: allocate enough space when strbuf_setlen() is called first time","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2011-04-27T00:12:53Z","receivedAt":"2011-04-27T00:12:53Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"2011/4/27 René Scharfe <rene.scharfe@lsrfire.ath.cx>:\n> Am 26.04.2011 19:18, schrieb Junio C Hamano:\n>> Nguyễn Thái Ngọc Duy<pclouds@gmail.com>  writes:\n>>\n>>> strbuf_grow(sb, 0) may allocate less than requested len and violate the\n>>> next assertion.\n>>>\n>>> Signed-off-by: Nguyễn Thái Ngọc Duy<pclouds@gmail.com>\n>>> ---\n>>>   strbuf.h |    2 +-\n>>>   1 files changed, 1 insertions(+), 1 deletions(-)\n>>>\n>>> diff --git a/strbuf.h b/strbuf.h\n>>> index 07060ce..ab213da 100644\n>>> --- a/strbuf.h\n>>> +++ b/strbuf.h\n>>> @@ -34,7 +34,7 @@ extern void strbuf_grow(struct strbuf *, size_t);\n>>>\n>>>   static inline void strbuf_setlen(struct strbuf *sb, size_t len) {\n>>>      if (!sb->alloc)\n>>> -            strbuf_grow(sb, 0);\n>>> +            strbuf_grow(sb, len);\n>>>      assert(len<  sb->alloc);\n>>\n>> Wait.  Isn't _setlen() meant to be used only to truncate at the length,\n>> and isn't that clearly documented?\n>>\n>> I don't think we need this patch at all.\n>\n> How about something like this instead?  The call to strbuf_grow() was\n> introduced in a8f3e2219 when there was no strbuf_slopbuf buffer that\n> nowadays makes sure we always have a place to write an initial NUL.\n> We can take it out again now, simplifying the code and hopefully\n> avoiding future confusion.\n>\n>  strbuf.h |    4 +---\n>  1 files changed, 1 insertions(+), 3 deletions(-)\n>\n> diff --git a/strbuf.h b/strbuf.h\n> index 07060ce..b157ede 100644\n> --- a/strbuf.h\n> +++ b/strbuf.h\n> @@ -33,9 +33,7 @@ static inline size_t strbuf_avail(const struct strbuf *sb) {\n>  extern void strbuf_grow(struct strbuf *, size_t);\n>\n>  static inline void strbuf_setlen(struct strbuf *sb, size_t len) {\n> -       if (!sb->alloc)\n> -               strbuf_grow(sb, 0);\n> -       assert(len < sb->alloc);\n> +       assert(len < (sb->alloc ? sb->alloc : 1));\n>        sb->len = len;\n>        sb->buf[len] = '\\0';\n>  }\n>\n>\n\nFine to me. I forgot the document, saw _grow and was under impression\nthat _setlen can grow too.\n-- \nDuy\n"},{"id":"166532","messageId":"4DB85162.6000204@lsrfire.ath.cx","threadId":"27186","inReplyTo":"7vhb9kd6kp.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] strbuf: allocate enough space when strbuf_setlen() is called first time","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2011-04-27T17:24:50Z","receivedAt":"2011-04-27T17:24:50Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Am 26.04.2011 23:51, schrieb Junio C Hamano:\n> René Scharfe<rene.scharfe@lsrfire.ath.cx>  writes:\n> \n>> How about something like this instead?  The call to strbuf_grow() was\n>> introduced in a8f3e2219 when there was no strbuf_slopbuf buffer that\n>> nowadays makes sure we always have a place to write an initial NUL.\n>> We can take it out again now, simplifying the code and hopefully\n>> avoiding future confusion.\n> \n> Thanks; I think that makes sense.\n> \n> It further may make sense to turn the assert into BUG() though, to clarify\n> what kind of programming error we are trying to catch.  Perhaps like:\n> \n>>   static inline void strbuf_setlen(struct strbuf *sb, size_t len) {\n>> +\tassert(len<  (sb->alloc ? sb->alloc : 1));\n> \n> \tif (len<  (sb->alloc ? sb->alloc : 1))\n> \t\tdie(\"programming error: using strbuf_setlen() to extend a strbuf\");\n> \n>>   \tsb->len = len;\n>>   \tsb->buf[len] = '\\0';\n>>   }\n\nI like the idea, except the comparison needs to be inverted.\n\nCompiled, but not tested.  The test suite takes too long and skips too\nmany tests on my Windows box and I don't have any other machine\navailable right now. :-/\n\n-- >8 --\nSubject: strbuf: clarify assertion in strbuf_setlen()\n\nCommit a8f3e2219 introduced the strbuf_grow() call to strbuf_setlen() to\nmake ensure that there was at least one byte available to write the\nmandatory trailing NUL, even for previously unallocated strbufs.\n\nThen b315c5c0 added strbuf_slopbuf for the same reason, only globally for\nall uses of strbufs.\n\nThus the strbuf_grow() call can be removed now.  This avoids readers of\nstrbuf.h from mistakenly thinking that strbuf_setlen() can be used to\nextend a strbuf.\n\nThe following assert() needs to be changed to cope with the fact that\nsb->alloc can now be zero, which is OK as long as len is also zero.  As\nsuggested by Junio, use the chance to convert it to a die() with a short\nexplanatory message.  The pattern of 'die(\"BUG: ...\")' is already used in\nstrbuf.c.\n\nThis was the only assert() in strbuf.[ch], so assert.h doesn't have to be\nincluded anymore either.\n\nSigned-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>\n---\n strbuf.h |    7 ++-----\n 1 files changed, 2 insertions(+), 5 deletions(-)\n\ndiff --git a/strbuf.h b/strbuf.h\nindex 07060ce..9e6d9fa 100644\n--- a/strbuf.h\n+++ b/strbuf.h\n@@ -3,8 +3,6 @@\n \n /* See Documentation/technical/api-strbuf.txt */\n \n-#include <assert.h>\n-\n extern char strbuf_slopbuf[];\n struct strbuf {\n \tsize_t alloc;\n@@ -33,9 +31,8 @@ static inline size_t strbuf_avail(const struct strbuf *sb) {\n extern void strbuf_grow(struct strbuf *, size_t);\n \n static inline void strbuf_setlen(struct strbuf *sb, size_t len) {\n-\tif (!sb->alloc)\n-\t\tstrbuf_grow(sb, 0);\n-\tassert(len < sb->alloc);\n+\tif (len > (sb->alloc ? sb->alloc - 1 : 0))\n+\t\tdie(\"BUG: strbuf_setlen() beyond buffer\");\n \tsb->len = len;\n \tsb->buf[len] = '\\0';\n }\n-- \n1.7.5\n"},{"id":"166659","messageId":"7vtydi48kp.fsf@alter.siamese.dyndns.org","threadId":"27186","inReplyTo":"4DB85162.6000204@lsrfire.ath.cx","subject":"Re: [PATCH] strbuf: allocate enough space when strbuf_setlen() is called first time","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-04-28T16:57:58Z","receivedAt":"2011-04-28T16:57:58Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"René Scharfe <rene.scharfe@lsrfire.ath.cx> writes:\n\n> Subject: strbuf: clarify assertion in strbuf_setlen()\n>\n> Commit a8f3e2219 introduced the strbuf_grow() call to strbuf_setlen() to\n> make ensure that there was at least one byte available to write the\n> mandatory trailing NUL, even for previously unallocated strbufs.\n>\n> Then b315c5c0 added strbuf_slopbuf for the same reason, only globally for\n> all uses of strbufs.\n>\n> Thus the strbuf_grow() call can be removed now.  This avoids readers of\n> strbuf.h from mistakenly thinking that strbuf_setlen() can be used to\n> extend a strbuf.\n>\n> The following assert() needs to be changed to cope with the fact that\n> sb->alloc can now be zero, which is OK as long as len is also zero.  As\n> suggested by Junio, use the chance to convert it to a die() with a short\n> explanatory message.  The pattern of 'die(\"BUG: ...\")' is already used in\n> strbuf.c.\n>\n> This was the only assert() in strbuf.[ch], so assert.h doesn't have to be\n> included anymore either.\n>\n> Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>\n\nVery nicely explained.  I wish everybody wrote his log message as clearly\nas this.\n\nThanks, will queue.\n\n> ---\n>  strbuf.h |    7 ++-----\n>  1 files changed, 2 insertions(+), 5 deletions(-)\n>\n> diff --git a/strbuf.h b/strbuf.h\n> index 07060ce..9e6d9fa 100644\n> --- a/strbuf.h\n> +++ b/strbuf.h\n> @@ -3,8 +3,6 @@\n>  \n>  /* See Documentation/technical/api-strbuf.txt */\n>  \n> -#include <assert.h>\n> -\n>  extern char strbuf_slopbuf[];\n>  struct strbuf {\n>  \tsize_t alloc;\n> @@ -33,9 +31,8 @@ static inline size_t strbuf_avail(const struct strbuf *sb) {\n>  extern void strbuf_grow(struct strbuf *, size_t);\n>  \n>  static inline void strbuf_setlen(struct strbuf *sb, size_t len) {\n> -\tif (!sb->alloc)\n> -\t\tstrbuf_grow(sb, 0);\n> -\tassert(len < sb->alloc);\n> +\tif (len > (sb->alloc ? sb->alloc - 1 : 0))\n> +\t\tdie(\"BUG: strbuf_setlen() beyond buffer\");\n>  \tsb->len = len;\n>  \tsb->buf[len] = '\\0';\n>  }\n"}]}