sh: Fix crash with empty functions (f() { }) introduced in r196483

Empty pairs of braces are represented by a NULL node pointer, just like
empty lines at the top level.

Support for empty pairs of braces may be removed later. They make the code
more complex, have inconsistent behaviour (may or may not change $?), are
not specified by POSIX and are not allowed by some other shells like bash,
dash and ksh93.

Reported by:	kan
This commit is contained in:
Jilles Tjoelker 2009-08-28 22:41:25 +00:00
parent a99fcfd4ca
commit e16947f83d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=196634
5 changed files with 28 additions and 8 deletions

View File

@ -807,9 +807,9 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
funcnest++;
exitstatus = oexitstatus;
if (flags & EV_TESTED)
evaltree(&cmdentry.u.func->n, EV_TESTED);
evaltree(getfuncnode(cmdentry.u.func), EV_TESTED);
else
evaltree(&cmdentry.u.func->n, 0);
evaltree(getfuncnode(cmdentry.u.func), 0);
funcnest--;
INTOFF;
unreffunc(cmdentry.u.func);

View File

@ -286,7 +286,7 @@ printentry(struct tblentry *cmdp, int verbose)
out1fmt("function %s", cmdp->cmdname);
if (verbose) {
INTOFF;
name = commandtext(&cmdp->param.func->n);
name = commandtext(getfuncnode(cmdp->param.func));
out1c(' ');
out1str(name);
ckfree(name);

View File

@ -248,11 +248,9 @@ output(char *file)
fputs("\tstruct nodelist *next;\n", hfile);
fputs("\tunion node *n;\n", hfile);
fputs("};\n\n\n", hfile);
fputs("struct funcdef {\n", hfile);
fputs("\tunsigned int refcount;\n", hfile);
fputs("\tunion node n;\n", hfile);
fputs("};\n\n\n", hfile);
fputs("struct funcdef;\n", hfile);
fputs("struct funcdef *copyfunc(union node *);\n", hfile);
fputs("union node *getfuncnode(struct funcdef *);\n", hfile);
fputs("void reffunc(struct funcdef *);\n", hfile);
fputs("void unreffunc(struct funcdef *);\n", hfile);

View File

@ -61,6 +61,10 @@ STATIC struct nodelist *copynodelist(struct nodelist *);
STATIC char *nodesavestr(char *);
struct funcdef {
unsigned int refcount;
union node n;
};
/*
* Make a copy of a parse tree.
@ -85,6 +89,12 @@ copyfunc(union node *n)
}
union node *
getfuncnode(struct funcdef *fn)
{
return fn == NULL ? NULL : &fn->n;
}
STATIC void
calcsize(union node *n)
@ -153,7 +163,8 @@ nodesavestr(char *s)
void
reffunc(struct funcdef *fn)
{
fn->refcount++;
if (fn)
fn->refcount++;
}

View File

@ -0,0 +1,11 @@
# $FreeBSD$
f() { }
f
hash -v f >/dev/null
f() { { }; }
f
hash -v f >/dev/null
f() { { } }
f
hash -v f >/dev/null