From: Jarkko Hietaniemi Date: Thu, 18 May 2006 22:44:14 +0000 (+0300) Subject: Re: [PATCH] Re: Change 28183 has broken 64-bit builds? X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=1208b3dd78273b01e1538ddb951ee4e62eb90ebe;p=p5sagit%2Fp5-mst-13.2.git Re: [PATCH] Re: Change 28183 has broken 64-bit builds? Message-ID: <446CCE8E.8010407@gmail.com> p4raw-id: //depot/perl@28234 --- diff --git a/perl.h b/perl.h index aa47dec..5b4dbdd 100644 --- a/perl.h +++ b/perl.h @@ -1458,24 +1458,34 @@ int sockatmark(int); * even with the version that uses the C99 variadic macros. */ -#if defined(HAS_C99_VARIADIC_MACROS) && !(defined(DEBUGGING) && !defined(PERL_USE_GCC_BRACE_GROUPS)) +/* Note that we do not check against snprintf()/vsnprintf() returning + * negative values because that is non-standard behaviour and we use + * snprintf/vsnprintf only iff HAS_VSNPRINTF has been defined, and + * that should be true only if the snprintf()/vsnprintf() are true + * to the standard. */ + +#if defined(HAS_SNPRINTF) && defined(HAS_C99_VARIADIC_MACROS) && !(defined(DEBUGGING) && !defined(PERL_USE_GCC_BRACE_GROUPS)) # ifdef PERL_USE_GCC_BRACE_GROUPS -# define my_snprintf(buffer, len, ...) ({ int __len__ = snprintf(buffer, len, __VA_ARGS__); if (__len__ >= (len)) Perl_croak(aTHX_ "panic: snprintf buffer overflow"); __len__; }) +# define my_snprintf(buffer, len, ...) ({ int __len__ = snprintf(buffer, len, __VA_ARGS__); if ((len) > 0 && __len__ >= (len)) Perl_croak(aTHX_ "panic: snprintf buffer overflow"); __len__; }) +# define PERL_MY_SNPRINTF_GUARDED # else # define my_snprintf(buffer, len, ...) snprintf(buffer, len, __VA_ARGS__) # endif #else # define my_snprintf Perl_my_snprintf +# define PERL_MY_SNPRINTF_GUARDED #endif -#if defined(HAS_C99_VARIADIC_MACROS) +#if defined(HAS_VSNPRINTF) && defined(HAS_C99_VARIADIC_MACROS) && !(defined(DEBUGGING) && !defined(PERL_USE_GCC_BRACE_GROUPS)) # ifdef PERL_USE_GCC_BRACE_GROUPS -# define my_vsnprintf(buffer, len, ...) ({ int __len__ = vsnprintf(buffer, len, __VA_ARGS__); if (__len__ >= (len)) Perl_croak(aTHX_ "panic: vsnprintf buffer overflow"); __len__; }) +# define my_vsnprintf(buffer, len, ...) ({ int __len__ = vsnprintf(buffer, len, __VA_ARGS__); if ((len) > 0 && __len__ >= (len)) Perl_croak(aTHX_ "panic: vsnprintf buffer overflow"); __len__; }) +# define PERL_MY_VSNPRINTF_GUARDED # else # define my_vsnprintf(buffer, len, ...) vsnprintf(buffer, len, __VA_ARGS__) # endif #else # define my_vsnprintf Perl_my_vsnprintf +# define PERL_MY_VSNPRINTF_GUARDED #endif /* Configure gets this right but the UTS compiler gets it wrong. diff --git a/perlio.c b/perlio.c index 9e06ef1..a0cb4a4 100644 --- a/perlio.c +++ b/perlio.c @@ -478,9 +478,9 @@ PerlIO_debug(const char *fmt, ...) const char * const s = CopFILE(PL_curcop); /* Use fixed buffer as sv_catpvf etc. needs SVs */ char buffer[1024]; - const STRLEN len = my_sprintf(buffer, "%.40s:%" IVdf " ", s ? s : "(none)", (IV) CopLINE(PL_curcop)); - const STRLEN len2 = my_vsnprintf(buffer+len, sizeof(buffer) - len, fmt, ap); - PerlLIO_write(PL_perlio_debug_fd, buffer, len + len2); + const STRLEN len1 = my_snprintf(buffer, sizeof(buffer), "%.40s:%" IVdf " ", s ? s : "(none)", (IV) CopLINE(PL_curcop)); + const STRLEN len2 = my_vsnprintf(buffer + len1, sizeof(buffer) - len1, fmt, ap); + PerlLIO_write(PL_perlio_debug_fd, buffer, len1 + len2); #else const char *s = CopFILE(PL_curcop); STRLEN len; @@ -5144,14 +5144,12 @@ PerlIO_vsprintf(char *s, int n, const char *fmt, va_list ap) { dTHX; const int val = my_vsnprintf(s, n > 0 ? n : 0, fmt, ap); - if (n >= 0) { - if (strlen(s) >= (STRLEN) n) { - dTHX; - (void) PerlIO_puts(Perl_error_log, - "panic: sprintf overflow - memory corrupted!\n"); - my_exit(1); - } +#ifndef PERL_MY_VSNPRINTF_GUARDED + if (val < 0 || (n > 0 ? val >= n : 0)) { + dTHX; + Perl_croak("panic: my_vsnprintf overflow in PerlIO_vsprintf\n"); } +#endif return val; } #endif diff --git a/util.c b/util.c index 4e49d19..4abdf73 100644 --- a/util.c +++ b/util.c @@ -5380,7 +5380,8 @@ Perl_my_snprintf(char *buffer, const Size_t len, const char *format, ...) retval = vsprintf(buffer, format, ap); #endif va_end(ap); - if (retval >= len) + /* vsnprintf() shows failure with >= len, vsprintf() with < 0 */ + if (retval < 0 || (len > 0 && retval >= len)) Perl_croak(aTHX_ "panic: my_snprintf buffer overflow"); return retval; } @@ -5416,7 +5417,8 @@ Perl_my_vsnprintf(char *buffer, const Size_t len, const char *format, va_list ap retval = vsprintf(buffer, format, ap); # endif #endif /* #ifdef NEED_VA_COPY */ - if (retval >= len) + /* vsnprintf() shows failure with >= len, vsprintf() with < 0 */ + if (retval < 0 || (len > 0 && retval >= len)) Perl_croak(aTHX_ "panic: my_vsnprintf buffer overflow"); return retval; }