Change 29984 by [EMAIL PROTECTED] on 2007/01/25 22:41:11
Integrate:
[ 28183]
Subject: Re: [PATCH] my_snprintf
From: Jarkko Hietaniemi <[EMAIL PROTECTED]>
Date: Fri, 12 May 2006 22:28:49 +0300
Message-ID: <[EMAIL PROTECTED]>
[ 28186]
Subject: [PATCH] sv.c: printf %d wants int not size_t
From: Jarkko Hietaniemi <[EMAIL PROTECTED]>
Message-Id: <[EMAIL PROTECTED]>
Date: Sat, 13 May 2006 10:15:32 +0300 (EEST)
[ 28216]
Subject: Re: Change 28183 has broken 64-bit builds?
From: Jarkko Hietaniemi <[EMAIL PROTECTED]>
Date: Wed, 17 May 2006 22:19:51 +0300
Message-ID: <[EMAIL PROTECTED]>
[ 28217]
Parenthesize uses of macro arguments
[ 28222]
Adjust calling of Perl_va_copy(), noticed by Jarkko
[ 28234]
Subject: [PATCH] Re: [PATCH] Re: Change 28183 has broken 64-bit builds?
From: Jarkko Hietaniemi <[EMAIL PROTECTED]>
Date: Thu, 18 May 2006 22:44:14 +0300
Message-ID: <[EMAIL PROTECTED]>
[ 28247]
Perl_croak() needs an aTHX_ in PerlIO_vsprintf().
[ 28249]
Solaris was happy, but change 28247 removed the wrong dTHX as far as
some other operating systems were concerned.
[ 28299]
The 'f' flag was missing for my_snprintf().
Affected files ...
... //depot/maint-5.8/perl/embed.fnc#192 integrate
... //depot/maint-5.8/perl/global.sym#55 integrate
... //depot/maint-5.8/perl/perl.h#138 integrate
... //depot/maint-5.8/perl/perlio.c#93 integrate
... //depot/maint-5.8/perl/pod/perlapi.pod#91 integrate
... //depot/maint-5.8/perl/pp_ctl.c#159 integrate
... //depot/maint-5.8/perl/proto.h#182 integrate
... //depot/maint-5.8/perl/regcomp.c#91 integrate
... //depot/maint-5.8/perl/sv.c#318 integrate
... //depot/maint-5.8/perl/toke.c#149 integrate
... //depot/maint-5.8/perl/universal.c#59 integrate
... //depot/maint-5.8/perl/util.c#130 integrate
Differences ...
==== //depot/maint-5.8/perl/embed.fnc#192 (text) ====
Index: perl/embed.fnc
--- perl/embed.fnc#191~29981~ 2007-01-25 13:31:37.000000000 -0800
+++ perl/embed.fnc 2007-01-25 14:41:11.000000000 -0800
@@ -1657,6 +1657,9 @@
Apnod |int |my_sprintf |NN char *buffer|NN const char *pat|...
#endif
+Apnodf |int |my_snprintf |NN char *buffer|const Size_t len|NN const char
*format|...
+Apnod |int |my_vsnprintf |NN char *buffer|const Size_t len|NN const char
*format|va_list ap
+
END_EXTERN_C
/*
* ex: set ts=8 sts=4 sw=4 noet:
==== //depot/maint-5.8/perl/global.sym#55 (text+w) ====
Index: perl/global.sym
--- perl/global.sym#54~29979~ 2007-01-25 13:01:25.000000000 -0800
+++ perl/global.sym 2007-01-25 14:41:11.000000000 -0800
@@ -737,4 +737,6 @@
Perl_gv_fetchpvn_flags
Perl_gv_fetchsv
Perl_my_sprintf
+Perl_my_snprintf
+Perl_my_vsnprintf
# ex: set ro:
==== //depot/maint-5.8/perl/perl.h#138 (text) ====
Index: perl/perl.h
--- perl/perl.h#137~29964~ 2007-01-24 15:53:28.000000000 -0800
+++ perl/perl.h 2007-01-25 14:41:11.000000000 -0800
@@ -291,11 +291,17 @@
#endif
#if defined(PERL_GCC_PEDANTIC)
-# if !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
+# ifndef PERL_GCC_BRACE_GROUPS_FORBIDDEN
# define PERL_GCC_BRACE_GROUPS_FORBIDDEN
# endif
#endif
+#if defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN) &&
!defined(__cplusplus)
+# ifndef PERL_USE_GCC_BRACE_GROUPS
+# define PERL_USE_GCC_BRACE_GROUPS
+# endif
+#endif
+
/*
* STMT_START { statements; } STMT_END;
* can be used as a single statement, as in
@@ -304,7 +310,7 @@
* Trying to select a version that gives no warnings...
*/
#if !(defined(STMT_START) && defined(STMT_END))
-# if defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN) &&
!defined(__cplusplus)
+# ifdef PERL_USE_GCC_BRACE_GROUPS
# define STMT_START (void)( /* gcc supports "({ STATEMENTS; })" */
# define STMT_END )
# else
@@ -1378,14 +1384,47 @@
*/
#ifdef SPRINTF_RETURNS_STRLEN
# define my_sprintf sprintf
-# ifdef HAS_SNPRINTF
-# define USE_SNPRINTF
+#else
+# define my_sprintf Perl_my_sprintf
+#endif
+
+/*
+ * If we have v?snprintf() and the C99 variadic macros, we can just
+ * use just the v?snprintf(). It is nice to try to trap the buffer
+ * overflow, however, so if we are DEBUGGING, and we cannot use the
+ * gcc brace groups, then use the function wrappers which try to trap
+ * the overflow. If we can use the gcc brace groups, we can try that
+ * even with the version that uses the C99 variadic macros.
+ */
+
+/* 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) > 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
-# ifdef HAS_VSNPRINTF
-# define USE_VSNPRINTF
+#else
+# define my_snprintf Perl_my_snprintf
+# define PERL_MY_SNPRINTF_GUARDED
+#endif
+
+#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) > 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_sprintf Perl_my_sprintf
+# define my_vsnprintf Perl_my_vsnprintf
+# define PERL_MY_VSNPRINTF_GUARDED
#endif
/* Configure gets this right but the UTS compiler gets it wrong.
==== //depot/maint-5.8/perl/perlio.c#93 (text) ====
Index: perl/perlio.c
--- perl/perlio.c#92~29981~ 2007-01-25 13:31:37.000000000 -0800
+++ perl/perlio.c 2007-01-25 14:41:11.000000000 -0800
@@ -477,13 +477,9 @@
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));
-# ifdef USE_VSNPRINTF
- const STRLEN len2 = vsnprintf(buffer+len, sizeof(buffer) - len, fmt,
ap);
-# else
- const STRLEN len2 = vsprintf(buffer+len, fmt, ap);
-# endif /* USE_VSNPRINTF */
- PerlLIO_write(dbg, 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(dbg, buffer, len1 + len2);
#else
const char *s = CopFILE(PL_curcop);
STRLEN len;
@@ -5094,19 +5090,13 @@
int
PerlIO_vsprintf(char *s, int n, const char *fmt, va_list ap)
{
-#ifdef USE_VSNPRINTF
- const int val = vsnprintf(s, n > 0 ? n : 0, fmt, ap);
-#else
- const int val = vsprintf(s, fmt, ap);
-#endif /* #ifdef USE_VSNPRINTF */
- if (n >= 0) {
- if (strlen(s) >= (STRLEN) n) {
- dTHX;
- (void) PerlIO_puts(Perl_error_log,
- "panic: sprintf overflow - memory corrupted!\n");
- my_exit(1);
- }
+ dTHX;
+ const int val = my_vsnprintf(s, n > 0 ? n : 0, fmt, ap);
+#ifndef PERL_MY_VSNPRINTF_GUARDED
+ if (val < 0 || (n > 0 ? val >= n : 0)) {
+ Perl_croak(aTHX_ "panic: my_vsnprintf overflow in PerlIO_vsprintf\n");
}
+#endif
return val;
}
#endif
==== //depot/maint-5.8/perl/pod/perlapi.pod#91 (text+w) ====
Index: perl/pod/perlapi.pod
--- perl/pod/perlapi.pod#90~29968~ 2007-01-25 02:55:13.000000000 -0800
+++ perl/pod/perlapi.pod 2007-01-25 14:41:11.000000000 -0800
@@ -2227,6 +2227,21 @@
=for hackers
Found in file util.c
+=item my_snprintf
+X<my_snprintf>
+
+The C library C<snprintf> functionality, if available and
+standards-compliant (uses C<vsnprintf>, actually). However, if the
+C<vsnprintf> is not available, will unfortunately use the unsafe
+C<vsprintf> which can overrun the buffer (there is an overrun check,
+but that may be too late). Consider using C<sv_vcatpvf> instead, or
+getting C<vsnprintf>.
+
+ int my_snprintf(char *buffer, const Size_t len, const char *format,
...)
+
+=for hackers
+Found in file util.c
+
=item my_sprintf
X<my_sprintf>
@@ -2239,6 +2254,20 @@
=for hackers
Found in file util.c
+=item my_vsnprintf
+X<my_vsnprintf>
+
+The C library C<vsnprintf> if available and standards-compliant.
+However, if if the C<vsnprintf> is not available, will unfortunately
+use the unsafe C<vsprintf> which can overrun the buffer (there is an
+overrun check, but that may be too late). Consider using
+C<sv_vcatpvf> instead, or getting C<vsnprintf>.
+
+ int my_vsnprintf(char *buffer, const Size_t len, const char
*format, va_list ap)
+
+=for hackers
+Found in file util.c
+
=item strEQ
X<strEQ>
==== //depot/maint-5.8/perl/pp_ctl.c#159 (text) ====
Index: perl/pp_ctl.c
--- perl/pp_ctl.c#158~29967~ 2007-01-25 02:34:50.000000000 -0800
+++ perl/pp_ctl.c 2007-01-25 14:41:11.000000000 -0800
@@ -773,11 +773,7 @@
/* Formats aren't yet marked for locales, so assume "yes". */
{
STORE_NUMERIC_STANDARD_SET_LOCAL();
-#ifdef USE_SNPRINTF
- snprintf(t, SvLEN(PL_formtarget) - (t - SvPVX(PL_formtarget)),
fmt, (int) fieldsize, (int) arg & 255, value);
-#else
- sprintf(t, fmt, (int) fieldsize, (int) arg & 255, value);
-#endif /* ifdef USE_SNPRINTF */
+ my_snprintf(t, SvLEN(PL_formtarget) - (t -
SvPVX(PL_formtarget)), fmt, (int) fieldsize, (int) arg & 255, value);
RESTORE_NUMERIC_STANDARD();
}
t += fieldsize;
@@ -2671,13 +2667,8 @@
len = SvCUR(sv);
}
else
-#ifdef USE_SNPRINTF
- len = snprintf(tmpbuf, sizeof(tbuf), "_<(%.10s_eval %lu)", code,
- (unsigned long)++PL_evalseq);
-#else
- len = my_sprintf(tmpbuf, "_<(%.10s_eval %lu)", code,
- (unsigned long)++PL_evalseq);
-#endif /* ifdef USE_SNPRINTF */
+ len = my_snprintf(tmpbuf, sizeof(tbuf), "_<(%.10s_eval %lu)", code,
+ (unsigned long)++PL_evalseq);
SAVECOPFILE_FREE(&PL_compiling);
CopFILE_set(&PL_compiling, tmpbuf+2);
SAVECOPLINE(&PL_compiling);
@@ -3441,11 +3432,7 @@
len = SvCUR(temp_sv);
}
else
-#ifdef USE_SNPRINTF
- len = snprintf(tmpbuf, sizeof(tbuf), "_<(eval %lu)", (unsigned
long)++PL_evalseq);
-#else
- len = my_sprintf(tmpbuf, "_<(eval %lu)", (unsigned long)++PL_evalseq);
-#endif /* ifdef USE_SNPRINTF */
+ len = my_snprintf(tmpbuf, sizeof(tbuf), "_<(eval %lu)", (unsigned
long)++PL_evalseq);
SAVECOPFILE_FREE(&PL_compiling);
CopFILE_set(&PL_compiling, tmpbuf+2);
SAVECOPLINE(&PL_compiling);
==== //depot/maint-5.8/perl/proto.h#182 (text+w) ====
Index: perl/proto.h
--- perl/proto.h#181~29981~ 2007-01-25 13:31:37.000000000 -0800
+++ perl/proto.h 2007-01-25 14:41:11.000000000 -0800
@@ -2311,6 +2311,15 @@
PERL_CALLCONV OP* Perl_ck_require(pTHX_ OP *o)
__attribute__warn_unused_result__;
+PERL_CALLCONV int Perl_my_snprintf(char *buffer, const Size_t len, const
char *format, ...)
+ __attribute__nonnull__(1)
+ __attribute__nonnull__(3);
+
+PERL_CALLCONV int Perl_my_vsnprintf(char *buffer, const Size_t len, const
char *format, va_list ap)
+ __attribute__nonnull__(1)
+ __attribute__nonnull__(3);
+
+
PERL_CALLCONV OP* Perl_ck_return(pTHX_ OP *o)
__attribute__warn_unused_result__;
==== //depot/maint-5.8/perl/regcomp.c#91 (text) ====
Index: perl/regcomp.c
--- perl/regcomp.c#90~29981~ 2007-01-25 13:31:37.000000000 -0800
+++ perl/regcomp.c 2007-01-25 14:41:11.000000000 -0800
@@ -5086,11 +5086,7 @@
for (i = 1; i <= rx->nparens; i++) {
GV *gv;
char digits[TYPE_CHARS(long)];
-#ifdef USE_SNPRINTF
- const STRLEN len = snprintf(digits, sizeof(digits), "%lu",
(long)i);
-#else
- const STRLEN len = my_sprintf(digits, "%lu", (long)i);
-#endif /* #ifdef USE_SNPRINTF */
+ const STRLEN len = my_snprintf(digits, sizeof(digits), "%lu",
(long)i);
GV *const *const gvp
= (GV**)hv_fetch(PL_defstash, digits, len, 0);
==== //depot/maint-5.8/perl/sv.c#318 (text) ====
Index: perl/sv.c
--- perl/sv.c#317~29980~ 2007-01-25 13:15:39.000000000 -0800
+++ perl/sv.c 2007-01-25 14:41:11.000000000 -0800
@@ -1042,8 +1042,9 @@
/* computed count doesnt reflect the 1st slot reservation */
DEBUG_m(PerlIO_printf(Perl_debug_log,
"arena %p end %p arena-size %d type %d size %d ct
%d\n",
- start, end, bdp->arena_size, sv_type, body_size,
- bdp->arena_size / body_size));
+ start, end,
+ (int)bdp->arena_size, sv_type, (int)body_size,
+ (int)bdp->arena_size / (int)body_size));
*root = (void *)start;
@@ -2579,13 +2580,8 @@
if (SvIOKp(sv)) {
len = SvIsUV(sv)
-#ifdef USE_SNPRINTF
- ? snprintf(tbuf, sizeof(tbuf), "%"UVuf, (UV)SvUVX(sv))
- : snprintf(tbuf, sizeof(tbuf), "%"IVdf, (IV)SvIVX(sv));
-#else
- ? my_sprintf(tbuf, "%"UVuf, (UV)SvUVX(sv))
- : my_sprintf(tbuf, "%"IVdf, (IV)SvIVX(sv));
-#endif /* #ifdef USE_SNPRINTF */
+ ? my_snprintf(tbuf, sizeof(tbuf), "%"UVuf, (UV)SvUVX(sv))
+ : my_snprintf(tbuf, sizeof(tbuf), "%"IVdf, (IV)SvIVX(sv));
} else {
Gconvert(SvNVX(sv), NV_DIG, 0, tbuf);
len = strlen(tbuf);
@@ -8686,13 +8682,8 @@
* --jhi */
#if defined(HAS_LONG_DOUBLE)
elen = ((intsize == 'q')
-# ifdef USE_SNPRINTF
- ? snprintf(PL_efloatbuf, PL_efloatsize, ptr, nv)
- : snprintf(PL_efloatbuf, PL_efloatsize, ptr,
(double)nv));
-# else
- ? my_sprintf(PL_efloatbuf, ptr, nv)
- : my_sprintf(PL_efloatbuf, ptr, (double)nv));
-# endif /* #ifdef USE_SNPRINTF */
+ ? my_snprintf(PL_efloatbuf, PL_efloatsize, ptr, nv)
+ : my_snprintf(PL_efloatbuf, PL_efloatsize, ptr,
(double)nv));
#else
elen = my_sprintf(PL_efloatbuf, ptr, nv);
#endif
==== //depot/maint-5.8/perl/toke.c#149 (text) ====
Index: perl/toke.c
--- perl/toke.c#148~29980~ 2007-01-25 13:15:39.000000000 -0800
+++ perl/toke.c 2007-01-25 14:41:11.000000000 -0800
@@ -4983,11 +4983,7 @@
if (!PL_in_my_stash) {
char tmpbuf[1024];
PL_bufptr = s;
-#ifdef USE_SNPRINTF
- snprintf(tmpbuf, sizeof(tmpbuf), "No such class %.1000s",
PL_tokenbuf);
-#else
- sprintf(tmpbuf, "No such class %.1000s", PL_tokenbuf);
-#endif /* #ifdef USE_SNPRINTF */
+ my_snprintf(tmpbuf, sizeof(tmpbuf), "No such class
%.1000s", PL_tokenbuf);
yyerror(tmpbuf);
}
}
==== //depot/maint-5.8/perl/util.c#130 (text) ====
Index: perl/util.c
--- perl/util.c#129~29982~ 2007-01-25 14:04:51.000000000 -0800
+++ perl/util.c 2007-01-25 14:41:11.000000000 -0800
@@ -4790,44 +4790,30 @@
/* We can't use SVs or PerlIO for obvious reasons,
* so we'll use stdio and low-level IO instead. */
char buf[PERL_MEM_LOG_SPRINTF_BUF_SIZE];
-# if defined(PERL_MEM_LOG_TIMESTAMP) && defined(HAS_GETTIMEOFDAY)
+# ifdef PERL_MEM_LOG_TIMESTAMP
struct timeval tv;
+# ifdef HAS_GETTIMEOFDAY
gettimeofday(&tv, 0);
+# endif
+ /* If there are other OS specific ways of hires time than
+ * gettimeofday() (see ext/Time/HiRes), the easiest way is
+ * probably that they would be used to fill in the struct
+ * timeval. */
+# endif
{
const STRLEN len =
-# ifdef USE_SNPRINTF
- snprintf(buf,
- PERL_MEM_LOG_SPRINTF_BUF_SIZE,
- "%10d.%06d: alloc: %s:%d:%s: %"IVdf" %"UVuf
- " %s = %"IVdf": %"UVxf"\n",
- (int)tv.tv_sec, (int)tv.tv_usec,
- filename, linenumber, funcname, n, typesize,
- typename, n * typesize, PTR2UV(newalloc));
-# else
- my_sprintf(buf,
- "%10d.%06d: alloc: %s:%d:%s: %"IVdf" %"UVuf
- " %s = %"IVdf": %"UVxf"\n",
- (int)tv.tv_sec, (int)tv.tv_usec,
- filename, linenumber, funcname, n, typesize,
- typename, n * typesize, PTR2UV(newalloc));
-# endif
-# else
- const STRLEN len =
-# ifdef USE_SNPRINTF
- snprintf(buf,
- PERL_MEM_LOG_SPRINTF_BUF_SIZE,
- "alloc: %s:%d:%s: %"IVdf" %"UVuf
- " %s = %"IVdf": %"UVxf"\n",
- filename, linenumber, funcname, n, typesize,
- typename, n * typesize, PTR2UV(newalloc));
-# else
- my_sprintf(buf,
- "alloc: %s:%d:%s: %"IVdf" %"UVuf
- " %s = %"IVdf": %"UVxf"\n",
- filename, linenumber, funcname, n, typesize,
- typename, n * typesize, PTR2UV(newalloc));
-# endif
+ my_snprintf(buf,
+ PERL_MEM_LOG_SPRINTF_BUF_SIZE,
+# ifdef PERL_MEM_LOG_TIMESTAMP
+ "%10d.%06d: "
# endif
+ "alloc: %s:%d:%s: %"IVdf" %"UVuf
+ " %s = %"IVdf": %"UVxf"\n",
+# ifdef PERL_MEM_LOG_TIMESTAMP
+ (int)tv.tv_sec, (int)tv.tv_usec,
+# endif
+ filename, linenumber, funcname, n, typesize,
+ typename, n * typesize, PTR2UV(newalloc));
# ifdef PERL_MEM_LOG_ENV_FD
s = PerlEnv_getenv("PERL_MEM_LOG_FD");
PerlLIO_write(s ? atoi(s) : PERL_MEM_LOG_FD, buf, len);
@@ -4855,48 +4841,25 @@
/* We can't use SVs or PerlIO for obvious reasons,
* so we'll use stdio and low-level IO instead. */
char buf[PERL_MEM_LOG_SPRINTF_BUF_SIZE];
-# if defined(PERL_MEM_LOG_TIMESTAMP) && defined(HAS_GETTIMEOFDAY)
+# ifdef PERL_MEM_LOG_TIMESTAMP
struct timeval tv;
gettimeofday(&tv, 0);
+# endif
{
const STRLEN len =
-# ifdef USE_SNPRINTF
- snprintf(buf,
- PERL_MEM_LOG_SPRINTF_BUF_SIZE,
- "%10d.%06d: realloc: %s:%d:%s: %"IVdf" %"UVuf
- " %s = %"IVdf": %"UVxf" -> %"UVxf"\n",
- (int)tv.tv_sec, (int)tv.tv_usec,
- filename, linenumber, funcname, n, typesize,
- typename, n * typesize, PTR2UV(oldalloc),
- PTR2UV(newalloc));
-# else
- my_sprintf(buf,
- "%10d.%06d: realloc: %s:%d:%s: %"IVdf" %"UVuf
- " %s = %"IVdf": %"UVxf" -> %"UVxf"\n",
- (int)tv.tv_sec, (int)tv.tv_usec,
- filename, linenumber, funcname, n, typesize,
- typename, n * typesize, PTR2UV(oldalloc),
- PTR2UV(newalloc));
-# endif
-# else
- const STRLEN len =
-# ifdef USE_SNPRINTF
- snprintf(buf,
- PERL_MEM_LOG_SPRINTF_BUF_SIZE,
- "realloc: %s:%d:%s: %"IVdf" %"UVuf
- " %s = %"IVdf": %"UVxf" -> %"UVxf"\n",
- filename, linenumber, funcname, n, typesize,
- typename, n * typesize, PTR2UV(oldalloc),
- PTR2UV(newalloc));
-# else
- my_sprintf(buf,
- "realloc: %s:%d:%s: %"IVdf" %"UVuf
- " %s = %"IVdf": %"UVxf" -> %"UVxf"\n",
- filename, linenumber, funcname, n, typesize,
- typename, n * typesize, PTR2UV(oldalloc),
- PTR2UV(newalloc));
-# endif
+ my_snprintf(buf,
+ PERL_MEM_LOG_SPRINTF_BUF_SIZE,
+# ifdef PERL_MEM_LOG_TIMESTAMP
+ "%10d.%06d: "
# endif
+ "realloc: %s:%d:%s: %"IVdf" %"UVuf
+ " %s = %"IVdf": %"UVxf" -> %"UVxf"\n",
+# ifdef PERL_MEM_LOG_TIMESTAMP
+ (int)tv.tv_sec, (int)tv.tv_usec,
+# endif
+ filename, linenumber, funcname, n, typesize,
+ typename, n * typesize, PTR2UV(oldalloc),
+ PTR2UV(newalloc));
# ifdef PERL_MEM_LOG_ENV_FD
s = PerlEnv_getenv("PERL_MEM_LOG_FD");
PerlLIO_write(s ? atoi(s) : PERL_MEM_LOG_FD, buf, len);
@@ -4924,32 +4887,23 @@
/* We can't use SVs or PerlIO for obvious reasons,
* so we'll use stdio and low-level IO instead. */
char buf[PERL_MEM_LOG_SPRINTF_BUF_SIZE];
-# if defined(PERL_MEM_LOG_TIMESTAMP) && defined(HAS_GETTIMEOFDAY)
+# ifdef PERL_MEM_LOG_TIMESTAMP
struct timeval tv;
gettimeofday(&tv, 0);
+# endif
{
const STRLEN len =
-# ifdef USE_SNPRINTF
- snprintf(buf,
- PERL_MEM_LOG_SPRINTF_BUF_SIZE,
- "%10d.%06d: free: %s:%d:%s: %"UVxf"\n",
- (int)tv.tv_sec, (int)tv.tv_usec,
- filename, linenumber, funcname,
- PTR2UV(oldalloc));
-# else
- my_sprintf(buf,
- "%10d.%06d: free: %s:%d:%s: %"UVxf"\n",
- (int)tv.tv_sec, (int)tv.tv_usec,
- filename, linenumber, funcname,
- PTR2UV(oldalloc));
-# endif
-# else
- const STRLEN len =
- my_sprintf(buf,
- "free: %s:%d:%s: %"UVxf"\n",
- filename, linenumber, funcname,
- PTR2UV(oldalloc));
+ my_snprintf(buf,
+ PERL_MEM_LOG_SPRINTF_BUF_SIZE,
+# ifdef PERL_MEM_LOG_TIMESTAMP
+ "%10d.%06d: "
+# endif
+ "free: %s:%d:%s: %"UVxf"\n",
+# ifdef PERL_MEM_LOG_TIMESTAMP
+ (int)tv.tv_sec, (int)tv.tv_usec,
# endif
+ filename, linenumber, funcname,
+ PTR2UV(oldalloc));
# ifdef PERL_MEM_LOG_ENV_FD
s = PerlEnv_getenv("PERL_MEM_LOG_FD");
PerlLIO_write(s ? atoi(s) : PERL_MEM_LOG_FD, buf, len);
@@ -4985,6 +4939,74 @@
}
#endif
+/*
+=for apidoc my_snprintf
+
+The C library C<snprintf> functionality, if available and
+standards-compliant (uses C<vsnprintf>, actually). However, if the
+C<vsnprintf> is not available, will unfortunately use the unsafe
+C<vsprintf> which can overrun the buffer (there is an overrun check,
+but that may be too late). Consider using C<sv_vcatpvf> instead, or
+getting C<vsnprintf>.
+
+=cut
+*/
+int
+Perl_my_snprintf(char *buffer, const Size_t len, const char *format, ...)
+{
+ dTHX;
+ int retval;
+ va_list ap;
+ va_start(ap, format);
+#ifdef HAS_VSNPRINTF
+ retval = vsnprintf(buffer, len, format, ap);
+#else
+ retval = vsprintf(buffer, format, ap);
+#endif
+ va_end(ap);
+ /* 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;
+}
+
+/*
+=for apidoc my_vsnprintf
+
+The C library C<vsnprintf> if available and standards-compliant.
+However, if if the C<vsnprintf> is not available, will unfortunately
+use the unsafe C<vsprintf> which can overrun the buffer (there is an
+overrun check, but that may be too late). Consider using
+C<sv_vcatpvf> instead, or getting C<vsnprintf>.
+
+=cut
+*/
+int
+Perl_my_vsnprintf(char *buffer, const Size_t len, const char *format, va_list
ap)
+{
+ dTHX;
+ int retval;
+#ifdef NEED_VA_COPY
+ va_list apc;
+ Perl_va_copy(ap, apc);
+# ifdef HAS_VSNPRINTF
+ retval = vsnprintf(buffer, len, format, apc);
+# else
+ retval = vsprintf(buffer, format, apc);
+# endif
+#else
+# ifdef HAS_VSNPRINTF
+ retval = vsnprintf(buffer, len, format, ap);
+# else
+ retval = vsprintf(buffer, format, ap);
+# endif
+#endif /* #ifdef NEED_VA_COPY */
+ /* 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;
+}
+
void
Perl_my_clearenv(pTHX)
{
End of Patch.