On Friday 02 January 2015 21:04:04 you wrote:
> On Mon, Dec 29, 2014 at 10:19 PM, tito <farmat...@tiscali.it> wrote:
> > after putting more work at this malloced libpwdgrp functions I think they  
> > now are
> > pretty robust, with no memory leaks and able to handle more or less 
> > gracefully
> > problematic passwd/group/shadow files. The main features of this
> > implemantation are:
> >
> > * 1) the buffer for getpwuid, getgrgid, getpwnam, getgrnam is dynamically
> >  *    allocated and reused by later calls. if ERANGE error pops up it is
> >  *    reallocated to the size of the longest line found so far in the
> >  *    passwd/group files and reused for later calls.
> >  *    If ENABLE_FEATURE_CLEAN_UP is set the buffers are freed at program
> >  *    exit using the atexit function to make valgrind happy.
> >   * 2) the passwd/group files:
> >  *      a) must contain the expected number of fields (as per count of field
> >  *         delimeters ":") or we will complain with a error message.
> >  *      b) leading or trailing whitespace in fields is allowed and handled.
> >  *      c) some fields are not allowed to be empty (e.g. username, uid/gid,
> >  *         homedir, shell) and in this case NULL is returned and errno is
> >  *         set to EINVAL. This behaviour could be easily changed by
> >  *         modifying PW_DEF, GR_DEF, SP_DEF strings (uppercase
> >  *         makes a field mandatory).
> >  *      d) the string representing uid/gid must be convertible by strtoXX
> >  *         functions or NULL is returned and errno is set to EINVAL.
> >  *      e) leading or trailing whitespaces in member names and empty members
> >  *         are allowed and handled.
> >  * 3) the internal function for getgrouplist uses a dynamically allocated
> >  *    buffer and retries with a bigger one in case it is to small;
> >  * 4) the _r functions use the user supplied buffers that are never 
> > reallocated
> >  *    but use mostly the same common code as the other functions.
> >  * 5) at the moment only the functions really used by busybox code are
> >  *    implemented, if you need a particular missing function it should be
> >  *    easy to write it by using the internal common code.
> >
> > I've done some testing and everything seems to work as expected
> > nonetheless some more testing by the list members and a good
> > code review by more experienced programmers is needed as this
> > lib calls stuff is very new for me and maybe I overlooked
> > something obvious.
> > Attached you will find a patch and a drop in replacement
> > for pwd_grp.c for easier review and testing.
> >
> > Size increase is about 120 bytes due to the increased feature set,
> > but the bloat-o-meter output looks somewhat suspicious:
> >
> > ./scripts/bloat-o-meter busybox_unstripped_original busybox_unstripped
> > function                                             old     new   delta
> > convert_to_struct                                      -     351    +351
> > parse_common                                           -     214    +214
> ...
> > bb__pgsreader                                        194       -    -194
> > bb__parsegrent                                       246       -    -246
> > ------------------------------------------------------------------------------
> > (add/remove: 16/10 grow/shrink: 4/6 up/down: 1411/-1293)      Total: 118 
> > bytes
> 
> 
> I see the following bloatcheck:
> 
> function                                             old     new   delta
> convert_to_struct                                      -     369    +369
> parse_common                                           -     236    +236
> tokenize                                               -     133    +133
> getgrouplist_internal                                195     328    +133
> getpw_common                                           -      97     +97
> getgr_common                                           -      97     +97
> getpw_common_malloc                                    -      81     +81
> getgr_common_malloc                                    -      81     +81
> parse_file                                             -      76     +76
> bb_internal_getpwent_r                               102     148     +46
> bb_internal_getgrent_r                               102     148     +46
> my_pwd                                                 -      28     +28
> my_grp                                                 -      16     +16
> sp_def                                                 -       4      +4
> pwd_buffer_size                                        -       4      +4
> pwd_buffer                                             -       4      +4
> pw_def                                                 -       4      +4
> my_pw                                                  -       4      +4
> my_gr                                                  -       4      +4
> grp_buffer_size                                        -       4      +4
> grp_buffer                                             -       4      +4
> gr_def                                                 -       4      +4
> gr_off                                                 3       4      +1
> sp_off                                                 9       8      -1
> ptr_to_statics                                         4       -      -4
> bb_internal_getpwuid                                  38      19     -19
> bb_internal_getspnam_r                               121      96     -25
> bb_internal_getgrgid                                  44      19     -25
> bb_internal_getpwnam                                  38      11     -27
> get_S                                                 30       -     -30
> bb_internal_getgrnam                                  44      11     -33
> bb_internal_fgetpwent_r                               51       -     -51
> bb_internal_fgetgrent_r                               51       -     -51
> bb_internal_getpwuid_r                               113      48     -65
> bb_internal_getgrgid_r                               113      48     -65
> bb_internal_getpwnam_r                               121      40     -81
> bb_internal_getgrnam_r                               121      40     -81
> bb__parsepwent                                       110       -    -110
> bb__parsespent                                       120       -    -120
> bb__pgsreader                                        213       -    -213
> bb__parsegrent                                       226       -    -226
> ------------------------------------------------------------------------------
> (add/remove: 19/8 grow/shrink: 4/10 up/down: 1476/-1227)      Total: 249 bytes
>    text       data        bss        dec        hex    filename
>  923471        928      17684     942083      e6003    busybox_old
>  923708        936      17744     942388      e6134    busybox_unstripped
> 
> The growth of data and bss needs fixing. Old code contained
> infrastructure which folded all data into one on-demand allocated area.
> Let's use a similar trick here?
> 
> tokenize() fails to strip trailing whitespace from last field.
> 
> get_record_line() returns ERANGE if buffer is too small. Callers
> retry when they see that. Why can't get_record_line() itself reallocate
> the buffer, avoiding retry logic altogether?
> Sounds suspiciously like our good old xmalloc_fgetline() ;)
> 
> +               if (def[idx] == 'm') {
> +                       char *s =  (char *) nth_string(buffer, idx);
> +                       int i = tokenize(s, ',');
> +                       char *p = (char *) nth_string(s, i);
> +                       /* Now align (p+1), rounding up. */
> +                       /* Assumes sizeof(char **) is a power of 2. */
> +                       members = (char **)((((intptr_t) p) + sizeof(char **))
> +                                               &
> ~((intptr_t)(sizeof(char **) - 1)));
> +                       ((struct group *) result)->gr_mem = members;
> 
> Looks like "members" now points past buffer's terminating NUL,
> which may not even be within allocated area.
> 
> How about attached version?
> 

Hi Denys,

thanks for applying it, I never believed this could get into bb! 
I fear I need  a few days (or more...) to understand your changes.
Will run it with the test cases I  wrote  with my standalone version (if 
possible).
I think we should fix the comments at the start as some now seem outdated.
I really have lots of questions...  
If I understand it correctly now we use our internal malloced buffer
also for the _r functions and copy the results to the user supplied buffer?
Also I wonder about:

while ((buf = xmalloc_fgetline(fp)) != NULL) {

if we use it to allocate a buffer holding the complete line from e.g  /etc/group
that includes already group members  why do we need to realloc it later...

Will look at it tomorrow, there is a lot of new stuff for me to learn ;-)

There were also some improvements I was talking about with
Harald Becker (prevent flooding terminal and syslog with error messages
if a line with wrong number of fields is found and corrupted/big sized
passwd/group files) but more to that later.
Thanks for your time and effort to improve my code,

Ciao,
Tito


_______________________________________________
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to