* [PATCH] fix potential infinite loop given large unsigned integer @ 2009-08-09 4:41 Ryan Flynn 2009-08-09 6:19 ` Junio C Hamano 0 siblings, 1 reply; 14+ messages in thread From: Ryan Flynn @ 2009-08-09 4:41 UTC (permalink / raw) To: git given n, tried to find i greater than n via i=1, iterate i *= 10. given n sufficiently close to UINT_MAX this will overflow; which can produce i==0, which results in an infinite loop. iteratively dividing n /= 10 does not have this problem, and though division is slower than multiplication this only runs once per `git format-patch --cover-letter` Signed-off-by: pizza <parseerror@gmail.com> --- log-tree.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/log-tree.c b/log-tree.c index 6f73c17..53a1bd2 100644 --- a/log-tree.c +++ b/log-tree.c @@ -160,9 +160,9 @@ static void append_signoff(struct strbuf *sb, const char *signoff) static unsigned int digits_in_number(unsigned int number) { - unsigned int i = 10, result = 1; - while (i <= number) { - i *= 10; + unsigned int result = 1; + while (number > 9) { + number /= 10; result++; } return result; -- 1.6.0.4 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH] fix potential infinite loop given large unsigned integer 2009-08-09 4:41 [PATCH] fix potential infinite loop given large unsigned integer Ryan Flynn @ 2009-08-09 6:19 ` Junio C Hamano 2009-08-09 7:38 ` Junio C Hamano 2009-08-09 23:16 ` Ryan Flynn 0 siblings, 2 replies; 14+ messages in thread From: Junio C Hamano @ 2009-08-09 6:19 UTC (permalink / raw) To: Ryan Flynn; +Cc: git Ryan Flynn <parseerror@gmail.com> writes: > given n, tried to find i greater than n via i=1, iterate i *= 10. > given n sufficiently close to UINT_MAX this will overflow; which can > produce i==0, which results in an infinite loop. iteratively dividing > n /= 10 does not have this problem, and though division is slower than > multiplication this only runs once per `git format-patch > --cover-letter` > > Signed-off-by: pizza <parseerror@gmail.com> Pizza? This is somewhat amusing. - digits_in_number() is called only with opt->total that is "int"; - opt->total is the total number of patches. - the return value is used like this: sprintf(buf, "%0*d", digits_in_number(opt->total), opt->nr); and opt->nr runs from 1 to opt->total; the use of "d" would be already wrong anyway even if you computed digits_in_number() correctly. Perhaps we should get rid of this function altogether? ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] fix potential infinite loop given large unsigned integer 2009-08-09 6:19 ` Junio C Hamano @ 2009-08-09 7:38 ` Junio C Hamano 2009-08-09 12:25 ` Erik Faye-Lund ` (2 more replies) 2009-08-09 23:16 ` Ryan Flynn 1 sibling, 3 replies; 14+ messages in thread From: Junio C Hamano @ 2009-08-09 7:38 UTC (permalink / raw) To: Junio C Hamano; +Cc: Ryan Flynn, git Junio C Hamano <gitster@pobox.com> writes: > Ryan Flynn <parseerror@gmail.com> writes: > >> given n, tried to find i greater than n via i=1, iterate i *= 10. >> given n sufficiently close to UINT_MAX this will overflow; which can >> produce i==0, which results in an infinite loop. iteratively dividing >> n /= 10 does not have this problem, and though division is slower than >> multiplication this only runs once per `git format-patch >> --cover-letter` >> >> Signed-off-by: pizza <parseerror@gmail.com> > > Pizza? > > This is somewhat amusing. > > - digits_in_number() is called only with opt->total that is "int"; > > - opt->total is the total number of patches. > > - the return value is used like this: > > sprintf(buf, "%0*d", digits_in_number(opt->total), opt->nr); > > and opt->nr runs from 1 to opt->total; the use of "d" would be already > wrong anyway even if you computed digits_in_number() correctly. > > Perhaps we should get rid of this function altogether? Or perhaps something stupid like this... builtin-log.c | 6 +++++- log-tree.c | 12 +----------- revision.h | 2 +- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/builtin-log.c b/builtin-log.c index 3817bf1..321e8f5 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -1096,8 +1096,12 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) total = nr; if (!keep_subject && auto_number && total > 1) numbered = 1; - if (numbered) + if (numbered) { + static char num_buf[64]; rev.total = total + start_number - 1; + sprintf(num_buf, "%d", rev.total); + rev.num_width = strlen(num_buf); + } if (in_reply_to || thread || cover_letter) rev.ref_message_ids = xcalloc(1, sizeof(struct string_list)); if (in_reply_to) { diff --git a/log-tree.c b/log-tree.c index 6f73c17..0d32a6c 100644 --- a/log-tree.c +++ b/log-tree.c @@ -158,16 +158,6 @@ static void append_signoff(struct strbuf *sb, const char *signoff) strbuf_addch(sb, '\n'); } -static unsigned int digits_in_number(unsigned int number) -{ - unsigned int i = 10, result = 1; - while (i <= number) { - i *= 10; - result++; - } - return result; -} - static int has_non_ascii(const char *s) { int ch; @@ -212,7 +202,7 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit, snprintf(buffer, sizeof(buffer), "Subject: [%s %0*d/%d] ", opt->subject_prefix, - digits_in_number(opt->total), + opt->num_width, opt->nr, opt->total); subject = buffer; } else if (opt->total == 0 && opt->subject_prefix && *opt->subject_prefix) { diff --git a/revision.h b/revision.h index fb74492..21e4d9d 100644 --- a/revision.h +++ b/revision.h @@ -84,7 +84,7 @@ struct rev_info { unsigned int abbrev; enum cmit_fmt commit_format; struct log_info *loginfo; - int nr, total; + int nr, total, num_width; const char *mime_boundary; const char *patch_suffix; int numbered_files; ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH] fix potential infinite loop given large unsigned integer 2009-08-09 7:38 ` Junio C Hamano @ 2009-08-09 12:25 ` Erik Faye-Lund 2009-08-10 5:24 ` Christian Couder 2009-08-11 0:55 ` Jeff Epler 2009-08-10 0:23 ` Ryan Flynn 2009-08-10 18:19 ` Tony Finch 2 siblings, 2 replies; 14+ messages in thread From: Erik Faye-Lund @ 2009-08-09 12:25 UTC (permalink / raw) To: Junio C Hamano; +Cc: Ryan Flynn, git On Sun, Aug 9, 2009 at 9:38 AM, Junio C Hamano<gitster@pobox.com> wrote: > + static char num_buf[64]; > rev.total = total + start_number - 1; > + sprintf(num_buf, "%d", rev.total); > + rev.num_width = strlen(num_buf); how about rev.num_width = (int)log10((double)rev.total) + 1; hm? log10() appears to be C99, but can be emulated on earlier C-versions by doing #define log10(x) (log(x) / log(10.0)) -- Erik "kusma" Faye-Lund kusmabite@gmail.com (+47) 986 59 656 ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] fix potential infinite loop given large unsigned integer 2009-08-09 12:25 ` Erik Faye-Lund @ 2009-08-10 5:24 ` Christian Couder 2009-08-10 11:12 ` Erik Faye-Lund 2009-08-11 0:55 ` Jeff Epler 1 sibling, 1 reply; 14+ messages in thread From: Christian Couder @ 2009-08-10 5:24 UTC (permalink / raw) To: Erik Faye-Lund; +Cc: Junio C Hamano, Ryan Flynn, git On Sunday 09 August 2009, Erik Faye-Lund wrote: > On Sun, Aug 9, 2009 at 9:38 AM, Junio C Hamano<gitster@pobox.com> wrote: > > + static char num_buf[64]; > > rev.total = total + start_number - 1; > > + sprintf(num_buf, "%d", rev.total); > > + rev.num_width = strlen(num_buf); > > how about > rev.num_width = (int)log10((double)rev.total) + 1; > > hm? > > log10() appears to be C99, but can be emulated on earlier C-versions by > doing #define log10(x) (log(x) / log(10.0)) That would mean linking with -lm? Regards, Christian. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] fix potential infinite loop given large unsigned integer 2009-08-10 5:24 ` Christian Couder @ 2009-08-10 11:12 ` Erik Faye-Lund 2009-08-10 12:24 ` Johannes Schindelin 0 siblings, 1 reply; 14+ messages in thread From: Erik Faye-Lund @ 2009-08-10 11:12 UTC (permalink / raw) To: Christian Couder; +Cc: Junio C Hamano, Ryan Flynn, git On Mon, Aug 10, 2009 at 7:24 AM, Christian Couder<chriscool@tuxfamily.org> wrote: >> log10() appears to be C99, but can be emulated on earlier C-versions by >> doing #define log10(x) (log(x) / log(10.0)) > > That would mean linking with -lm? I guess so. Are we currently trying to avoid linking to the math-parts of libc? -- Erik "kusma" Faye-Lund kusmabite@gmail.com (+47) 986 59 656 ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] fix potential infinite loop given large unsigned integer 2009-08-10 11:12 ` Erik Faye-Lund @ 2009-08-10 12:24 ` Johannes Schindelin 2009-08-10 16:14 ` Ryan Flynn 2009-08-10 16:17 ` Ryan Flynn 0 siblings, 2 replies; 14+ messages in thread From: Johannes Schindelin @ 2009-08-10 12:24 UTC (permalink / raw) To: Erik Faye-Lund; +Cc: Christian Couder, Junio C Hamano, Ryan Flynn, git Hi, On Mon, 10 Aug 2009, Erik Faye-Lund wrote: > On Mon, Aug 10, 2009 at 7:24 AM, Christian > Couder<chriscool@tuxfamily.org> wrote: > >> log10() appears to be C99, but can be emulated on earlier C-versions by > >> doing #define log10(x) (log(x) / log(10.0)) > > > > That would mean linking with -lm? > > I guess so. Are we currently trying to avoid linking to the math-parts > of libc? Yes. I guess we could fix the overflow thing very easily, though: static unsigned int digits_of_number(unsigned int number) { unsigned int result; for (result = 1; number; number /= 10, result++) ; /* do nothing */ return result; } Ciao, Dscho ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] fix potential infinite loop given large unsigned integer 2009-08-10 12:24 ` Johannes Schindelin @ 2009-08-10 16:14 ` Ryan Flynn 2009-08-10 16:17 ` Ryan Flynn 1 sibling, 0 replies; 14+ messages in thread From: Ryan Flynn @ 2009-08-10 16:14 UTC (permalink / raw) To: Johannes Schindelin; +Cc: Erik Faye-Lund, Christian Couder, Junio C Hamano, git On Mon, Aug 10, 2009 at 8:24 AM, Johannes Schindelin<Johannes.Schindelin@gmx.de> wrote: > Hi, > > On Mon, 10 Aug 2009, Erik Faye-Lund wrote: > >> On Mon, Aug 10, 2009 at 7:24 AM, Christian >> Couder<chriscool@tuxfamily.org> wrote: >> >> log10() appears to be C99, but can be emulated on earlier C-versions by >> >> doing #define log10(x) (log(x) / log(10.0)) >> > >> > That would mean linking with -lm? >> >> I guess so. Are we currently trying to avoid linking to the math-parts >> of libc? > > Yes. > > I guess we could fix the overflow thing very easily, though: > > static unsigned int digits_of_number(unsigned int number) { > unsigned int result; > for (result = 1; number; number /= 10, result++) > ; /* do nothing */ > return result; > } > > Ciao, > Dscho > > that is equivalent to the original patch, yes. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] fix potential infinite loop given large unsigned integer 2009-08-10 12:24 ` Johannes Schindelin 2009-08-10 16:14 ` Ryan Flynn @ 2009-08-10 16:17 ` Ryan Flynn 2009-08-10 16:53 ` Johannes Schindelin 1 sibling, 1 reply; 14+ messages in thread From: Ryan Flynn @ 2009-08-10 16:17 UTC (permalink / raw) To: Johannes Schindelin; +Cc: Erik Faye-Lund, Christian Couder, Junio C Hamano, git On Mon, Aug 10, 2009 at 8:24 AM, Johannes Schindelin<Johannes.Schindelin@gmx.de> wrote: > Hi, > > On Mon, 10 Aug 2009, Erik Faye-Lund wrote: > >> On Mon, Aug 10, 2009 at 7:24 AM, Christian >> Couder<chriscool@tuxfamily.org> wrote: >> >> log10() appears to be C99, but can be emulated on earlier C-versions by >> >> doing #define log10(x) (log(x) / log(10.0)) >> > >> > That would mean linking with -lm? >> >> I guess so. Are we currently trying to avoid linking to the math-parts >> of libc? > > Yes. > > I guess we could fix the overflow thing very easily, though: > > static unsigned int digits_of_number(unsigned int number) { > unsigned int result; > for (result = 1; number; number /= 10, result++) > ; /* do nothing */ > return result; > } > > Ciao, > Dscho > > whoops, actually yours: digits_of_number(1) -> 2 ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] fix potential infinite loop given large unsigned integer 2009-08-10 16:17 ` Ryan Flynn @ 2009-08-10 16:53 ` Johannes Schindelin 0 siblings, 0 replies; 14+ messages in thread From: Johannes Schindelin @ 2009-08-10 16:53 UTC (permalink / raw) To: Ryan Flynn; +Cc: Erik Faye-Lund, Christian Couder, Junio C Hamano, git [-- Attachment #1: Type: TEXT/PLAIN, Size: 845 bytes --] Hi, [please cull the quoted text to what you are actually replying to. Thanks] On Mon, 10 Aug 2009, Ryan Flynn wrote: > On Mon, Aug 10, 2009 at 8:24 AM, Johannes > Schindelin<Johannes.Schindelin@gmx.de> wrote: > > > > static unsigned int digits_of_number(unsigned int number) { > > unsigned int result; > > for (result = 1; number; number /= 10, result++) > > ; /* do nothing */ > > return result; > > } > > whoops, actually yours: digits_of_number(1) -> 2 static unsigned int digits(unsigned int number) { unsigned int result; for (result = 1; (number /= 10); result++) ; /* do nothing */ return result; } I'm sorry, I forgot the "something like this" in my mail. This version is actually tested. It has non-optimal runtime, but then, it does not really matter. Ciao, Dscho ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] fix potential infinite loop given large unsigned integer 2009-08-09 12:25 ` Erik Faye-Lund 2009-08-10 5:24 ` Christian Couder @ 2009-08-11 0:55 ` Jeff Epler 1 sibling, 0 replies; 14+ messages in thread From: Jeff Epler @ 2009-08-11 0:55 UTC (permalink / raw) To: Erik Faye-Lund; +Cc: Junio C Hamano, Ryan Flynn, git On Sun, Aug 09, 2009 at 02:25:40PM +0200, Erik Faye-Lund wrote: > log10() appears to be C99, but can be emulated on earlier C-versions by doing > #define log10(x) (log(x) / log(10.0)) I don't think you'll like the results of this very much. #include <math.h> #include <stdio.h> int main(void) { double n=1; int i, j; for(i=0; i<10; i++, n*=10) { j = (int)(log(n)/log(10)); if(i != j) printf("%d %d\n", i, (int)j); } return 0; } (on my system, 3 of the 10 tested cases give the wrong answer due to rounding) For a tour of some of the difficulties of implementing log10, http://www.cs.berkeley.edu/~wkahan/LOG10HAF.TXT Jeff ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] fix potential infinite loop given large unsigned integer 2009-08-09 7:38 ` Junio C Hamano 2009-08-09 12:25 ` Erik Faye-Lund @ 2009-08-10 0:23 ` Ryan Flynn 2009-08-10 18:19 ` Tony Finch 2 siblings, 0 replies; 14+ messages in thread From: Ryan Flynn @ 2009-08-10 0:23 UTC (permalink / raw) To: Junio C Hamano; +Cc: git On Sun, Aug 9, 2009 at 3:38 AM, Junio C Hamano<gitster@pobox.com> wrote: > Junio C Hamano <gitster@pobox.com> writes: > >> Ryan Flynn <parseerror@gmail.com> writes: >> >>> given n, tried to find i greater than n via i=1, iterate i *= 10. >>> given n sufficiently close to UINT_MAX this will overflow; which can >>> produce i==0, which results in an infinite loop. iteratively dividing >>> n /= 10 does not have this problem, and though division is slower than >>> multiplication this only runs once per `git format-patch >>> --cover-letter` >>> >>> Signed-off-by: pizza <parseerror@gmail.com> >> >> Pizza? >> >> This is somewhat amusing. >> >> - digits_in_number() is called only with opt->total that is "int"; >> >> - opt->total is the total number of patches. >> >> - the return value is used like this: >> >> sprintf(buf, "%0*d", digits_in_number(opt->total), opt->nr); >> >> and opt->nr runs from 1 to opt->total; the use of "d" would be already >> wrong anyway even if you computed digits_in_number() correctly. >> >> Perhaps we should get rid of this function altogether? > > Or perhaps something stupid like this... > > builtin-log.c | 6 +++++- > log-tree.c | 12 +----------- > revision.h | 2 +- > 3 files changed, 7 insertions(+), 13 deletions(-) > > diff --git a/builtin-log.c b/builtin-log.c > index 3817bf1..321e8f5 100644 > --- a/builtin-log.c > +++ b/builtin-log.c > @@ -1096,8 +1096,12 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) > total = nr; > if (!keep_subject && auto_number && total > 1) > numbered = 1; > - if (numbered) > + if (numbered) { > + static char num_buf[64]; > rev.total = total + start_number - 1; > + sprintf(num_buf, "%d", rev.total); > + rev.num_width = strlen(num_buf); > + } > if (in_reply_to || thread || cover_letter) > rev.ref_message_ids = xcalloc(1, sizeof(struct string_list)); > if (in_reply_to) { > diff --git a/log-tree.c b/log-tree.c > index 6f73c17..0d32a6c 100644 > --- a/log-tree.c > +++ b/log-tree.c > @@ -158,16 +158,6 @@ static void append_signoff(struct strbuf *sb, const char *signoff) > strbuf_addch(sb, '\n'); > } > > -static unsigned int digits_in_number(unsigned int number) > -{ > - unsigned int i = 10, result = 1; > - while (i <= number) { > - i *= 10; > - result++; > - } > - return result; > -} > - > static int has_non_ascii(const char *s) > { > int ch; > @@ -212,7 +202,7 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit, > snprintf(buffer, sizeof(buffer), > "Subject: [%s %0*d/%d] ", > opt->subject_prefix, > - digits_in_number(opt->total), > + opt->num_width, > opt->nr, opt->total); > subject = buffer; > } else if (opt->total == 0 && opt->subject_prefix && *opt->subject_prefix) { > diff --git a/revision.h b/revision.h > index fb74492..21e4d9d 100644 > --- a/revision.h > +++ b/revision.h > @@ -84,7 +84,7 @@ struct rev_info { > unsigned int abbrev; > enum cmit_fmt commit_format; > struct log_info *loginfo; > - int nr, total; > + int nr, total, num_width; > const char *mime_boundary; > const char *patch_suffix; > int numbered_files; > why carry around a piece of information that is only used in one place and is not expensive to calculate? how about a middle-ground such as: diff --git a/log-tree.c b/log-tree.c index 6f73c17..4888518 100644 --- a/log-tree.c +++ b/log-tree.c @@ -158,14 +158,11 @@ static void append_signoff(struct strbuf *sb, const char *signoff) strbuf_addch(sb, '\n'); } -static unsigned int digits_in_number(unsigned int number) +static int digits_in_number(int number) { - unsigned int i = 10, result = 1; - while (i <= number) { - i *= 10; - result++; - } - return result; + static char num_buf[64]; + sprintf(num_buf, "%u", number); + return (int)strlen(num_buf); } static int has_non_ascii(const char *s) ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH] fix potential infinite loop given large unsigned integer 2009-08-09 7:38 ` Junio C Hamano 2009-08-09 12:25 ` Erik Faye-Lund 2009-08-10 0:23 ` Ryan Flynn @ 2009-08-10 18:19 ` Tony Finch 2 siblings, 0 replies; 14+ messages in thread From: Tony Finch @ 2009-08-10 18:19 UTC (permalink / raw) To: Junio C Hamano; +Cc: Ryan Flynn, git On Sun, 9 Aug 2009, Junio C Hamano wrote: > + if (numbered) { > + static char num_buf[64]; > rev.total = total + start_number - 1; > + sprintf(num_buf, "%d", rev.total); > + rev.num_width = strlen(num_buf); > + } why not if (numbered) { rev.total = total + start_number - 1; rev.num_width = snprintf(NULL, 0, "%d", rev.total); } ? Tony. -- f.anthony.n.finch <dot@dotat.at> http://dotat.at/ GERMAN BIGHT HUMBER: SOUTHWEST 5 TO 7. MODERATE OR ROUGH. SQUALLY SHOWERS. MODERATE OR GOOD. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] fix potential infinite loop given large unsigned integer 2009-08-09 6:19 ` Junio C Hamano 2009-08-09 7:38 ` Junio C Hamano @ 2009-08-09 23:16 ` Ryan Flynn 1 sibling, 0 replies; 14+ messages in thread From: Ryan Flynn @ 2009-08-09 23:16 UTC (permalink / raw) To: Junio C Hamano; +Cc: git > Perhaps we should get rid of this function altogether? I was thinking of something like that, but figured i'd start small and fix the bug first. ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2009-08-11 0:55 UTC | newest] Thread overview: 14+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2009-08-09 4:41 [PATCH] fix potential infinite loop given large unsigned integer Ryan Flynn 2009-08-09 6:19 ` Junio C Hamano 2009-08-09 7:38 ` Junio C Hamano 2009-08-09 12:25 ` Erik Faye-Lund 2009-08-10 5:24 ` Christian Couder 2009-08-10 11:12 ` Erik Faye-Lund 2009-08-10 12:24 ` Johannes Schindelin 2009-08-10 16:14 ` Ryan Flynn 2009-08-10 16:17 ` Ryan Flynn 2009-08-10 16:53 ` Johannes Schindelin 2009-08-11 0:55 ` Jeff Epler 2009-08-10 0:23 ` Ryan Flynn 2009-08-10 18:19 ` Tony Finch 2009-08-09 23:16 ` Ryan Flynn
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).