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

tkutil.c: fix memory leak and segfault

* ext/tk/tkutil/tkutil.c (cbsubst_append_inf_key): extract a
  function append a key in subst info to a string.  make result
  strings first and get rid of potential memory leak.

* ext/tk/tkutil/tkutil.c (cbsubst_get_subst_arg): allocate the
  result buffer as a string to fix:

  * memory leak when the argument key is not found:

      loop {Tk::Event.subst_arg(:a) rescue nil}

  * buffer overflow segfault when many arguments:

      class T < TkUtil::CallbackSubst
        _setup_subst_table([[?a, ?A, :_a]], [])
        subst_arg(*[:_a]*1000).size
      end

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50704 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2015-05-31 22:32:14 +00:00
parent 1611735b29
commit 30e6825e1b

View file

@ -1323,6 +1323,39 @@ cbsubst_def_attr_aliases(self, tbl)
return rb_funcall(inf->aliases, rb_intern("update"), 1, tbl); return rb_funcall(inf->aliases, rb_intern("update"), 1, tbl);
} }
static VALUE
cbsubst_append_inf_key(str, inf, idx)
VALUE str;
const struct cbsubst_info *inf;
int idx;
{
const long len = inf->keylen[idx];
const long olen = RSTRING_LEN(str);
char *buf, *ptr;
rb_str_modify_expand(str, (len ? len : 1) + 2);
buf = RSTRING_PTR(str);
ptr = buf + olen;
*(ptr++) = '%';
if (len != 0) {
/* longname */
strncpy(ptr, inf->key[idx], len);
ptr += len;
}
else {
/* single char */
*(ptr++) = (unsigned char)idx;
}
*(ptr++) = ' ';
rb_str_set_len(str, ptr - buf);
return str;
}
static VALUE static VALUE
cbsubst_sym_to_subst(self, sym) cbsubst_sym_to_subst(self, sym)
VALUE self; VALUE self;
@ -1330,9 +1363,7 @@ cbsubst_sym_to_subst(self, sym)
{ {
struct cbsubst_info *inf; struct cbsubst_info *inf;
VALUE str; VALUE str;
char *buf, *ptr;
int idx; int idx;
long len;
ID id; ID id;
volatile VALUE ret; volatile VALUE ret;
@ -1353,27 +1384,7 @@ cbsubst_sym_to_subst(self, sym)
} }
if (idx >= CBSUBST_TBL_MAX) return sym; if (idx >= CBSUBST_TBL_MAX) return sym;
ptr = buf = ALLOC_N(char, inf->full_subst_length + 1); return cbsubst_append_inf_key(rb_str_new(0, 0), inf, idx);
*(ptr++) = '%';
if ((len = inf->keylen[idx]) != 0) {
/* longname */
strncpy(ptr, inf->key[idx], len);
ptr += len;
} else {
/* single char */
*(ptr++) = (unsigned char)idx;
}
*(ptr++) = ' ';
*(ptr++) = '\0';
ret = rb_str_new2(buf);
xfree(buf);
return ret;
} }
static VALUE static VALUE
@ -1384,16 +1395,13 @@ cbsubst_get_subst_arg(argc, argv, self)
{ {
struct cbsubst_info *inf; struct cbsubst_info *inf;
VALUE str; VALUE str;
char *buf, *ptr;
int i, idx; int i, idx;
long len;
ID id; ID id;
volatile VALUE arg_sym, ret; VALUE arg_sym, ret, result;
inf = cbsubst_get_ptr(self); inf = cbsubst_get_ptr(self);
ptr = buf = ALLOC_N(char, inf->full_subst_length + 1); result = rb_str_new(0, 0);
for(i = 0; i < argc; i++) { for(i = 0; i < argc; i++) {
switch(TYPE(argv[i])) { switch(TYPE(argv[i])) {
case T_STRING: case T_STRING:
@ -1425,27 +1433,10 @@ cbsubst_get_subst_arg(argc, argv, self)
rb_raise(rb_eArgError, "cannot find attribute :%"PRIsVALUE, str); rb_raise(rb_eArgError, "cannot find attribute :%"PRIsVALUE, str);
} }
*(ptr++) = '%'; result = cbsubst_append_inf_key(result, inf, idx);
if ((len = inf->keylen[idx]) != 0) {
/* longname */
strncpy(ptr, inf->key[idx], len);
ptr += len;
} else {
/* single char */
*(ptr++) = (unsigned char)idx;
}
*(ptr++) = ' ';
} }
*ptr = '\0'; return result;
ret = rb_str_new2(buf);
xfree(buf);
return ret;
} }
static VALUE static VALUE
@ -1454,8 +1445,8 @@ cbsubst_get_subst_key(self, str)
VALUE str; VALUE str;
{ {
struct cbsubst_info *inf; struct cbsubst_info *inf;
volatile VALUE list; VALUE list;
volatile VALUE ret; VALUE ret;
long i, len, keylen; long i, len, keylen;
int idx; int idx;
char *buf, *ptr; char *buf, *ptr;
@ -1466,7 +1457,8 @@ cbsubst_get_subst_key(self, str)
inf = cbsubst_get_ptr(self); inf = cbsubst_get_ptr(self);
ptr = buf = ALLOC_N(char, len + 1); ret = rb_str_new(0, len);
ptr = buf = RSTRING_PTR(ret);
for(i = 0; i < len; i++) { for(i = 0; i < len; i++) {
VALUE keyval = RARRAY_CONST_PTR(list)[i]; VALUE keyval = RARRAY_CONST_PTR(list)[i];
@ -1494,10 +1486,8 @@ cbsubst_get_subst_key(self, str)
*(ptr++) = ' '; *(ptr++) = ' ';
} }
} }
*ptr = '\0';
ret = rb_str_new2(buf); rb_str_set_len(ret, ptr - buf);
xfree(buf);
return ret; return ret;
} }
@ -1506,45 +1496,26 @@ cbsubst_get_all_subst_keys(self)
VALUE self; VALUE self;
{ {
struct cbsubst_info *inf; struct cbsubst_info *inf;
char *buf, *ptr;
char *keys_buf, *keys_ptr; char *keys_buf, *keys_ptr;
int idx; int idx;
long len; VALUE str, keys_str;
volatile VALUE ret;
inf = cbsubst_get_ptr(self); inf = cbsubst_get_ptr(self);
ptr = buf = ALLOC_N(char, inf->full_subst_length + 1); str = rb_str_new(0, 0);
keys_ptr = keys_buf = ALLOC_N(char, CBSUBST_TBL_MAX + 1); keys_str = rb_str_new(0, CBSUBST_TBL_MAX);
keys_ptr = keys_buf = RSTRING_PTR(keys_str);
for(idx = 0; idx < CBSUBST_TBL_MAX; idx++) { for(idx = 0; idx < CBSUBST_TBL_MAX; idx++) {
if (inf->ivar[idx] == (ID) 0) continue; if (inf->ivar[idx] == (ID) 0) continue;
*(keys_ptr++) = (unsigned char)idx; *(keys_ptr++) = (unsigned char)idx;
*(ptr++) = '%'; str = cbsubst_append_inf_key(str, inf, idx);
if ((len = inf->keylen[idx]) != 0) {
/* longname */
strncpy(ptr, inf->key[idx], len);
ptr += len;
} else {
/* single char */
*(ptr++) = (unsigned char)idx;
}
*(ptr++) = ' ';
} }
rb_str_set_len(keys_str, keys_ptr - keys_buf);
*ptr = '\0'; return rb_ary_new3(2, keys_str, str);
*keys_ptr = '\0';
ret = rb_ary_new3(2, rb_str_new2(keys_buf), rb_str_new2(buf));
xfree(buf);
xfree(keys_buf);
return ret;
} }
static VALUE static VALUE