Permalink
Browse files

Fix issue where negative integers were being treated incorrectly in s…

…printf. This was causing a bug in ActiveSupport.
  • Loading branch information...
1 parent bad7cd9 commit c5a88c5dd77c701138ec4113f31ca22f44d4ef9d Yehuda Katz committed Dec 13, 2009
Showing with 29 additions and 11 deletions.
  1. +14 −6 kernel/common/sprintf.rb
  2. +15 −5 spec/frozen/core/string/modulo_spec.rb
View
@@ -283,23 +283,31 @@ def pad(val, width, precision, pad_override = nil)
ret = val.to_s
modded_width = width.to_i + (flags[:plus] ? 1 : 0)
width = nil if modded_width <= val.to_s.size
+ sign = plus_char
+
if precision || flags[:zero]
ret.gsub!("..", "")
end
if precision
if precision > PrecisionMax
raise ArgumentError, "precision too big"
end
- ret = plus_char + ret.send(direction, precision, pad_override || "0")
+ ret = sign + ret.send(direction, precision, pad_override || "0")
flags[:zero] = flags[:plus] = flags[:space] = nil
end
if width
- ret = ret.send(direction, width, pad_char)
- ret[0] = plus_char unless plus_char.empty?
- else
- ret = plus_char + ret
+ if pad_char != " " && ret[0] == ?-
+ ret.slice!(0)
+ sign = "-"
+ width -= 1
+ ret = ret.rjust(width, pad_char)
+ else
+ ret = ret.send(direction, width, pad_char)
+ ret[0] = sign unless sign.empty?
+ return ret
+ end
end
- ret
+ sign + ret
end
def pad_char
@@ -336,6 +336,16 @@ def universal.to_f() 0.0 end
("%04#{f}" % 10).should == "0010"
("%*#{f}" % [10, 4]).should == " 4"
end
+
+ it "supports negative integers using #{format}" do
+ ("%#{f}" % -5).should == "-5"
+ ("%3#{f}" % -5).should == " -5"
+ ("%03#{f}" % -5).should == "-05"
+ ("%+03#{f}" % -5).should == "-05"
+ ("%-3#{f}" % -5).should == "-5 "
+ ("%-03#{f}" % -5).should == "-05"
+ ("%+-03#{f}" % -5).should == "-05"
+ end
end
it "supports float formats using %e" do
@@ -417,7 +427,7 @@ def universal.to_f() 0.0 end
("%E" % (-0e0/0)).should == "NAN"
end
end
-
+
# TODO: If http://redmine.ruby-lang.org/issues/show/1566 is confirmed, we
# can guard the behaviour of capitalising Inf and NaN as a bug, and
# removed the compliance guards.
@@ -438,7 +448,7 @@ def universal.to_f() 0.0 end
end
end
end
-
+
ruby_version_is "1.9" do
it "pads with spaces for %E with Inf, -Inf, and NaN" do
("%010E" % -1e1020).should == " -Inf"
@@ -655,7 +665,7 @@ def obj.to_s() "obj" end
("%d" % -(2 ** 64 + 5)).should == "-18446744073709551621"
end
end
-
+
it "supports hex formats using %x for positive numbers" do
("%x" % 10).should == "a"
("% x" % 10).should == " a"
@@ -788,7 +798,7 @@ def obj.to_s() "obj" end
obj.should_receive(:to_int).and_return(6)
(format % obj).should == (format % 6)
end
-
+
# 1.9 raises a TypeError for Kernel.Integer(nil), so we version guard this
# case
ruby_version_is ""..."1.9" do
@@ -797,7 +807,7 @@ def obj.to_s() "obj" end
format = "%" + f
(format % nil).should == (format % Kernel.Integer(nil))
end
- end
+ end
end
it "doesn't taint the result for #{format} when argument is tainted" do

0 comments on commit c5a88c5

Please sign in to comment.