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:
		
							parent
							
								
									1611735b29
								
							
						
					
					
						commit
						30e6825e1b
					
				
					 1 changed files with 50 additions and 79 deletions
				
			
		|  | @ -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 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 nobu
						nobu