Bug in csh (history, "!a%100s"). Report and Fix.
Michael Greim
greim at sbsvax.UUCP
Mon Jul 3 23:46:20 AEST 1989
In article <192 at dg.dg.com> in comp.bugs.sys5 rec at dg.dg.com (Robert Cousins)
reported a bug in csh.
Here is a description of it and a fix.
Absorb, apply and enjoy,
-mg
Symptoms:
>I have found that there are several basic bugs in the Cshell history
>mechanism which can be quite problematic. These were originally called
>to my attention by the work of a couple of researchers at the U of W in
>Madison. Bug 1:
>
> !a%999999999f
>
>which causes 999999999 spaces to be output to the screen. (Fewer on
>16 bit machines.) It seems that the error message in the history
>module goes through the first argument of a printf() call and can be
>interpreted as a format. A second bug, which happens on fewer machines
>takes place with:
>
> !a%f%f
>
>which can cause csh to dump core from a floating point error.
[...]
Diagnosis:
When printing an error message the csh function "error" passes
its first argument to its printf. If this string contains a "%",
printf tries to evaluate the following as a format accessing its
argument list, which is empty quite probably. This will cause
unpredictable behaviour, like core dumps, strange numbers, ...
Therapy:
Apply the following context diff to your source of 43BSD csh.
This fix works like this:
- in error only a string ending in "@" is passed as format string
to printf.
- only internal error messages needing arguments need format specifiers,
so I add a trailing "@" to any such message
- any string not ending with "@" is passed to printf with "%s" as first
parameter.
*** sh.dol.c.old Mon Jul 3 15:18:22 1989
--- sh.dol.c Mon Jul 3 15:12:39 1989
***************
*** 159,165
if (c == c1)
break;
if (c == '\n' || c == DEOF)
! error("Unmatched %c", c1);
if ((c & (QUOTE|TRIM)) == ('\n' | QUOTE))
--wp, ++i;
if (--i <= 0)
--- 159,165 -----
if (c == c1)
break;
if (c == '\n' || c == DEOF)
! error("Unmatched %c@", c1); /* mg 3-jul-89 */
if ((c & (QUOTE|TRIM)) == ('\n' | QUOTE))
--wp, ++i;
if (--i <= 0)
*** sh.err.c.old Mon Jul 3 15:18:36 1989
--- sh.err.c Mon Jul 3 15:16:10 1989
***************
*** 34,39
{
register char **v;
register char *ep;
/*
* Must flush before we print as we wish output before the error
--- 34,40 -----
{
register char **v;
register char *ep;
+ register int i; /* mg 3-jul-89 */
/*
* Must flush before we print as we wish output before the error
***************
*** 53,58
/*
* A zero arguments causes no printing, else print
* an error diagnostic here.
*/
if (s)
printf(s, arg), printf(".\n");
--- 54,65 -----
/*
* A zero arguments causes no printing, else print
* an error diagnostic here.
+ * mg 3-jul-89 : If error is called with s containing a part of
+ * the users input, and if this contains a "%", printf tries to evaluate
+ * this as a format reference. Try : "!a%100s".
+ * I fixed this: internal error messages which should be processed as
+ * format strings, will end in "@", all else is NOT interpreted as a
+ * format string.
*/
if (s) {
i = strlen (s) - 1;
***************
*** 54,61
* A zero arguments causes no printing, else print
* an error diagnostic here.
*/
! if (s)
! printf(s, arg), printf(".\n");
didfds = 0; /* Forget about 0,1,2 */
if ((ep = err) && errspl) {
--- 61,74 -----
* format strings, will end in "@", all else is NOT interpreted as a
* format string.
*/
! if (s) {
! i = strlen (s) - 1;
! if (s[i] == '@') {
! s[i] = '\0';
! printf(s, arg), printf(".\n");
! } else
! printf("%s\n", s);
! }
didfds = 0; /* Forget about 0,1,2 */
if ((ep = err) && errspl) {
*** sh.func.c.old Mon Jul 3 15:18:55 1989
--- sh.func.c Mon Jul 3 15:12:55 1989
***************
*** 1004,1010
while (*cp && *cp == *str)
cp++, str++;
if (*cp)
! error("Bad scaling; did you mean ``%s''?", str0);
}
plim(lp, hard)
--- 1004,1010 -----
while (*cp && *cp == *str)
cp++, str++;
if (*cp)
! error("Bad scaling; did you mean ``%s''?@", str0); /* mg 3-jul-89 */
}
plim(lp, hard)
*** sh.glob.c.old Mon Jul 3 15:19:06 1989
--- sh.glob.c Mon Jul 3 15:13:10 1989
***************
*** 139,145
if (gpathp != gpath + 1) {
*gpathp = 0;
if (gethdir(gpath + 1))
! error("Unknown user: %s", gpath + 1);
(void) strcpy(gpath, gpath + 1);
} else
(void) strcpy(gpath, value("home"));
--- 139,145 -----
if (gpathp != gpath + 1) {
*gpathp = 0;
if (gethdir(gpath + 1))
! error("Unknown user: %s@", gpath + 1); /* mg 3-jul-89 */
(void) strcpy(gpath, gpath + 1);
} else
(void) strcpy(gpath, value("home"));
*** sh.sem.c.old Mon Jul 3 15:19:21 1989
--- sh.sem.c Mon Jul 3 15:13:22 1989
***************
*** 401,405
return;
if ((stb.st_mode & S_IFMT) == S_IFCHR)
return;
! error("%s: File exists", cp);
}
--- 401,405 -----
return;
if ((stb.st_mode & S_IFMT) == S_IFCHR)
return;
! error("%s: File exists@", cp); /* mg 3-jul-89 */
}
--
Michael Greim Email : greim at sbsvax.informatik.uni-saarland.dbp.de
or : ...!uunet!unido!sbsvax!greim
# include <disclaimers/std.h>
More information about the Comp.sources.bugs
mailing list