ruby-changes:33211
From: nobu <ko1@a...>
Date: Sat, 8 Mar 2014 13:31:03 +0900 (JST)
Subject: [ruby-changes:33211] nobu:r45290 (trunk): process.c: expand buffer on ERANGE
nobu 2014-03-08 13:30:56 +0900 (Sat, 08 Mar 2014) New Revision: 45290 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=45290 Log: 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] Modified files: trunk/ChangeLog trunk/process.c Index: ChangeLog =================================================================== --- ChangeLog (revision 45289) +++ ChangeLog (revision 45290) @@ -1,3 +1,10 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Sat Mar 8 13:30:39 2014 Nobuyoshi Nakada <nobu@r...> + + * 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] + Sat Mar 8 07:35:40 2014 Nobuyoshi Nakada <nobu@r...> * enum.c (find_i): yield multiple values instead of a packed Index: process.c =================================================================== --- process.c (revision 45289) +++ process.c (revision 45290) @@ -153,6 +153,7 @@ static void check_gid_switch(void); https://github.com/ruby/ruby/blob/trunk/process.c#L153 # 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); https://github.com/ruby/ruby/blob/trunk/process.c#L193 # 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 https://github.com/ruby/ruby/blob/trunk/process.c#L4743 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 https://github.com/ruby/ruby/blob/trunk/process.c#L4821 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 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/