scsh-users
[Top] [All Lists]

(user-info "UnKnOwN") => Segmentation fault

To: sjenkins@ms.com
Subject: (user-info "UnKnOwN") => Segmentation fault
From: Alan Bawden <Alan@lcs.mit.edu>
Date: Tue, 1 Apr 1997 14:57:53 -0500
Cc: scsh-bugs@martigny.ai.mit.edu
Sender: Alan@lcs.mit.edu
   Date: Tue, 01 Apr 1997 09:54:54 -0500
   From: Steven Jenkins <sjenkins@ms.com>


   FWIW, I can't reproduce your bug.  What level of scsh & what OS are
   you on?

Of -course- you can't reproduce it.  It depends on exactly what garbage
happens to be sitting on the stack.  For the record, I'm using Scsh-0.4.4,
compiled by GCC 2.6.3, running under FreeBSD 2.1.0 -- but there really is
no guarantee that you will be able to reproduce exactly the behavior I
reported.

But I thought I was clear enough about what was going wrong that we
wouldn't have to go through a second round of this.

   eg,
   lambda$ scsh
   Scsh 0.4
   > (user-info "sjenkins")
   '#{user-info "sjenkins"}
   > (user-info "noone")

   Error: Cannot get user's information
          #{Procedure 8656 name->user-info}
          "noone"
   1>

   >Since I don't 100% understand how CIG is supposed to work, I don't know the
   >right way to fix this.  The symptom:
   >
   >  curry:alan> scsh
   >  Scsh 0.4
   >  > (user-info "alan")
   >  '#{user-info "alan"}
   >  > (user-info "UnKnOwN")
   >  Segmentation fault
   >  curry:alan> 
   >
   >The problem is that the the code generated by CIG for `%name->user-info'
   >allocates a bunch of variables and passes the addresses of those variables
   >in to user_info_name().  user_info_name() looks like this:
   >
   >  int user_info_name(const char *name,
   >                 uid_t *uid, gid_t *gid, char **dir, char **shell)
   >  {
   >      struct passwd *pwd = getpwnam(name);
   >      if( !pwd ) return 0;
   >      *uid  = pwd->pw_uid;
   >      *gid  = pwd->pw_gid;
   >      *dir  = pwd->pw_dir;
   >      *shell = pwd->pw_shell;
   >      return 1;
   >      }
   >
   >Notice that if getpwnam() returns NULL, then nothing is done with those
   >variable addresses.  So the variables are still uninitialized.  Next, the
   >CIG generated code attempts to convert those C values into Scheme48 values.
   >Since the C value is ininitialized garbage, this conversion sometimes
   >generates a segmentation fault.

   It's actually more like: the 'main' return value is a boolean (ie, 'win?').
   If you 'lose', the contents are invalid, but you never poke at them, as an
   error is raised.

Read the code generated by CIG:

  scheme_value df_user_info_name(long nargs, scheme_value *args)
  {
      extern int user_info_name(const char *, uid_t *, gid_t  *, char **, char 
**);
      scheme_value ret1;
      int r1;
      uid_t r2;
      gid_t  r3;
      char *r4;
      char *r5;

      cig_check_nargs(2, nargs, "user_info_name");
      r1 = user_info_name(cig_string_body(args[1]), &r2, &r3, &r4, &r5);
      ret1 = ENTER_BOOLEAN(r1);
      VECTOR_REF(*args,0) = ENTER_FIXNUM(r2);
      VECTOR_REF(*args,1) = ENTER_FIXNUM(r3);
      {AlienVal(CAR(VECTOR_REF(*args,2))) = (long) r4; CDR(VECTOR_REF(*args,2)) 
= strlen_or_false(r4);}
      {AlienVal(CAR(VECTOR_REF(*args,3))) = (long) r5; CDR(VECTOR_REF(*args,3)) 
= strlen_or_false(r5);}
      return ret1;
      }

strlen_or_false() is passed garbage, which it passes to strlen(), which
gets a segmentation fault (depending on exactly what the garbage is).  I
stand by my original description of the problem.

   >
   >I would -guess- that the fix is to re-write all those routines in
   >`userinfo1.c'.  Although perhaps the answer is for CIG to initialize such
   >variables with reasonable initial C values.
   >
   >If the fix is the former, I'll fix it myself and send you the patch.  Let
   >me know...
   >
   >Seems like this is the kind of error that might be lurking in a lot of
   >places.  Someone might want to browse through the code looking for other
   >instances.

   Steven L. Jenkins

I'm still waiting for someone to tell me which fix is the right one.  I
have fixed my local scsh by fixing all the `userinfo1.c' procedures.  I
still think perhaps someone should check over the entire system for this
class of bug.

<Prev in Thread] Current Thread [Next in Thread>