* 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.
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;
{
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
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;
}
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;
}