StringScanner#scan BUG?

e$B$H$_$?$G$9!#e(B

Ruby 1.8.5 e$B$G<!$N%3!<%I$r<B9T$9$k$H!"e(B$KCODE=“NONE”
[email protected],I=8=$N%U%ie(B
e$B%0$,e(B e, s, u e$B$N>l9g$K!“e(B"a:b” e$B$rJV$7$^$9!#e(B

require “strscan”
str = “a:b”
[“NONE”, “EUC”, “SJIS”, “UTF8”].each do |code|
p code
$KCODE = code
p StringScanner.new(str).scan(/[^\x01:]+/n)
p StringScanner.new(str).scan(/[^\x01:]+/e)
p StringScanner.new(str).scan(/[^\x01:]+/s)
p StringScanner.new(str).scan(/[^\x01:]+/u)
end

[^\x01:] e$B$re(B [^:\x01] e$B$K$9$k$HH/@8$7$^$;$s!#4|BT$I$*$je(B “a”
e$B$rJV$7$^$9!#e(B

e$B$O$8$a$Oe(B Ruby
e$BK\[email protected],I=8=$N%P%0$+$H;W$C$?$N$G$9$,!"e(BStringScanner e$B0Je(B
e$B30$G$OH/@8$7$J$$$h$&$G$9!#e(B

[email protected]$G$9!#$9$_$^$;$s!"$9$C$+$j8+Mn$H$7$F$^$7$?!#e(B

In mail “[ruby-dev:29914] StringScanner#scan BUG?”
e$B$H$_$?$^$5$R$me(B [email protected] wrote:

p StringScanner.new(str).scan(/[^\x01:]+/n)
p StringScanner.new(str).scan(/[^\x01:]+/e)
p StringScanner.new(str).scan(/[^\x01:]+/s)
p StringScanner.new(str).scan(/[^\x01:]+/u)
end

[^\x01:] e$B$re(B [^:\x01] e$B$K$9$k$HH/@8$7$^$;$s!#4|BT$I$*$je(B “a” e$B$rJV$7$^$9!#e(B

e$B$O$8$a$Oe(B Ruby e$BK\[email protected],I=8=$N%P%0$+$H;W$C$?$N$G$9$,!"e(BStringScanner e$B0Je(B
e$B30$G$OH/@8$7$J$$$h$&$G$9!#e(B

strscan.c e$B$Ge(B kcode_set_option
e$B$r8F$s$G$J$+$C$?$N$,860x$G$7$?!#e(B

e$B0J2<$N%Q%C%[email protected]$G$-$k$N$G$9$,!"e(B1.8
e$B%V%i%s%A$K%3%_%C%H$7$F$h$$$G$7$g$&$+!)e(B
extern e$B4X?t$,e(B 2 e$B$DA}$($^$9!#e(B

Index: intern.h

RCS file: /var/cvs/src/ruby/intern.h,v
retrieving revision 1.139.2.21
diff -u -r1.139.2.21 intern.h
— intern.h 30 Oct 2006 02:24:08 -0000 1.139.2.21
+++ intern.h 7 Jan 2007 01:33:27 -0000
@@ -370,6 +370,8 @@
int rb_reg_options _((VALUE));
void rb_set_kcode _((const char*));
const char* rb_get_kcode _((void));
+void rb_kcode_set_option _((VALUE));
+void rb_kcode_reset_option _((void));
/* ruby.c */
RUBY_EXTERN VALUE rb_argv;
RUBY_EXTERN VALUE rb_argv0;
Index: re.c

RCS file: /var/cvs/src/ruby/re.c,v
retrieving revision 1.114.2.20
diff -u -r1.114.2.20 re.c
— re.c 20 Jul 2006 07:04:17 -0000 1.114.2.20
+++ re.c 7 Jan 2007 01:31:23 -0000
@@ -200,8 +200,8 @@

static int curr_kcode;

-static void
-kcode_set_option(re)
+void
+rb_kcode_set_option(re)
VALUE re;
{
if (!FL_TEST(re, KCODE_FIXED)) return;
@@ -224,8 +224,8 @@
}
}

-static void
-kcode_reset_option()
+void
+rb_kcode_reset_option()
{
if (reg_kcode == curr_kcode) return;
switch (reg_kcode) {
@@ -253,9 +253,9 @@

 if (!FL_TEST(re, KCODE_FIXED))

return mbclen©;

  • kcode_set_option(re);
  • rb_kcode_set_option(re);
    len = mbclen©;
  • kcode_reset_option();
  • rb_kcode_reset_option();
    return len;
    }

@@ -486,11 +486,11 @@
}
if (*ptr == ‘:’ && ptr[len-1] == ‘)’) {
Regexp *rp;

  •  kcode_set_option(re);
    
  •  rb_kcode_set_option(re);
     rp = ALLOC(Regexp);
     MEMZERO((char *)rp, Regexp, 1);
     err = re_compile_pattern(++ptr, len -= 2, rp) != 0;
    
  •  kcode_reset_option();
    
  •  rb_kcode_reset_option();
     re_free_pattern(rp);
    

    }
    if (err) {
    @@ -849,7 +849,7 @@
    char *err;

    if (FL_TEST(re, KCODE_FIXED))

  •  kcode_set_option(re);
    
  •  rb_kcode_set_option(re);
    

    rb_reg_check(re);
    RREGEXP(re)->ptr->fastmap_accurate = 0;
    err = re_compile_pattern(RREGEXP(re)->str, RREGEXP(re)->len,
    RREGEXP(re)->ptr);
    @@ -870,9 +870,9 @@
    if (may_need_recompile) rb_reg_prepare_re(re);

    if (FL_TEST(re, KCODE_FIXED))

  • kcode_set_option(re);
  • rb_kcode_set_option(re);
    else if (reg_kcode != curr_kcode)
  • kcode_reset_option();
  • rb_kcode_reset_option();

    if (reverse) {
    range = -pos;
    @@ -904,9 +904,9 @@
    if (may_need_recompile) rb_reg_prepare_re(re);

    if (FL_TEST(re, KCODE_FIXED))

  • kcode_set_option(re);
  • rb_kcode_set_option(re);
    else if (reg_kcode != curr_kcode)
  • kcode_reset_option();
  • rb_kcode_reset_option();

    if (reverse) {
    range = -pos;
    @@ -918,7 +918,7 @@
    pos, range, &regs);

    if (FL_TEST(re, KCODE_FIXED))

  • kcode_reset_option();
  • rb_kcode_reset_option();

    if (result == -2) {
    rb_reg_raise(RREGEXP(re)->str, RREGEXP(re)->len,
    @@ -1364,7 +1364,7 @@
    }

    if (options & ~0xf) {

  • kcode_set_option((VALUE)re);
  • rb_kcode_set_option((VALUE)re);
    }
    if (ruby_ignorecase) {
    options |= RE_OPTION_IGNORECASE;
    @@ -1376,7 +1376,7 @@
    re->str[len] = ‘\0’;
    re->len = len;
    if (options & ~0xf) {
  • kcode_reset_option();
  • rb_kcode_reset_option();
    }
    if (ruby_in_compile) FL_SET(obj, REG_LITERAL);
    }
    @@ -1839,7 +1839,7 @@
    }
    StringValue(str);
    str = rb_reg_quote(str);
  • kcode_reset_option();
  • rb_kcode_reset_option();
    return str;
    }

Index: ext/strscan/strscan.c

RCS file: /var/cvs/src/ruby/ext/strscan/strscan.c,v
retrieving revision 1.7.2.8
diff -u -r1.7.2.8 strscan.c
— ext/strscan/strscan.c 26 Jul 2006 09:37:00 -0000 1.7.2.8
+++ ext/strscan/strscan.c 7 Jan 2007 01:31:23 -0000
@@ -403,6 +403,7 @@
if (S_RESTLEN§ < 0) {
return Qnil;
}

  • rb_kcode_set_option(regex);
    if (headonly) {
    ret = re_match(RREGEXP(regex)->ptr,
    CURPTR§, S_RESTLEN§,
    @@ -416,6 +417,7 @@
    S_RESTLEN§,
    &(p->regs));
    }

  • rb_kcode_reset_option();

    if (ret == -2) rb_raise(ScanError, “regexp buffer overflow”);
    if (ret < 0) {

 問題ありません。お願いします。

At Sun, 7 Jan 2007 10:34:15 +0900,
Minero A. wrote:

[^\x01:] ã‚’ [^:\x01] にすると発生しません。期待どおり “a” を返します。

はじめは Ruby 本体の正規表現のバグかと思ったのですが、StringScanner 以
外では発生しないようです。

strscan.c で kcode_set_option ã‚’å‘¼ã‚“ã§ãªã‹ã£ãŸã®ãŒåŽŸå› ã§ã—ãŸã€‚

以下のパッチで修正できるのですが、1.8 ブランチにコミットしてよいでしょうか?
extern 関数が 2 つ増えます。


/
/__ __ Akinori.org / MUSHA.org
/ ) ) ) ) / FreeBSD.org / Ruby-lang.org
Akinori MUSHA aka / (_ / ( (__( @ iDaemons.org / and.or.jp

“Different eyes see different things,
Different hearts beat on different strings –
But there are times for you and me when all such things agree”

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs