From: Tim Kientzle Date: Sat, 29 Sep 2012 05:55:13 +0000 (-0700) Subject: I'm not entirely happy with Xi Wang's solution to this mess. X-Git-Tag: v3.1.0~42 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ce39cb40953a110eafe6c80b292e545ffa2e7963;p=thirdparty%2Flibarchive.git I'm not entirely happy with Xi Wang's solution to this mess. The cast to (unsigned) feels like we're just exploiting a compiler limitation. The original idea here was to detect overflow and therefore avoid hard-coding assumptions about the platform arithmetic. But allowing compilers to assume that overflow can never happen means that portable C code can never really detect overflow without hackish workarounds. The only practical solution seems to be an arbitrary limit on the size of a string that we can format. --- diff --git a/tar/util.c b/tar/util.c index 4ed2901d5..34b62718b 100644 --- a/tar/util.c +++ b/tar/util.c @@ -120,16 +120,12 @@ safe_fprintf(FILE *f, const char *fmt, ...) fmtbuff_length = length+1; else if (fmtbuff_length < 8192) fmtbuff_length *= 2; + else if (fmtbuff_length < 1000000) + fmtbuff_length += fmtbuff_length / 4; else { - int old_length = fmtbuff_length; - /* Convert to unsigned to avoid signed overflow, - * otherwise the check may be optimized away. */ - fmtbuff_length += (unsigned)fmtbuff_length / 4; - if (old_length > fmtbuff_length) { - length = old_length; - fmtbuff_heap[length-1] = '\0'; - break; - } + length = old_length; + fmtbuff_heap[length-1] = '\0'; + break; } free(fmtbuff_heap); fmtbuff_heap = malloc(fmtbuff_length); @@ -153,8 +149,7 @@ safe_fprintf(FILE *f, const char *fmt, ...) if (mbtowc(NULL, NULL, 1) == -1) { /* Reset the shift state. */ /* NOTE: This case may not happen, but it needs to be compiled * safely without warnings by both gcc on linux and clang. */ - if (fmtbuff_heap != NULL) - free(fmtbuff_heap); + free(fmtbuff_heap); return; }