From maechler at stat.math.ethz.ch  Wed Apr 22 16:10:25 2009
From: maechler at stat.math.ethz.ch (maechler at stat.math.ethz.ch)
Date: Wed, 22 Apr 2009 16:10:25 +0200 (CEST)
Subject: [Rd] incorrect output and segfaults from sprintf with %*d
	(PR#13667)
Message-ID: <20090422141025.2B02528321B3@mail.pubhealth.ku.dk>

>>>>> "vQ" == Wacek Kusnierczyk <waku at idi.ntnu.no>
>>>>>     on Tue, 21 Apr 2009 13:05:11 +0200 (CEST) writes:

    vQ> Full_Name: Wacek Kusnierczyk
    vQ> Version: 2.10.0 r48365
    vQ> OS: Ubuntu 8.04 Linux 32bit
    vQ> Submission from: (NULL) (129.241.110.141)


    vQ> sprintf has a documented limit on strings included in the output using the
    vQ> format '%s'.  It appears that there is a limit on the length of strings included
    vQ> with, e.g., the format '%d' beyond which surprising things happen (output
    vQ> modified for conciseness):

    vQ> gregexpr('1', sprintf('%9000d', 1))
    vQ> # [1] 9000 9801

    vQ> gregexpr('1', sprintf('%9000d', 1))
    vQ> # [1]  9000  9801 10602

    vQ> gregexpr('1', sprintf('%9000d', 1))
    vQ> # [1]  9000  9801 10602 11403

    vQ> gregexpr('1', sprintf('%9000d', 1))
    vQ> # [1]  9000  9801 10602 11403 12204

    vQ> ...

    vQ> Note that not only more than one '1' is included in the output, but also that
    vQ> the same functional expression (no side effects used beyond the interface) gives
    vQ> different results on each execution.  Analogous behaviour can be observed with
    vQ> '%nd' where n > 8200.

    vQ> The actual output above is consistent across separate sessions.

    vQ> With sufficiently large field width values, R segfaults:

    vQ> sprintf('%*d', 10^5, 1)
    vQ> # *** caught segfault ***
    vQ> # address 0xbfcfc000, cause 'memory not mapped'
    vQ> # Segmentation fault


Thank you, Wacek.
That's all ``interesting''  ... unfortunately, 

my version of  'man 3 sprintf' contains

>> BUGS
>>        Because sprintf() and vsprintf() assume an arbitrarily
>>        long string, callers must be careful not to overflow the
>>        actual space; this is often impossible to assure. Note
>>        that the length of the strings produced is
>>        locale-dependent and difficult to predict.  Use
>>        snprintf() and vsnprintf() instead (or asprintf() and vasprintf).

(note the "impossible" part above)       
and we haven't used  snprintf() yet, probably because it
requires the  C99 C standard, and AFAIK, we have only relatively
recently started to more or less rely on C99 in the R sources.
       
More precisely, I see that some windows-only code relies on
snprintf() being available  whereas in at least on non-Windows
section, I read   /* we cannot assume snprintf here */

Now such platform dependency issues and corresponding configure
settings I do typically leave to other R-corers with a much
wider overview about platforms and their compilers and C libraries.
       

BTW,  
1) sprintf("%n %g", 1,1)   also seg.faults

2) Did you have a true use case where  the  8192  limit was an
   undesirable limit?

Martin       

    vQ> sessionInfo()
    vQ> # R version 2.10.0 Under development (unstable) (2009-04-20 r48365) 
    vQ> # i686-pc-linux-gnu



[Rd] incorrect output and segfaults from sprintf with %*d (PR#13667)
maechler at stat.math.ethz.ch