[ruby-dev:36750] [Bug #650] Marshal.load raises RegexpError

View: New views
10 Messages — Rating Filter:   Alert me  
< Prev | 1 - 2 | Next >

[ruby-dev:36865] Re: [Bug #650] Marshal.load raises RegexpError

by Urabe Shyouhei-4 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

卜部です。

石塚圭樹 さんは書きました:

> 例えば, 配列の一要素が復元できなかった場合など, 複数のオブジェクトを再
> 生したとき,
>
>  
>>>   obj = Marshal.load src, invalid: :replace
>>>   obj == Marshal::Invalid and raise "invalid data"
>>>      
>
> このやり方では, 実際にどのオブジェクトの再生に失敗したのか調べるのが難
> しいと思います. まず例外を発生させて, 再生できなかったことを明示的に知
> らせて, ではどこがおかしいのかな? って中身を調べられる方がよいのでは?
>  

いや、まず例外が起きるなら現状と何ら変わりませんがな。

失敗したやつはともかくとして、それ以外の部分データを救いたいのが動機です。
# つまりそのサンプルコードはちょっといけてない

> あと, この方法だと, オプションの指定も必要ないような気がします. 常にマー
> カーに置き換えちゃえば良いので.
>  

例外のほうがうれしい局面ってあるんでしょうかね。
invalid: :replaceはもちろんString#encodeから引っ張ってきたアイディアです
けど、String#encodeではなんでデフォルトが例外なんでしょうか。


[ruby-dev:36870] Re: [Bug #650] Marshal.load raises RegexpError

by Keiju ISHITSUKA :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

けいじゅ@いしつかです.

In [ruby-dev :36865 ] the message: "[ruby-dev:36865] Re: [Bug #650]
Marshal.load raises RegexpError ", on Oct/22 20:31(JST) Urabe Shyouhei
writes:

>卜部です。

>いや、まず例外が起きるなら現状と何ら変わりませんがな。

パラメータを指定するなら, 例外の捕捉を書いてもあまり変わらないと思いま
す.

>失敗したやつはともかくとして、それ以外の部分データを救いたいのが動機
>です。

そうすると, 1.8で作成したデータを1.9で使えるようにコンバートしたいって
用途だと考えてよいでしょうか?

文字列と違って, 相手はオブジェクトなので, 再生を失敗したオブジェクトも
それなりのものに再変換する必要があると思います.

また, 例えば, PStoreに入っているオブジェクト群を変換することを考えると,
ほとんどのものは正常に再生できることが多いと思いますので, 変換に失敗し
たものだけが例外になってもらった方がコンバートもしやすいです.

あと, 気になっているのが,

  [1, 2, 3, <再生不能オブジェクト>]

が dump されていたとして, これをloadすると 何が帰ってくるのでしょう?
私は, まず例外を発生させて,

  [1, 2, 4, markerオブジェクト]

になるのかな? と考えていました. 例外を捕捉してから, オブジェクト内をス
キャンしていくイメージです. 卜部さんの案はどのように返ってくるのでしょ
う?

ただ, スキャンするといっても, 任意のオブジェクトのツリーのスキャンを一
般のユーザにやってもらうののは難しい気がしてきました. で, こんなのはいか
がでしょう?

obj = Marshal.load(src, invalid: proc{|invalid_info| ...})

再生不能オブジェクトに当たったら, 指定したprocを呼び出し, それなりのオ
ブジェクトを返してもらって, それをloadの返り値にアサインするというもの
です. これだったら, 複雑なネットワーク状になったオブジェクト群をloadし
た場合でも, それなりに対応できそうです.

>例外のほうがうれしい局面ってあるんでしょうかね。

converter的な使い方をするのであれば, 例外である必要はない気がします.

>invalid: :replaceはもちろんString#encodeから引っ張ってきたアイディアです
>けど、

そうだったんですか...
bladeで調べたんですけど, 探し方が悪いのか本質的な議論は見つかりません
でした. 他で議論されたものです?

__
---------------------------------------------------->> 石塚 圭樹 <<---
---------------------------------->> e-mail: keiju@... <<---


[ruby-dev:36871] Re: [Bug #650] Marshal.load raises RegexpError

by Urabe Shyouhei-4 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

卜部です。

ちょと混乱してきました。石塚さんがおっしゃっておられる「例外」ってのはな
んなんでしょう。
私の中ではRubyのException(つまりrb_raise()でトリガするあれ)のつもりだっ
たので、例外を発生させたところで処理が中断する前提でお話をしていたのです
が、「変換に失敗したものだけが例外になってもらった方が」のくだりで指して
おられる「例外」は、どうもそれとは違うようで。


石塚圭樹 さんは書きました:

>> いや、まず例外が起きるなら現状と何ら変わりませんがな。
>>    
>
> パラメータを指定するなら, 例外の捕捉を書いてもあまり変わらないと思いま
> す.
>
>  
>> 失敗したやつはともかくとして、それ以外の部分データを救いたいのが動機
>> です。
>>    
>
> そうすると, 1.8で作成したデータを1.9で使えるようにコンバートしたいって
> 用途だと考えてよいでしょうか?
>
> 文字列と違って, 相手はオブジェクトなので, 再生を失敗したオブジェクトも
> それなりのものに再変換する必要があると思います.
>
> また, 例えば, PStoreに入っているオブジェクト群を変換することを考えると,
> ほとんどのものは正常に再生できることが多いと思いますので, 変換に失敗し
> たものだけが例外になってもらった方がコンバートもしやすいです.
>
> あと, 気になっているのが,
>
>   [1, 2, 3, <再生不能オブジェクト>]
>
> が dump されていたとして, これをloadすると 何が帰ってくるのでしょう?
> 私は, まず例外を発生させて,
>
>   [1, 2, 4, markerオブジェクト]
>
> になるのかな? と考えていました. 例外を捕捉してから, オブジェクト内をス
> キャンしていくイメージです. 卜部さんの案はどのように返ってくるのでしょ
> う?
>
> ただ, スキャンするといっても, 任意のオブジェクトのツリーのスキャンを一
> 般のユーザにやってもらうのは難しい気がしてきました. で, こんなのはいか
> がでしょう?
>
> obj = Marshal.load(src, invalid: proc{|invalid_info| ...})
>
> 再生不能オブジェクトに当たったら, 指定したprocを呼び出し, それなりのオ
> ブジェクトを返してもらって, それをloadの返り値にアサインするというもの
> です. これだったら, 複雑なネットワーク状になったオブジェクト群をloadし
> た場合でも, それなりに対応できそうです.
>
>  
>> 例外のほうがうれしい局面ってあるんでしょうかね。
>>    
>
> converter的な使い方をするのであれば, 例外である必要はない気がします.
>
>  
>> invalid: :replaceはもちろんString#encodeから引っ張ってきたアイディアです
>> けど、
>>    
>
> そうだったんですか...
> bladeで調べたんですけど, 探し方が悪いのか本質的な議論は見つかりません
> でした. 他で議論されたものです?
>
> __
> ---------------------------------------------------->> 石塚 圭樹 <<---
> ---------------------------------->> e-mail: keiju@... <<---
>  


[ruby-dev:36872] Re: [Bug #650] Marshal.load raises RegexpError

by Keiju ISHITSUKA :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

けいじゅ@いしつかです.

In [ruby-dev :36871 ] the message: "[ruby-dev:36871] Re: [Bug #650]
Marshal.load raises RegexpError ", on Oct/23 02:07(JST) Urabe Shyouhei
writes:

>卜部です。
>
>ちょと混乱してきました。石塚さんがおっしゃっておられる「例外」ってのはな
>んなんでしょう。
>私の中ではRubyのException(つまりrb_raise()でトリガするあれ)のつもりだっ
>たので、例外を発生させたところで処理が中断する前提でお話をしていたのです
>が、「変換に失敗したものだけが例外になってもらった方が」のくだりで指して
>おられる「例外」は、どうもそれとは違うようで。

確かに説明不足でした.

例外オブジェクトのアクセサで取りあえずの変換結果が取り出せるイメージで
した.

入力が:

  [1, 2, 3, <再生不能オブジェクト>, 5]

だったら, 例外から取り出せるのは

  [1, 2, 4, <markerオブジェクト>, 5]

という感じです. ここから, markerオブジェクトを探して, 適当に処理するイ
メージでした.

ただ, 今は, 前メイルの理由より, API的には

  obj = Marshal.load(src, invalid: proc{|invalid_info| ...})

の方がふさわしいと感じています.

さらに, invalid_info は適当な(適当な情報を持った)例外がいいんじゃない
かと思っています. つまり, invalid: が指定されなかったとき発生するもの
と同じ例外です. procでは, 個々のオブジェクトの再生が失敗したという例外
を引数として受け取ってそれなりに処理する感じです.

この問題は, 松本さんの[ruby-dev:36784]にあった:

> Marshalファイルフォーマットには、メジャーバージョンとマイナー
> バージョンの情報が付加されており、マイナーバージョンの違いは
> 「上位互換性がある」ので「古いmarshal formatのデータを読もう
> とすると、警告が出るが処理自体はできる」、メジャーバージョン
> の違いは「互換性はないので古いデータは読めない」とする仕組み
> があります。

でのメジャーバージョンを越えるための方法を考えることであり, 結構重要な
問題だと思っています. 卜部さんもその辺りを気にしているのではと感じてい
ます. Rubyも今となっては, メジャーバージョンが変わったので互換性がない
からあきらめてね, とはいえない状態だと考えています.

__
---------------------------------------------------->> 石塚 圭樹 <<---
---------------------------------->> e-mail: keiju@... <<---


[ruby-dev:36873] Re: [Bug #650] Marshal.load raises RegexpError

by Masatoshi SEKI :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

咳といいます。

On 2008/10/23, at 3:26, 石塚圭樹 wrote:

>
>
>> Marshalファイルフォーマットには、メジャーバージョンとマイナー
>> バージョンの情報が付加されており、マイナーバージョンの違いは
>> 「上位互換性がある」ので「古いmarshal formatのデータ
>> を読もう
>> とすると、警告が出るが処理自体はできる」、メジャーバージョン
>> の違いは「互換性はないので古いデータは読めない」とする仕組み
>> があります。
>
> でのメジャーバージョンを越えるための方法を考えることであ
> り, 結構重要な
> 問題だと思っています. 卜部さんもその辺りを気にしてい
> るのではと感じてい
> ます. Rubyも今となっては, メジャーバージョンが
> 変わったので互換性がない
> からあきらめてね, とはいえない状態だと考えています.

各メジャーバージョンのコンバータをRubyスクリプトの
ライブラリとして提供したらどうでしょうか。

前にRubyスクリプトでMarshalフォーマットを読み込み、
田中さんのAMarshalをパクってオブジェクトを復元する
練習をしたことがありますが、たぶん実現可能な気がします。

Marshal.loadが古いデータを読もうとしたときにあげる例外に、
メジャーバージョンの情報などをつけてくれると少し楽になるのかしら。





[ruby-dev:36882] Re: [Bug #650] Marshal.load raises RegexpError

by Yukihiro Matsumoto :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

まつもと ゆきひろです

In message "Re: [ruby-dev:36872] Re: [Bug #650] Marshal.load raises RegexpError"
    on Thu, 23 Oct 2008 03:26:00 +0900, keiju@... (石塚圭樹) writes:

|例外オブジェクトのアクセサで取りあえずの変換結果が取り出せるイメージで
|した.

例外は実行を中断しちゃうんで、「とりあえずの変換結果」ではか
なり情報が失われるような気がします。

|入力が:
|
|  [1, 2, 3, <再生不能オブジェクト>, 5]
|
|だったら, 例外から取り出せるのは
|
|  [1, 2, 4, <markerオブジェクト>, 5]
|
|という感じです. ここから, markerオブジェクトを探して, 適当に処理するイ
|メージでした.

この例だと「5の再生に届かない」って感じでしょうか。
5を復元するためには例外が発生した情報だけはとっておいてとり
あえず最後まで復元して、改めて例外を発生し直すとかいうことに
なりそうですが、複数の例外が発生したらどうするかとか悩ましい
限りです。

|ただ, 今は, 前メイルの理由より, API的には
|
|  obj = Marshal.load(src, invalid: proc{|invalid_info| ...})
|
|の方がふさわしいと感じています.

こちらならcallbackとして呼ばれますから、複数の例外などの問題
はありませんね。

|さらに, invalid_info は適当な(適当な情報を持った)例外がいいんじゃない
|かと思っています. つまり, invalid: が指定されなかったとき発生するもの
|と同じ例外です. procでは, 個々のオブジェクトの再生が失敗したという例外
|を引数として受け取ってそれなりに処理する感じです.

例外が良いかもしれないことを頭から否定するわけではありません
が、たとえばmarshal_loadメソッドから発生した例外とかは事前に
予測困難ですから、統一的な対応はなかなか難しいかもしれません。

|この問題は, 松本さんの[ruby-dev:36784]にあった:
|
|> Marshalファイルフォーマットには、メジャーバージョンとマイナー
|> バージョンの情報が付加されており、マイナーバージョンの違いは
|> 「上位互換性がある」ので「古いmarshal formatのデータを読もう
|> とすると、警告が出るが処理自体はできる」、メジャーバージョン
|> の違いは「互換性はないので古いデータは読めない」とする仕組み
|> があります。
|
|でのメジャーバージョンを越えるための方法を考えることであり, 結構重要な
|問題だと思っています. 卜部さんもその辺りを気にしているのではと感じてい
|ます. Rubyも今となっては, メジャーバージョンが変わったので互換性がない
|からあきらめてね, とはいえない状態だと考えています.

まあ、そうなんですが、今さらメジャーバージョンが変わることは
ないと思います。とりあえず不足はないと思うし。

気になっている点は

  * ユーザ定義の_load,_dump,marshal_dump,marshal_loadが変化
    したらどうするのか
  * markerとなるオブジェクトはどんなオブジェクトでどんな属性
    を持つのか
  * callbackにするのか、markerを埋め込んだオブジェクトを返す
    のか

などがあります。

                                まつもと ゆきひろ /:|)


[ruby-dev:36884] Re: [Bug #650] Marshal.load raises RegexpError

by Keiju ISHITSUKA :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

けいじゅ@いしつかです.

In [ruby-dev :36882 ] the message: "[ruby-dev:36882] Re: [Bug #650]
Marshal.load raises RegexpError ", on Oct/23 17:39(JST) Yukihiro
Matsumoto writes:

>まつもと ゆきひろです
>
>例外は実行を中断しちゃうんで、「とりあえずの変換結果」ではか
>なり情報が失われるような気がします。

えー.

>|  [1, 2, 3, <再生不能オブジェクト>, 5]
>|  [1, 2, 4, <markerオブジェクト>, 5]
>
>この例だと「5の再生に届かない」って感じでしょうか。
>5を復元するためには例外が発生した情報だけはとっておいてとり
>あえず最後まで復元して、改めて例外を発生し直すとかいうことに
>なりそうですが、複数の例外が発生したらどうするかとか悩ましい
>限りです。

後者のイメージでした. 確に複数の例外の問題はありますね. <marker>に情報
を埋め込めばどうにかなるとは思いますが.
とはいえ, こちらの案はもう良いです.


>|  obj = Marshal.load(src, invalid: proc{|invalid_info| ...})
>
>こちらならcallbackとして呼ばれますから、複数の例外などの問題
>はありませんね。

そうでもなくて, 1オブジェクトで2種類の例外はなくはないんですよね. 今回
の問題はRegexpの問題でしたが, また, 同じクラスで別の問題が発生する可能
性がなくもないです.

>例外が良いかもしれないことを頭から否定するわけではありません
>が、たとえばmarshal_loadメソッドから発生した例外とかは事前に
>予測困難ですから、統一的な対応はなかなか難しいかもしれません。

converterを作るって話であれば, 統一的な対応でなくても良い気がします.
というか, 将来どういう非互換が発生するかは読めないですからね.

>まあ、そうなんですが、今さらメジャーバージョンが変わることは
>ないと思います。とりあえず不足はないと思うし。

変えたくないって話なんですよね? でも, storeしたものが(何も対処しないで)
load出来ないってことは, 事実上メジャーバージョンが変わっていると思いま
すが?

>  * ユーザ定義の_load,_dump,marshal_dump,marshal_loadが変化
>    したらどうするのか

いろいろな変更があると思いますが, ユーザ定義でも互換性を維持して行うの
が当然ですので, 互換性を維持できない場合ですよね.

marshal_load で invalidが指定されているときは, marshal_loadもinvalidを
指定して呼び出し, コールバックするなりmakerを生成するなりすれば良いの
では?

>  * markerとなるオブジェクトはどんなオブジェクトでどんな属性
>    を持つのか

これが問題ですよねぇ. 最低でもダンプしたイメージは欲しいと思いますが,
あとは, 推選の変換オブジェクトがあればそういうのもあると良い気がします.

marshal_load(obj)の場合は, objを渡すと良いですね. 一般的にもこういうの
があるといいんですが, あ, 問題が発生したときに考えれば良いのかな? 今回
はRegexp なので, Regexp.new(string, option, code)のstring, option,
codeを渡せばほとんど再生できます.

あとは, 何の非互換性かを識別するIDなり例外クラスが欲しいですよね.

今回の例をコールバックの例で考えると

  proc do |exp|
    case exp
    when MarshalInvalid_Regex_backslash_u
      newstr = exp.string.gsub("\\u", "u")
      Regex.new(newstr, exp.option, exp.code)
    :

みたいなかんじでしょうか.    

>  * callbackにするのか、markerを埋め込んだオブジェクトを返す
>    のか

これは, 後者の方が良いと思いますねぇ. maker埋め込みはあとで, スキャン
するのがたいへんそうです. 無限ループしたりね...

__
---------------------------------------------------->> 石塚 圭樹 <<---
---------------------------------->> e-mail: keiju@... <<---


[ruby-dev:37377] [Bug #650] Marshal.load raises RegexpError

by Nobuyoshi Nakada-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

チケット #650 が更新されました。 (by Yuki Sonoda)

Target version 1.9.xにセット

1.9.1には間に合わなそうです。直接的な解決はしません @ Ruby開発者会議
----------------------------------------
http://redmine.ruby-lang.org/issues/show/650

----------------------------------------
http://redmine.ruby-lang.org


[ruby-dev:38753] [Bug #650] Marshal.load raises RegexpError

by Nobuyoshi Nakada-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

チケット #650 が更新されました。 (by Yui NARUSE)

ruby -v ruby 1.9.2devにセット

修正案です。エンコーディングを見て、UTF-8でない場合は1.8からとみなして、s/\\u/u/gしています。

diff --git a/marshal.c b/marshal.c
index 0c44eba..d572ecd 100644
--- a/marshal.c
+++ b/marshal.c
@@ -1393,8 +1393,19 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
        {  
            volatile VALUE str = r_bytes(arg);
            int options = r_byte(arg);
+           v = r_entry(rb_reg_new("", 0, options), arg);
+           if (ivp) {
+               r_ivar(v, arg);
+               rb_p(v);
+               *ivp = Qfalse;
+           }
+           rb_enc_copy(str, v);
+           if (rb_enc_get_index(str) != rb_utf8_encindex()) {
+#define f_gsub_bang(x,y,z) rb_funcall(x, rb_intern("gsub!"), 2, y, z)
+               f_gsub_bang(str, rb_reg_new("\\\\u", 3, 0), rb_usascii_str_new_cstr("u"));
+           }
            v = r_entry(rb_reg_new_str(str, options), arg);
-            v = r_leave(v, arg);
+           v = r_leave(v, arg);
        }
        break;

----------------------------------------
http://redmine.ruby-lang.org/issues/show/650

----------------------------------------
http://redmine.ruby-lang.org


[ruby-dev:38757] [Bug #650](Closed) Marshal.load raises RegexpError

by Nobuyoshi Nakada-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

チケット #650 が更新されました。 (by Yui NARUSE)

ステータス OpenからClosedに変更
進捗 % 0から100に変更

Applied in changeset r23999.
----------------------------------------
http://redmine.ruby-lang.org/issues/show/650

----------------------------------------
http://redmine.ruby-lang.org

< Prev | 1 - 2 | Next >