Skip to content
Prev 30536 / 63421 Next

(PR#13283) R crashes on sprintf with bad format specification

The following change recognizes 'S' as a format type (but doesn't
do anything with it) and thus avoids the crash.  

--- sprintf.c   (revision 46944)
+++ sprintf.c   (working copy)
@@ -103,7 +103,7 @@
                else {
                    /* recognise selected types from Table B-1 of K&R */
                    /* This is MBCS-OK, as we are in a format spec */
-                   chunk = strcspn(formatString + cur + 1,
"aAdisfeEgGxX%") + 2;
+                   chunk = strcspn(formatString + cur + 1,
"aAdisSfeEgGxX%") + 2;
                    if (cur + chunk > n)
                        error(_("unrecognised format at end of
string"));

The resulting error messages are not terribly direct, but nicer
than the crash
   > sprintf("A %S %S %S XYZ", 1, 1, 1)
   Error in sprintf("A %S %S %S XYZ", 1, 1, 1) :
     use format %f, %e, %g or %a for numeric objects
   > sprintf("A %S %S %S XYZ", "foo", "bar", "foo")
   Error in sprintf("A %S %S %S XYZ", "foo", "bar", "foo") :
     use format %s for character objects

One could add 'S' to some switch cases below there to have
it convert the corresponding argument to a wide character string
or say directly that %S is not allowed.

This piece of code finds the conversion type by looking for this
first of a bunch of known conversion characters after the %, which
doesn't find lots of illegal formats and causes some surprises.  E.g.,
because 'p' is not in that list we get:
   > sprintf("%p", 3)
   Error in sprintf("%p", 3) : unrecognised format at end of string
   > sprintf("%p is a pointer!", 3)
   [1] "0x3 is a pointer!"
   > sprintf("%p %o", 17L, 17L)
   [1] "0x4 o"