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.
|