SEGV by attr

e$B0J2<$N$h$&$K$9$k$He(B SEGV e$B$7$^$9!#e(B

% limit stacksize 1m
% ./ruby -ve ’
class C
attr “a” * 2000000
end

ruby 1.9.0 (2007-09-22 patchlevel 0) [i686-linux]
zsh: segmentation fault (core dumped) ./ruby -ve ’ class C attr “a” *
2000000 end ’
% gdb ruby core.4810
GNU gdb 6.4.90-debian
Copyright © 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you
are
welcome to change it and/or distribute copies of it under certain
conditions.
Type “show copying” to see the conditions.
There is absolutely no warranty for GDB. Type “show warranty” for
details.
This GDB was configured as “i486-linux-gnu”…Using host libthread_db
library “/lib/tls/libthread_db.so.1”.

warning: Can’t read pathname for load map: Input/output error.
Reading symbols from /lib/tls/libpthread.so.0…done.
Loaded symbols for /lib/tls/libpthread.so.0
Reading symbols from /lib/tls/libdl.so.2…done.
Loaded symbols for /lib/tls/libdl.so.2
Reading symbols from /lib/tls/libcrypt.so.1…done.
Loaded symbols for /lib/tls/libcrypt.so.1
Reading symbols from /lib/tls/libm.so.6…done.
Loaded symbols for /lib/tls/libm.so.6
Reading symbols from /lib/tls/libc.so.6…done.
Loaded symbols for /lib/tls/libc.so.6
Reading symbols from /lib/ld-linux.so.2…done.
Loaded symbols for /lib/ld-linux.so.2
Core was generated by `./ruby -ve
class C
attr “a” * 2000000
end
'.
Program terminated with signal 11, Segmentation fault.
#0 0x08058f4b in rb_attr (klass=3084222700, id=8776, read=2, write=0,
ex=2) at eval_method.ci:441
441 snprintf(buf, len, “@%s”, name);
(gdb) bt
#0 0x08058f4b in rb_attr (klass=3084222700, id=8776, read=2, write=0,
ex=2) at eval_method.ci:441
#1 0x0807942f in rb_mod_attr_reader (argc=1, argv=0xb7d7a028,
klass=3084222700) at object.c:1408
#2 0x080794d8 in rb_mod_attr (argc=1, argv=0xb7d7a028,
klass=3084222700) at object.c:1421
#3 0x080edf5a in call_cfunc (func=0x8079441 <rb_mod_attr>,
recv=3084222700, len=-1, argc=1, argv=0xb7d7a028)
at insnhelper.ci:276
#4 0x080f59e1 in vm_call_cfunc (th=0x8181160, reg_cfp=0xb7df9f28,
num=1, id=1088, recv=3084222700, klass=3084222680,
mn=0xb7d780e0, blockptr=0x0) at insnhelper.ci:365
#5 0x080f5570 in vm_call_method (th=0x8181160, cfp=0xb7df9f28, num=1,
blockptr=0x0, flag=8, id=1088, mn=0xb7d780b8,
recv=3084222700, klass=3084222680) at insnhelper.ci:490
#6 0x080f1daf in vm_eval (th=0x8181160, initial=0) at insns.def:1073
#7 0x080f5bba in vm_eval_body (th=0x8181160) at vm.c:1162
#8 0x080f61ff in rb_iseq_eval (iseqval=3084222940) at vm.c:1371
#9 0x0805a47d in ruby_exec_node (n=0xb7d58218, file=0x81bb1d1 “-e”) at
eval.c:231
#10 0x0805a500 in ruby_run_node (n=0xb7d58218) at eval.c:256
#11 0x080576c5 in main (argc=3, argv=0xbff33104, envp=0xbff33114) at
main.c:46
(gdb)

e$B$J$+$@$G$9!#e(B

At Sun, 23 Sep 2007 00:52:42 +0900,
Tanaka A. wrote in [ruby-dev:31818]:

Program terminated with signal 11, Segmentation fault.
#0 0x08058f4b in rb_attr (klass=3084222700, id=8776, read=2, write=0, ex=2) at eval_method.ci:441
441 snprintf(buf, len, “@%s”, name);

e$B$U$H!“e(BID_ATTRSETe$B$N$h$&$Ke(BID_INSTANCEe$B$J$I$be(BID_LOCALe$B$HBP1~4X78$,$“e(B
e$B$l$P!”$o$6$o$6$”$i$?$a$FJ8;zNs$r:n$kI,MW$b$J$$$s$8$c$J$$$+!"$H;We(B
e$B$$$^$7$?!#e(B

Index: parse.y

— parse.y (revision 13508)
+++ parse.y (working copy)
@@ -7375,4 +7375,28 @@ rb_id_attrset(ID id)
}

+ID
+rb_id_ivar(ID id)
+{

  • id &= ~ID_SCOPE_MASK;
  • id |= ID_INSTANCE;
  • return id;
    +}

+ID
+rb_id_cvar(ID id)
+{

  • id &= ~ID_SCOPE_MASK;
  • id |= ID_CLASS;
  • return id;
    +}

+ID
+rb_id_gvar(ID id)
+{

  • id &= ~ID_SCOPE_MASK;
  • id |= ID_GLOBAL;
  • return id;
    +}

static NODE *
attrset_gen(struct parser_params *parser, NODE *recv, ID id)
@@ -8504,8 +8528,20 @@ rb_intern3(const char *name, long len, r
}
if (m - name < len) id = ID_JUNK;

  • m = name;
  • switch (id) {
  •  case ID_CLASS:
    
  • m++;
  •  case ID_GLOBAL:
    
  •  case ID_INSTANCE:
    
  • m++;
  • id |= rb_intern3(m, len-(m-name), enc) & ~ID_SCOPE_MASK;
  • goto id_register;
  •  default:
    
  • break;
  • }
    new_id:
    id |= ++global_symbols.last_id << ID_SCOPE_SHIFT;
    @@ -8534,4 +8570,17 @@ rb_intern_str(VALUE str)
    }

+static VALUE
+id2string(ID id)
+{

  • ID id2 = (id & ~ID_SCOPE_MASK) | ID_LOCAL;
  • VALUE str;
  • while (!(str = rb_id2str(id2))) {
  • if ((id2 & ID_SCOPE_MASK) == ID_CONST) return 0;
  • id2 = (id & ~ID_SCOPE_MASK) | ID_CONST;
  • }
  • return str;
    +}

VALUE
rb_id2str(ID id)
@@ -8558,19 +8607,27 @@ rb_id2str(ID id)
return (VALUE)data;

  • if (is_attrset_id(id)) {
  • ID id2 = (id & ~ID_SCOPE_MASK) | ID_LOCAL;
  • VALUE str;
  • while (!(str = rb_id2str(id2))) {
  •  if (!is_local_id(id2)) return 0;
    
  •  id2 = (id & ~ID_SCOPE_MASK) | ID_CONST;
    
  • }
  • switch (id & ID_SCOPE_MASK) {
  •  case ID_CLASS:
    
  • if (!(str = id2string(id))) return 0;
  • str = rb_str_append(rb_str_new2("@@"), str);
  • break;
  •  case ID_GLOBAL:
    
  • if (!(str = id2string(id))) return 0;
  • str = rb_str_append(rb_str_new2("$"), str);
  • break;
  •  case ID_INSTANCE:
    
  • if (!(str = id2string(id))) return 0;
  • str = rb_str_append(rb_str_new2("@"), str);
  • break;
  •  case ID_ATTRSET:
    
  • if (!(str = id2string(id))) return 0;
    str = rb_str_dup(str);
    rb_str_cat(str, “=”, 1);
  • rb_intern_str(str);
  • if (st_lookup(global_symbols.id_str, id, &data))
  •  return (VALUE)data;
    
  • break;
    }
  • return 0;
  • OBJ_FREEZE(str);
  • st_add_direct(global_symbols.sym_id, (st_data_t)str, id);
  • st_add_direct(global_symbols.id_str, id, (st_data_t)str);
  • return str;
    }

Index: eval_method.ci

— eval_method.ci (revision 13508)
+++ eval_method.ci (working copy)
@@ -406,4 +406,5 @@ rb_method_boundp(VALUE klass, ID id, int
}

+extern ID rb_id_ivar(ID);
void
rb_attr(VALUE klass, ID id, int read, int write, int ex)
@@ -438,5 +439,5 @@ rb_attr(VALUE klass, ID id, int read, in
rb_raise(rb_eArgError, “argument needs to be symbol or string”);
}

  • attriv = rb_intern_str(rb_sprintf("@%s", name));
  • attriv = rb_id_ivar(id);
    if (read) {
    rb_add_method(klass, id, NEW_IVAR(attriv), noex);

e$B$J$+$@$G$9!#e(B

At Tue, 25 Sep 2007 00:04:11 +0900,
Nobuyoshi N. wrote in [ruby-dev:31844]:

e$B$U$H!“e(BID_ATTRSETe$B$N$h$&$Ke(BID_INSTANCEe$B$J$I$be(BID_LOCALe$B$HBP1~4X78$,$“e(B
e$B$l$P!”$o$6$o$6$”$i$?$a$FJ8;zNs$r:n$kI,MW$b$J$$$s$8$c$J$$$+!"$H;We(B
e$B$$$^$7$?!#e(B

e$B$A$g$$$H8E$$$N$rAw$C$F$7$^$$$^$7$?!#e(B

@@ -8558,19 +8607,27 @@ rb_id2str(ID id)

VALUE str; e$B$He(B

str = rb_str_dup(str);
rb_str_cat(str, “=”, 1);

  • rb_intern_str(str);
  • if (st_lookup(global_symbols.id_str, id, &data))
  •  return (VALUE)data;
    
  • break;
  default:

return 0;

e$B$,H4$1$F$^$7$?!#e(B