[Rd] incorrect output and segfaults from sprintf with %*d (PR#13667)

Waclaw.Marcin.Kusnierczyk at idi.ntnu.no Waclaw.Marcin.Kusnierczyk at idi.ntnu.no
Sat Apr 25 19:40:27 CEST 2009

Martin Maechler wrote:
>>>     MM> well, it is basically (+ a few bytes ?)
>>>     MM> the same  8192  limit that *is* documented.
>>> indeed, I was right with that..
>> hmm, i'd guess this limit is valid for all strings included in the
>> output with any format?  not just %s (and, as it appears, undocumentedly
>> %d)?
> yes.

so it's perhaps easiest to change

" There is a limit of 8192 bytes on elements of 'fmt' and also on
     strings included by a '%s' conversion specification."

to sth like

" There is a limit of 8192 bytes on elements of 'fmt' and also on
     strings included in the output by any conversion specification."

it's in fact so easy that even i should be able to do it.

[1 minute later...]  i see you've fixed this one, too.

>> btw. (i do know what that means ;)), after your recent fix:
>>    sprintf('%q%s', 1)
>>    # Error in sprintf("%q%s", 1) :
>>    #  use format %f, %e, %g or %a for numeric objects
>>    sprintf('%s', 1)
>>    # [1] "1"
>> you may want to add '%s' (and '%x', and ...) to the error message.  or
>> perhaps make it say sth like 'invalid format: ...'.  the problem is not
>> that %q is not applicable to numeric, but that it is not a valid format
>> at all.
> yes.  As a matter of fact,  "%q%s" is dealt with as *one* format
> chunk, since "%q" is
> not a valid format.
> The code I have just committed now gives a longer erro message, that
> should be more helpful.

yes, but

    sptinf('%q%s', 1)

still suggests that one uses %{f,e,g,a} for numerics, while %s is pretty
much valid, too.  you see, in c sprintf(buffer, "%s", 1) is destined to
cause a segfault, but in r it works -- so the error message is slightly
misleading, as it suggests %s is *not* valid for numerics.

> Thank you for the suggestion!

yo welcum

>> there's also an issue with the additional arguments supplied after the
>> format:  any superfluous arguments are ignored (this is not documented,
>> as far as i can see),
> I think we should signal an error if there are too many arguments.

agree.  but it might be more complex than it appears:

    sprintf('%3$s', 1, 2, 3)

should *not* complain about too many args, despite just one conversion
spec in the format.  interestingly,

    sprintf('%3$s', , , 3)
    # error: argument is missing, with no default

> Could anyone think of a case where the current behavior is desirable ?

well, one scenario might be that one wants to print a collection of
items with an arbitrary format, supplied by the users, e.g.

    foo = function(fmt) {
       a = ...
       b = ...
       s = sprintf(fmt, a, b, ...)
       ... }

without having to examine the format to establish which values are
needed.  in the current state, sprintf would use those it would need to
use with a particular format, with no undesirable complaints.

>> but they *are* evaluated nevertheless, e.g.:
>>    sprintf('%d', 0, {print(1)})
>>    # "1"
>>    # [1] "0"
>> it might be a good idea to document this behaviour.
> actually I think it should be changed to be more strict (see above).

strict in which sense?  enforce a constraint on the number of arguments
to that needed by a specific format?  or do you mean evaluation of only
those arguments that are needed in a format?  or both?

what about:

    sprintf('%2$s', {print(1)}, 2)
    # too many arguments?
    # should 1 be printed?

    sprintf('%2$s', , 2)
    # too few arguments?
    # missing value?  (yes, sprintf is .Internal, but...)

> Thank you for the constructive feedback!

not much to thank for...  certainly, it's the first time my feedback is
called 'constructive'.  i'm making progress, am i not?

btw., thank you for the fixes.  i appreciate your efforts a lot.


More information about the R-devel mailing list