summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorJan Dubois <jand@activestate.com>1999-10-15 03:14:23 +0200
committerGurusamy Sarathy <gsar@cpan.org>1999-10-15 01:14:22 +0000
commit25685dc7c95e47b94f62c769e3db898f82b0eb99 (patch)
tree323bf2754b767d494e4db562e9ba7393dc9b6811 /ext
parent62d10b704aa877d24f326d3b46b7eceb38549c98 (diff)
downloadperl-25685dc7c95e47b94f62c769e3db898f82b0eb99.tar.gz
Prevent "Out of memory" error in POSIX's strftime()
Message-ID: <380f61ae.18202914@smtprelay.t-online.de> p4raw-id: //depot/perl@4382
Diffstat (limited to 'ext')
-rw-r--r--ext/POSIX/POSIX.xs25
1 files changed, 16 insertions, 9 deletions
diff --git a/ext/POSIX/POSIX.xs b/ext/POSIX/POSIX.xs
index 23c38b5e20..59adb2eecb 100644
--- a/ext/POSIX/POSIX.xs
+++ b/ext/POSIX/POSIX.xs
@@ -3858,28 +3858,35 @@ strftime(fmt, sec, min, hour, mday, mon, year, wday = -1, yday = -1, isdst = -1)
** If there is a better way to make it portable, go ahead by
** all means.
*/
- if ( ( len > 0 && len < sizeof(tmpbuf) )
- || ( len == 0 && strlen(fmt) == 0 ) ) {
+ if ((len > 0 && len < sizeof(tmpbuf)) || (len == 0 && *fmt == '\0'))
ST(0) = sv_2mortal(newSVpv(tmpbuf, len));
- } else {
+ else {
/* Possibly buf overflowed - try again with a bigger buf */
- int bufsize = strlen(fmt) + sizeof(tmpbuf);
+ int fmtlen = strlen(fmt);
+ int bufsize = fmtlen + sizeof(tmpbuf);
char* buf;
int buflen;
New(0, buf, bufsize, char);
- while( buf ) {
+ while (buf) {
buflen = strftime(buf, bufsize, fmt, &mytm);
- if ( buflen > 0 && buflen < bufsize ) break;
+ if (buflen > 0 && buflen < bufsize)
+ break;
+ /* heuristic to prevent out-of-memory errors */
+ if (bufsize > 100*fmtlen) {
+ Safefree(buf);
+ buf = NULL;
+ break;
+ }
bufsize *= 2;
Renew(buf, bufsize, char);
}
- if ( buf ) {
+ if (buf) {
ST(0) = sv_2mortal(newSVpvn(buf, buflen));
Safefree(buf);
- } else {
- ST(0) = sv_2mortal(newSVpvn(tmpbuf, len));
}
+ else
+ ST(0) = sv_2mortal(newSVpvn(tmpbuf, len));
}
}