Mailing List Archive

Core dump from sprintf "%9999..."
The implementation of do_sprintf leaves perl open to core dumps from
the common programming error of using $foo or @foo in sprintf format
strings:

sprintf "... $foo ... %d ..."

where, one day, when you least expect it, $foo will contain a %.

Generally it would be not be fatal but if the % happend to be
followed by a large number then you're in core dump city.

Guess what I got bitten by today (well, yesterday now, yawn) :(

Someone here used % as a separator for some numbers and a (very old :)
piece of low-level tracing code of mine using sprintf got caught out.

My Solaris 1 sprintf treats '%9999 ' as an instruction to sprint 9999
spaces into the string. Umm. Curiously perl actually parsed '%9999 d'
and passed that to sprintf. Why does perl allow spaces in the middle of
sprintf specifiers?

In fact _any_ sprintf format (other than the specially handled '%s')
producing more that 1024 characters (sizeof(buf)) will corrupt memory
with unknown effects.

Here's a trivial and very cheap patch which at least tells what's
happened and exits asap instead of letting the corruption persist.

*** ./doop.c.1m Wed Nov 1 06:33:55 1995
--- ./doop.c Wed Nov 1 07:07:52 1995
***************
*** 320,323 ****
--- 320,327 ----
/* end of switch, copy results */
*t = ch;
+ if (xs == buf && xlen >= sizeof(buf)) { /* Ooops! */
+ fputs("panic: sprintf overflow - memory corrupted!\n",stderr);
+ my_exit(1);
+ }
SvGROW(sv, SvCUR(sv) + (f - s) + xlen + 1 + pre + post);
sv_catpvn(sv, s, f - s);

I've got a patch which counts the width and precision digits as they
are scanned but it doesn't seem worth the effort. This is good enough.

I also think it would be worthwhile increasing buf to 2048 chars.
Certainly buf _must_ be greater than PATH_MAX.

Tim.