1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

string.c: multi-byte terminator

* string.c (rb_string_value_cstr): fill minimum length of the encoding
  as the terminator.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@41919 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2013-07-11 11:17:59 +00:00
parent db3ddad3a7
commit b271a8c98d
4 changed files with 48 additions and 5 deletions

View file

@ -1,4 +1,7 @@
Thu Jul 11 20:17:51 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
Thu Jul 11 20:17:57 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
* string.c (rb_string_value_cstr): fill minimum length of the encoding
as the terminator.
* string.c (rb_string_value_cstr): check null char in char, not in
byte.

View file

@ -1,16 +1,22 @@
#include "ruby.h"
#include "ruby/encoding.h"
static VALUE
bug_str_cstr_term(VALUE str)
{
long len;
char *s;
int c;
rb_encoding *enc;
rb_str_modify(str);
len = RSTRING_LEN(str);
RSTRING_PTR(str)[len] = 'x';
s = StringValueCStr(str);
rb_gc();
return INT2NUM(s[len]);
enc = rb_enc_get(str);
c = rb_enc_codepoint(&s[len], &s[len+rb_enc_mbminlen(enc)], enc);
return INT2NUM(c);
}
void

View file

@ -91,6 +91,15 @@ VALUE rb_cSymbol;
}\
} while (0)
#define TERM_LEN(str) rb_enc_mbminlen(rb_enc_get(str))
#define TERM_FILL(ptr, termlen) do {\
char *const term_fill_ptr = (ptr);\
const int term_fill_len = (termlen);\
*term_fill_ptr = '\0';\
if (UNLIKELY(term_fill_len > 1))\
memset(term_fill_ptr, 0, term_fill_len);\
} while (0)
#define RESIZE_CAPA(str,capacity) do {\
if (STR_EMBED_P(str)) {\
if ((capacity) > RSTRING_EMBED_LEN_MAX) {\
@ -1471,6 +1480,25 @@ str_null_char(const char *s, long len, rb_encoding *enc)
return 0;
}
static char *
str_fill_term(VALUE str, char *s, long len, int termlen, rb_encoding *enc)
{
long capa = rb_str_capacity(str) + 1;
int n;
if (capa < len + termlen) {
rb_str_modify_expand(str, len + termlen - capa);
}
else {
const char *e = s + len;
if (!rb_enc_ascget(e, e + termlen, &n, enc)) return s;
rb_str_modify(str);
}
s = RSTRING_PTR(str);
TERM_FILL(s + len, termlen);
return s;
}
char *
rb_string_value_cstr(volatile VALUE *ptr)
{
@ -1484,8 +1512,8 @@ rb_string_value_cstr(volatile VALUE *ptr)
if (str_null_char(s, len, enc)) {
rb_raise(rb_eArgError, "string contains null char");
}
return str_fill_term(str, s, len, minlen, enc);
}
else
if (!s || memchr(s, 0, len)) {
rb_raise(rb_eArgError, "string contains null byte");
}

View file

@ -19,18 +19,24 @@ class Test_StringCStr < Test::Unit::TestCase
def test_wchar_embed
WCHARS.each do |enc|
s = Bug::String.new("ab".encode(enc))
s = Bug::String.new("\u{4022}a".encode(enc))
assert_nothing_raised(ArgumentError) {s.cstr_term}
s.set_len(s.bytesize / 2)
assert_equal(1, s.size)
assert_equal(0, s.cstr_term)
end
end
def test_wchar_long
str = "abcdef"
str = "\u{4022}abcdef"
n = 100
len = str.size * n
WCHARS.each do |enc|
s = Bug::String.new(str.encode(enc))*n
assert_nothing_raised(ArgumentError) {s.cstr_term}
s.set_len(s.bytesize / 2)
assert_equal(len / 2, s.size)
assert_equal(0, s.cstr_term)
end
end
end