sprintf: Format specifier tokens aren't checked well enough

4 views
Skip to first unread message

Florian Gross

unread,
Jul 1, 2007, 2:16:33 PM7/1/07
to ruby...@ruby-lang.org
Hi,

all of these format specifiers are currently considered valid by Ruby
1.8 and 1.9:

Star precision before star width:
"%.**d" % [5, 10, 1] # => " 00001"

Precision before flags and width:
"%.5+05d" % 5 # => "+00005"
"%.5 5d" % 5 # => " 00005"

Overriding a star width with a numeric one: (star argument still gets
popped)
"%*1s" % [5, 1] # => "1"

Width before flags:
"%5+0d" % 1 # => "+0001"
"%5 0d" % 1 # => " 0001"

Specifying width multiple times:
"%50+30+20+10+5d" % 5 # => " +5"
"%50 30 20 10 5d" % 5 # => " 5"

I think they should be considered invalid instead. That would avoid
confusion in the case of typos.

Kind regards,
Florian Gross


Florian Gross

unread,
Jul 1, 2007, 2:48:29 PM7/1/07
to ruby...@ruby-lang.org
It's also possible to specify the precision multiple times with
negative star arguments:

"%.*.*.*.*f" % [-1, -1, -1, 5, 1] # => "1.00000"


Florian Gross

unread,
Jul 1, 2007, 3:01:14 PM7/1/07
to ruby...@ruby-lang.org
Null bytes after percent signs are removed:

"%\0x hello" % [] # => "%x hello"

This can be fixed by moving "case '\0':" before "p--" in sprintf.c.


Florian Gross

unread,
Jul 1, 2007, 3:14:39 PM7/1/07
to ruby...@ruby-lang.org
irb(main):001:0> "%.25555555555555555555555555555555555555s" % "hello
world"
[BUG] Segmentation fault
ruby 1.9.0 (2007-06-30) [i686-darwin8.10.1]

Same for 1.8.


Florian Gross

unread,
Jul 1, 2007, 4:20:31 PM7/1/07
to ruby...@ruby-lang.org
Something seems to be broken for %u with negative bignums:

"%u" % -5 # => "..4294967291"
"%.20u" % -5 # => "..........4294967291"
"%+u" % -5 # => "-5"

big = -(2 ** 80 + 5)
"%u" % big # => "-79226953588444722964369244155"
"%.50u" % big # =>
"....................-79226953588444722964369244155"

"%+u" % big # => "-1208925819614629174706181"
big.to_s # => "-1208925819614629174706181"


Nobuyoshi Nakada

unread,
Jul 15, 2007, 11:57:08 PM7/15/07
to ruby...@ruby-lang.org
Hi,

I've fixed other sprintf bugs you had posted, with the tests, but:

At Mon, 2 Jul 2007 05:20:31 +0900,
Florian Gross wrote in [ruby-core:11575]:

I'm not sure if this is broken. Can you explain the results
what you expect?

--
Nobu Nakada

Florian Gross

unread,
Jul 16, 2007, 1:23:11 AM7/16/07
to ruby...@ruby-lang.org
On Jul 16, 5:57 am, Nobuyoshi Nakada <n...@ruby-lang.org> wrote:
> > big = -(2 ** 80 + 5)
> > "%u" % big # => "-79226953588444722964369244155"
> > "%.50u" % big # =>
> > "....................-79226953588444722964369244155"
>
> > "%+u" % big # => "-1208925819614629174706181"
> > big.to_s # => "-1208925819614629174706181"
>
> I'm not sure if this is broken. Can you explain the results
> what you expect?

I'd expect negative bignums to produce results with at least two dots
(no "-"!) and the real bits for "%u" and "%.20u". I'm OK with "%+u"
producing the same as big.to_s.

That way it would match the behaviour of "%u" and fixnums.


Tanaka Akira

unread,
Jul 16, 2007, 3:20:54 AM7/16/07
to ruby...@ruby-lang.org
In article <200707160357....@sharui.nakada.kanuma.tochigi.jp>,
Nobuyoshi Nakada <no...@ruby-lang.org> writes:

> I'm not sure if this is broken. Can you explain the results
> what you expect?

An interesting example:

% ./ruby -ve '(-0xfffffffe).downto(-0x100000001) {|v| printf "%u\n", v }'
ruby 1.9.0 (2007-07-16 patchlevel 0) [i686-linux]
000000000002
000000000001
-e:1: warning: negative number for %u specifier
..18446744069414584320
-e:1: warning: negative number for %u specifier
..18446744069414584319

% ./ruby -ve '(-0xfffffffffffffffe).downto(-0x10000000000000001) {|v| printf "%u\n", v }'
ruby 1.9.0 (2007-07-16 patchlevel 0) [i686-linux]
-e:1: warning: negative number for %u specifier
..00000000000000000002
-e:1: warning: negative number for %u specifier
..00000000000000000001
0079228162495817593519834398720
0079228162495817593519834398719

% ./ruby -ve '(-0xfffffffffffffffffffffffe).downto(-0x1000000000000000000000001) {|v| printf "%u\n", v }'
ruby 1.9.0 (2007-07-16 patchlevel 0) [i686-linux]
0000000000000000000000000000002
0000000000000000000000000000001
00340282366841710300949110269838224261120
00340282366841710300949110269838224261119

It is difficult to define a semantics for %u with negative values.

Some idea:

1. ArgumentError
2. two dots with ten's complement
3. minus sign with absolute value (same as %d)
--
Tanaka Akira

Yukihiro Matsumoto

unread,
Jul 16, 2007, 10:52:54 AM7/16/07
to ruby...@ruby-lang.org
Hi,

In message "Re: sprintf: Format specifier tokens aren't checked well enough"


on Mon, 16 Jul 2007 16:20:54 +0900, Tanaka Akira <a...@fsij.org> writes:

|It is difficult to define a semantics for %u with negative values.
|
|Some idea:
|
|1. ArgumentError
|2. two dots with ten's complement
|3. minus sign with absolute value (same as %d)

After thinking while, I'd rather take No.3.

matz.

Yukihiro Matsumoto

unread,
Jul 16, 2007, 10:52:57 AM7/16/07
to ruby...@ruby-lang.org
Hi,

In message "Re: sprintf: Format specifier tokens aren't checked well enough"

on Mon, 2 Jul 2007 05:20:31 +0900, Florian Gross <flo...@gmail.com> writes:

|Something seems to be broken for %u with negative bignums:

Right.

|"%u" % -5 # => "..4294967291"

Dots do not work well with decimals. Maybe we should either

* prohibit negative number for %u
* or make %u works as an alias to %d (a la Python)

|"%.20u" % -5 # => "..........4294967291"
|"%+u" % -5 # => "-5"

Since %u specifies "unsigned" it should ignore "+" modifier.

|big = -(2 ** 80 + 5)
|"%u" % big # => "-79226953588444722964369244155"
|"%.50u" % big # =>
|"....................-79226953588444722964369244155"

Dots and negative sign should not co-exist. My 1.8.6 gives

".....................79226953588444722964369244155"

which is still wrong though.

matz.

Florian Gross

unread,
Aug 1, 2007, 9:07:35 PM8/1/07
to ruby...@ruby-lang.org
On Jul 16, 5:57 am, Nobuyoshi Nakada <n...@ruby-lang.org> wrote:
> I've fixed other sprintf bugs you had posted, with the tests

Sorry for not discovering this earlier, but there is a small
regression.

In 1.8:
("%*1$.*2$3$d" % [10, 5, 1]) # => " 00001"

(%d with a positional width, precision and value argument.)

In 1.9 it raises ArgumentError: width given twice.


Nobuyoshi Nakada

unread,
Aug 2, 2007, 12:52:21 AM8/2/07
to ruby...@ruby-lang.org
Hi,

At Thu, 2 Aug 2007 10:07:35 +0900,
Florian Gross wrote in [ruby-core:11838]:


> Sorry for not discovering this earlier, but there is a small
> regression.
>
> In 1.8:
> ("%*1$.*2$3$d" % [10, 5, 1]) # => " 00001"
>
> (%d with a positional width, precision and value argument.)
>
> In 1.9 it raises ArgumentError: width given twice.

Thank you, fixed now.

--
Nobu Nakada

Reply all
Reply to author
Forward
0 new messages