summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-09-09 09:16:59 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-09-09 09:16:59 +0000
commit067d9e9ce97dd42b8b13eef10031b0fa9cf23a1f (patch)
tree934f07816670ae9286f399b18f9b8b78c495bc16
parent6c3c48e3d569a40774a14a5bfbebf3fc72874de0 (diff)
sprintf.c: NULL as str
* sprintf.c (ruby_vsnprintf, ruby_snprintf): allow NULL as str, just count the expected buffer size. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59789 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ext/-test-/printf/printf.c8
-rw-r--r--sprintf.c20
-rw-r--r--test/-ext-/test_printf.rb4
3 files changed, 26 insertions, 6 deletions
diff --git a/ext/-test-/printf/printf.c b/ext/-test-/printf/printf.c
index 666f5592e5..e793bb7a48 100644
--- a/ext/-test-/printf/printf.c
+++ b/ext/-test-/printf/printf.c
@@ -90,6 +90,13 @@ printf_test_call(int argc, VALUE *argv, VALUE self)
return rb_assoc_new(result, rb_usascii_str_new_cstr(format));
}
+static VALUE
+snprintf_count(VALUE self, VALUE str)
+{
+ int n = ruby_snprintf(NULL, 0, "%s", StringValueCStr(str));
+ return INT2FIX(n);
+}
+
void
Init_printf(void)
{
@@ -98,4 +105,5 @@ Init_printf(void)
rb_define_singleton_method(m, "v", printf_test_v, 1);
rb_define_singleton_method(m, "q", printf_test_q, 1);
rb_define_singleton_method(m, "call", printf_test_call, -1);
+ rb_define_singleton_method(m, "sncount", snprintf_count, 1);
}
diff --git a/sprintf.c b/sprintf.c
index 4ee7e1d4f0..2bd4966a1b 100644
--- a/sprintf.c
+++ b/sprintf.c
@@ -1261,21 +1261,29 @@ ruby_ultoa(unsigned long val, char *endp, int base, int flags)
return BSD__ultoa(val, endp, base, octzero, xdigs);
}
+static int ruby_do_vsnprintf(char *str, size_t n, const char *fmt, va_list ap);
+
int
ruby_vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
{
+ if (str && (ssize_t)n < 1)
+ return (EOF);
+ return ruby_do_vsnprintf(str, n, fmt, ap);
+}
+
+static int
+ruby_do_vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
+{
int ret;
rb_printf_buffer f;
- if ((int)n < 1)
- return (EOF);
f._flags = __SWR | __SSTR;
f._bf._base = f._p = (unsigned char *)str;
- f._bf._size = f._w = n - 1;
+ f._bf._size = f._w = str ? (n - 1) : 0;
f.vwrite = BSD__sfvwrite;
f.vextra = 0;
ret = (int)BSD_vfprintf(&f, fmt, ap);
- *f._p = 0;
+ if (str) *f._p = 0;
return ret;
}
@@ -1285,11 +1293,11 @@ ruby_snprintf(char *str, size_t n, char const *fmt, ...)
int ret;
va_list ap;
- if ((int)n < 1)
+ if (str && (ssize_t)n < 1)
return (EOF);
va_start(ap, fmt);
- ret = ruby_vsnprintf(str, n, fmt, ap);
+ ret = ruby_do_vsnprintf(str, n, fmt, ap);
va_end(ap);
return ret;
}
diff --git a/test/-ext-/test_printf.rb b/test/-ext-/test_printf.rb
index 4e4f5b4695..cd3ba76364 100644
--- a/test/-ext-/test_printf.rb
+++ b/test/-ext-/test_printf.rb
@@ -184,4 +184,8 @@ class Test_SPrintf < Test::Unit::TestCase
assert_equal(" a", Bug::Printf.("s", "a", width: 3, prec: 3)[0])
assert_equal("a ", Bug::Printf.("s", "a", minus: true, width: 3, prec: 3)[0])
end
+
+ def test_snprintf_count
+ assert_equal(3, Bug::Printf.sncount("foo"))
+ end
end