From 119d66232db60742c0110cb0019f41f912ae3aaf Mon Sep 17 00:00:00 2001 From: nobu Date: Sat, 8 Mar 2014 04:30:56 +0000 Subject: process.c: expand buffer on ERANGE * process.c (obj2uid, obj2gid): now getpwnam_r() and getgrnam_r() may need larger buffers than sysconf values, so retry with expanding the buffer when ERANGE is returned. [ruby-core:61325] [Bug #9600] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@45290 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- process.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) (limited to 'process.c') diff --git a/process.c b/process.c index 77cc65bd2f..33a294866d 100644 --- a/process.c +++ b/process.c @@ -153,6 +153,7 @@ static void check_gid_switch(void); # define USE_GETPWNAM_R 1 # define GETPW_R_SIZE_INIT sysconf(_SC_GETPW_R_SIZE_MAX) # define GETPW_R_SIZE_DEFAULT 0x1000 +# define GETPW_R_SIZE_LIMIT 0x10000 # endif # ifdef USE_GETPWNAM_R # define PREPARE_GETPWNAM \ @@ -192,6 +193,7 @@ static rb_uid_t obj2uid(VALUE id); # define USE_GETGRNAM_R # define GETGR_R_SIZE_INIT sysconf(_SC_GETGR_R_SIZE_MAX) # define GETGR_R_SIZE_DEFAULT 0x1000 +# define GETGR_R_SIZE_LIMIT 0x10000 # endif # ifdef USE_GETGRNAM_R # define PREPARE_GETGRNAM \ @@ -4741,8 +4743,17 @@ obj2uid(VALUE id getpw_buf = RSTRING_PTR(*getpw_tmp); getpw_buf_len = rb_str_capacity(*getpw_tmp); } - if (getpwnam_r(usrname, &pwbuf, getpw_buf, getpw_buf_len, &pwptr)) - rb_sys_fail("getpwnam_r"); + errno = ERANGE; + /* gepwnam_r() on MacOS X doesn't set errno if buffer size is insufficient */ + while (getpwnam_r(usrname, &pwbuf, getpw_buf, getpw_buf_len, &pwptr)) { + if (errno != ERANGE || getpw_buf_len >= GETPW_R_SIZE_LIMIT) { + rb_free_tmp_buffer(getpw_tmp); + rb_sys_fail("getpwnam_r"); + } + rb_str_modify_expand(*getpw_tmp, getpw_buf_len); + getpw_buf = RSTRING_PTR(*getpw_tmp); + getpw_buf_len = rb_str_capacity(*getpw_tmp); + } #else pwptr = getpwnam(usrname); #endif @@ -4810,8 +4821,17 @@ obj2gid(VALUE id getgr_buf = RSTRING_PTR(*getgr_tmp); getgr_buf_len = rb_str_capacity(*getgr_tmp); } - if (getgrnam_r(grpname, &grbuf, getgr_buf, getgr_buf_len, &grptr)) - rb_sys_fail("getgrnam_r"); + errno = ERANGE; + /* gegrnam_r() on MacOS X doesn't set errno if buffer size is insufficient */ + while (getgrnam_r(grpname, &grbuf, getgr_buf, getgr_buf_len, &grptr)) { + if (errno != ERANGE || getgr_buf_len >= GETGR_R_SIZE_LIMIT) { + rb_free_tmp_buffer(getgr_tmp); + rb_sys_fail("getgrnam_r"); + } + rb_str_modify_expand(*getgr_tmp, getgr_buf_len); + getgr_buf = RSTRING_PTR(*getgr_tmp); + getgr_buf_len = rb_str_capacity(*getgr_tmp); + } #else grptr = getgrnam(grpname); #endif -- cgit v1.2.3