ruby-dev (Japanese) list archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-dev:48591] StringValuePtrでnull終止されてない文字列の作り方
@ 2014-10-05 13:22 madoka yamamoto
  2014-10-06 14:02 ` [ruby-dev:48598] StringValuePtrでnull終止されてない文字列の作り方 NARUSE, Yui
  0 siblings, 1 reply; 5+ messages in thread
From: madoka yamamoto @ 2014-10-05 13:22 UTC (permalink / raw
  To: ruby-dev

[-- Attachment #1: Type: text/plain, Size: 848 bytes --]

山本ともうします。

trunkのRubyでPostgreSQL拡張ライブラリを使っていて、null終止されない文字列がPostgreSQL拡張ライブラリに渡っていることに起因するエラーに遭遇しました。
\x1e参考: https://github.com/ged/ruby-pg/pull/5

PostgresSQL拡張ライブラリのソースを見ていると、Rubyから文字列を取り出すのにStringValuePtrが使われており、これが原因だと思われるのですが、どのような経緯を経たことが原因でnull終止されない文字列が生成されるかが解らず、このエラーの再現に苦労しています。

このような、StringValueCStrとStringValuePtrの差異が出るような文字列を作る方法がRubyレベル、もしくは拡張ライブラリレベル\x1cでありますでしょうか?

[-- Attachment #2: Type: text/html, Size: 1022 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [ruby-dev:48598] Re: StringValuePtrでnull終止されてない文字列の作り方
  2014-10-05 13:22 [ruby-dev:48591] StringValuePtrでnull終止されてない文字列の作り方 madoka yamamoto
@ 2014-10-06 14:02 ` NARUSE, Yui
  2014-10-06 14:21   ` [ruby-dev:48599] " SASADA Koichi
  0 siblings, 1 reply; 5+ messages in thread
From: NARUSE, Yui @ 2014-10-06 14:02 UTC (permalink / raw
  To: Ruby developers (Japanese)

まず、CRubyとしてはStringValuePtrがNUL終端する保証はしていませんから、仮にnull-terminateしてないことにより問題が起きるならば、
それはruby-pgのバグです。
とはいえ、Railsアプリがないと再現出来ないようではテストするにもつらいでしょうねぇ。

さて、nul-terminateされていないStringを作る方法ですが、Rubyレベルではありません(ないようにしているはずです)。
拡張ライブラリでは作ることが一応でき、例えば以下のような感じでしょうか。

diff --git a/ext/-test-/string/nulterm.c b/ext/-test-/string/nulterm.c
new file mode 100644
index 0000000..78f5af3
--- /dev/null
+++ b/ext/-test-/string/nulterm.c
@@ -0,0 +1,44 @@
+#include "ruby/ruby.h"
+
+#define STR_NOEMBED      FL_USER1
+#define STR_EMBED_P(str) (!FL_TEST((str), STR_NOEMBED))
+
+#define STR_SET_EMBED_LEN(str, n) do { \
+    long tmp_n = (n);\
+    RBASIC(str)->flags &= ~RSTRING_EMBED_LEN_MASK;\
+    RBASIC(str)->flags |= (tmp_n) << RSTRING_EMBED_LEN_SHIFT;\
+} while (0)
+
+#define STR_SET_LEN(str, n) do { \
+    if (STR_EMBED_P(str)) {\
+ STR_SET_EMBED_LEN((str), (n));\
+    }\
+    else {\
+ RSTRING(str)->as.heap.len = (n);\
+    }\
+} while (0)
+
+/* return coderange without scan */
+static VALUE
+str_chop_without_terminate(VALUE str)
+{
+    STR_SET_LEN(str, RSTRING_LEN(str)-1);
+    return Qnil;
+}
+
+/* scan coderange and return the result */
+static VALUE
+str_null_terminated_p(VALUE str)
+{
+    if ((size_t)RSTRING_LEN(str) == rb_str_capacity(str)) return Qfalse;
+    if (*RSTRING_END(str) != 0) return Qfalse;
+
+    return Qtrue;
+}
+
+void
+Init_nulterm(VALUE klass)
+{
+    rb_define_method(klass, "chop_without_terminate",
str_chop_without_terminate, 0);
+    rb_define_method(klass, "null_terminated?", str_null_terminated_p, 0);
+}
diff --git a/test/-ext-/string/test_nulterm.rb
b/test/-ext-/string/test_nulterm.rb
new file mode 100644
index 0000000..de5f2ba
--- /dev/null
+++ b/test/-ext-/string/test_nulterm.rb
@@ -0,0 +1,13 @@
+# coding: ascii-8bit
+require 'test/unit'
+require "-test-/string/string"
+
+class Test_StringNulterm < Test::Unit::TestCase
+  def test_usascii
+    str = Bug::String.new("foo")
+    assert_equal true, str.null_terminated?
+    str.chop_without_terminate
+    assert_equal "fo", str
+    assert_equal false, str.null_terminated?
+  end
+end

2014年10月5日 22:22 madoka yamamoto <yamamotomadoka@gmail•com>:
> 山本ともうします。
>
> trunkのRubyでPostgreSQL拡張ライブラリを使っていて、null終止されない文字列がPostgreSQL拡張ライブラリに渡っていることに起因するエラーに遭遇しました。
> 参考: https://github.com/ged/ruby-pg/pull/5
>
> PostgresSQL拡張ライブラリのソースを見ていると、Rubyから文字列を取り出すのにStringValuePtrが使われており、これが原因だと思われるのですが、どのような経緯を経たことが原因でnull終止されない文字列が生成されるかが解らず、このエラーの再現に苦労しています。
>
> このような、StringValueCStrとStringValuePtrの差異が出るような文字列を作る方法がRubyレベル、もしくは拡張ライブラリレベル
> でありますでしょうか?
>



-- 
NARUSE, Yui  <naruse@airemix•jp>

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [ruby-dev:48599] Re: StringValuePtrでnull終止されてない文字列の作り方
  2014-10-06 14:02 ` [ruby-dev:48598] StringValuePtrでnull終止されてない文字列の作り方 NARUSE, Yui
@ 2014-10-06 14:21   ` SASADA Koichi
  2014-10-06 15:42     ` [ruby-dev:48601] " NARUSE, Yui
  0 siblings, 1 reply; 5+ messages in thread
From: SASADA Koichi @ 2014-10-06 14:21 UTC (permalink / raw
  To: ruby-dev

On 2014/10/06 23:02, NARUSE, Yui wrote:
> まず、CRubyとしてはStringValuePtrがNUL終端する保証はしていませんから、仮にnull-terminateしてないことにより問題が起きるならば、

 あれ、してないんでしたっけ? RSTRING_PTR() で取れる C 文字列が NULL
終端するために、色々苦労をしていたような。

-- 
// SASADA Koichi at atdot dot net

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [ruby-dev:48601] Re: StringValuePtrでnull終止されてない文字列の作り方
  2014-10-06 14:21   ` [ruby-dev:48599] " SASADA Koichi
@ 2014-10-06 15:42     ` NARUSE, Yui
  2014-10-07  3:02       ` [ruby-dev:48603] " madoka yamamoto
  0 siblings, 1 reply; 5+ messages in thread
From: NARUSE, Yui @ 2014-10-06 15:42 UTC (permalink / raw
  To: Ruby developers (Japanese)

2014年10月6日 23:21 SASADA Koichi <ko1@atdot•net>:
> On 2014/10/06 23:02, NARUSE, Yui wrote:
>> まず、CRubyとしてはStringValuePtrがNUL終端する保証はしていませんから、仮にnull-terminateしてないことにより問題が起きるならば、
>
>  あれ、してないんでしたっけ? RSTRING_PTR() で取れる C 文字列が NULL
> 終端するために、色々苦労をしていたような。

本件のように問題が起きることがしばしばあるので対処はするようにしていますが、
拡張ライブラリに対して保証はしていないはずです。
ご存じの通り、concatや共有の野望もありますし。

-- 
NARUSE, Yui  <naruse@airemix•jp>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [ruby-dev:48603] Re: StringValuePtrでnull終止されてない文字列の作り方
  2014-10-06 15:42     ` [ruby-dev:48601] " NARUSE, Yui
@ 2014-10-07  3:02       ` madoka yamamoto
  0 siblings, 0 replies; 5+ messages in thread
From: madoka yamamoto @ 2014-10-07  3:02 UTC (permalink / raw
  To: Ruby developers (Japanese)

[-- Attachment #1: Type: text/plain, Size: 1401 bytes --]

> さて、nul-terminateされていないStringを作る方法ですが、Rubyレベルではありません(ないようにしているはずです)。
> 拡張ライブラリでは作ることが一応でき、例えば以下のような感じでしょうか。

Rubyレベルでは作れないのですね。そして拡張ライブラリでのコード、私のRuby知識では読み解くのが難しいですが、実際動かして希望の動作をしていることを確認しました。
ありがとうございます。とても助かりました。\x1e

2014年10月7日 0:42 NARUSE, Yui <naruse@airemix•jp>:

> 2014年10月6日 23:21 SASADA Koichi <ko1@atdot•net>:
> > On 2014/10/06 23:02, NARUSE, Yui wrote:
> >>
> まず、CRubyとしてはStringValuePtrがNUL終端する保証はしていませんから、仮にnull-terminateしてないことにより問題が起きるならば、
> >
> > あれ、してないんでしたっけ? RSTRING_PTR() で取れる C 文字列が NULL
> > 終端するために、色々苦労をしていたような。
>
> 本件のように問題が起きることがしばしばあるので対処はするようにしていますが、
> 拡張ライブラリに対して保証はしていないはずです。
> ご存じの通り、concatや共有の野望もありますし。
>
> --
> NARUSE, Yui  <naruse@airemix•jp>
>

[-- Attachment #2: Type: text/html, Size: 2569 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2014-10-07  3:19 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-10-05 13:22 [ruby-dev:48591] StringValuePtrでnull終止されてない文字列の作り方 madoka yamamoto
2014-10-06 14:02 ` [ruby-dev:48598] StringValuePtrでnull終止されてない文字列の作り方 NARUSE, Yui
2014-10-06 14:21   ` [ruby-dev:48599] " SASADA Koichi
2014-10-06 15:42     ` [ruby-dev:48601] " NARUSE, Yui
2014-10-07  3:02       ` [ruby-dev:48603] " madoka yamamoto

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).