Bug#682992: unblock: mksh/40.9.20120630-2
Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock
Please unblock package mksh
This is a resend of <Pine.BSM.4.64L.1207240952130.30311@herc.mirbsd.org>
as requested in the d-d-a mail of today.
unblock mksh/40.9.20120630-2
Hi,
after getting negative responses, I decided to start a wheezy
maintenance branch and only cherry-pick the important fixes.
The attached diff has been cleaned off "RCS ID" and other
version numbering only noise from comments, and diffs the
patched source + debian/ not the quilt patches, for easier
review.
The package's otherwise in a good shape, built everywhere,
I've been using the new version for a while, etc. (and even
the klibc version is safe, as longjmp is never passed 0).
Changes:
* Fix CONSERVATIVE_FDS: the definition was missing in one
case and silently ignored in another due to use of the
macro before its implicit definition; also add this fact
to the lksh(1) manpage
* Correct a regression wrt. tab completion, at least two
other bugs in the same code, and the same bug class in
similar code (e.g. inline-expansion with Esc+*) that
could lead to unrelated input on the current command
line being overwritten (and sanitise int into size_t,
for 64-bit cleanliness), upstream bug LP#1025843
-- System Information:
Debian Release: wheezy/sid
APT prefers unreleased
APT policy: (500, 'unreleased'), (500, 'unstable')
Architecture: m68k
Kernel: Linux 3.2.0-2-atari
Locale: LANG=C, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/mksh-static
--- mksh-40.9.20120630-1/Build.sh 2012-06-28 20:18:21.000000000 +0000
+++ mksh-40.9.20120630-2/Build.sh 2012-07-24 09:54:20.000000000 +0000
@@ -414,6 +414,7 @@ else
check_categories="$check_categories shell:legacy-yes"
add_cppflags -DMKSH_LEGACY_MODE
HAVE_PERSISTENT_HISTORY=0
+ HAVE_ISSET_MKSH_CONSERVATIVE_FDS=1 # from sh.h
fi
if test x"$srcdir" = x"."; then
--- mksh-40.9.20120630-1/debian/changelog 2012-06-30 17:34:53.000000000 +0000
+++ mksh-40.9.20120630-2/debian/changelog 2012-07-20 23:33:59.000000000 +0000
@@ -1,3 +1,14 @@
+mksh (40.9.20120630-2) unstable; urgency=low
+
+ * The “kutweer” upload
+ * Apply cherry-picked fixes from mksh CVS (branch mksh-wheezy):
+ - [tg] Fix CONSERVATIVE_FDS use-before-definition bug
+ - [tg] Correct a regression when tab-completing (LP#1025843) and fix
+ bugs in the same code wrt. completion display and other expansions
+ * Document use of CONSERVATIVE_FDS in lksh manpage
+
+ -- Thorsten Glaser <tg@mirbsd.de> Fri, 20 Jul 2012 23:32:37 +0000
+
mksh (40.9.20120630-1) unstable; urgency=low
* The “GC2TDN7” upload
--- mksh-40.9.20120630-1/debian/lksh.1 2012-06-30 17:25:00.000000000 +0000
+++ mksh-40.9.20120630-2/debian/lksh.1 2012-07-20 23:34:00.000000000 +0000
@@ -223,6 +223,9 @@ but might work on 32-bit and 64-bit
.Vt long
types
.Pc .
+.It
+.Nm
+only offers the traditional ten file descriptors to scripts.
.El
.Sh SEE ALSO
.Xr mksh 1
@@ -262,4 +265,8 @@ or the
IRC channel at
.Pa irc.freenode.net
.Pq Port 6697 SSL, 6667 unencrypted
-if you need any further quirks.
+if you need any further quirks or assistance,
+and consider migrating your legacy scripts to work with
+.Nm mksh
+instead of requiring
+.Nm .
--- mksh-40.9.20120630-1/edit.c 2012-05-05 17:33:19.000000000 +0000
+++ mksh-40.9.20120630-2/edit.c 2012-07-24 09:54:20.000000000 +0000
@@ -76,6 +76,8 @@ static int x_do_comment(char *, ssize_t,
static void x_print_expansions(int, char *const *, bool);
static int x_cf_glob(int *, const char *, int, int, int *, int *, char ***);
static size_t x_longest_prefix(int, char *const *);
+static void x_glob_hlp_add_qchar(char *);
+static void x_glob_hlp_rem_qchar(char *);
static int x_basename(const char *, const char *);
static void x_free_words(int, char **);
static int x_escape(const char *, size_t, int (*)(const char *, size_t));
@@ -281,50 +283,78 @@ x_print_expansions(int nwords, char * co
XPfree(l);
}
-/**
- * Do file globbing:
- * - appends * to (copy of) str if no globbing chars found
- * - does expansion, checks for no match, etc.
- * - sets *wordsp to array of matching strings
- * - returns number of matching strings
+/*
+ * Convert backslash-escaped string to QCHAR-escaped
+ * string useful for globbing; loses QCHAR unless it
+ * can squeeze in, eg. by previous loss of backslash
*/
-static int
-x_file_glob(int flags MKSH_A_UNUSED, char *toglob, char ***wordsp)
+static void
+x_glob_hlp_add_qchar(char *cp)
{
- char ch, **words;
- int nwords, i = 0, idx = 0;
- bool escaping;
- XPtrV w;
- struct source *s, *sold;
+ char ch, *dp = cp;
+ bool escaping = false;
- /* remove all escaping backward slashes */
- escaping = false;
- while ((ch = toglob[i++])) {
+ while ((ch = *cp++)) {
if (ch == '\\' && !escaping) {
escaping = true;
continue;
}
- if (escaping) {
+ if (escaping || (ch == QCHAR && (cp - dp) > 1)) {
/*
* empirically made list of chars to escape
- * for globbing; ASCII 0x02 probably too as
- * that's what QCHAR is, but...
+ * for globbing as well as QCHAR itself
*/
switch (ch) {
+ case QCHAR:
case '$':
case '*':
case '?':
case '[':
case '\\':
case '`':
- toglob[idx++] = QCHAR;
+ *dp++ = QCHAR;
break;
}
escaping = false;
}
- toglob[idx++] = ch;
+ *dp++ = ch;
}
- toglob[idx] = '\0';
+ *dp = '\0';
+}
+
+/*
+ * Unescape a QCHAR-escaped string
+ */
+static void
+x_glob_hlp_rem_qchar(char *cp)
+{
+ char ch, *dp = cp;
+
+ while ((ch = *cp++)) {
+ if (ch == QCHAR && !(ch = *cp++))
+ break;
+ *dp++ = ch;
+ }
+ *dp = '\0';
+}
+
+/**
+ * Do file globbing:
+ * - appends * to (copy of) str if no globbing chars found
+ * - does expansion, checks for no match, etc.
+ * - sets *wordsp to array of matching strings
+ * - returns number of matching strings
+ */
+static int
+x_file_glob(int flags MKSH_A_UNUSED, char *toglob, char ***wordsp)
+{
+ char **words;
+ int nwords;
+ XPtrV w;
+ struct source *s, *sold;
+
+ /* remove all escaping backward slashes */
+ x_glob_hlp_add_qchar(toglob);
/*
* Convert "foo*" (toglob) to an array of strings (words)
@@ -350,13 +380,7 @@ x_file_glob(int flags MKSH_A_UNUSED, cha
struct stat statb;
/* Drop all QCHAR from toglob for strcmp below */
- i = 0;
- idx = 0;
- while ((ch = toglob[i++])) {
- if (ch != QCHAR)
- toglob[idx++] = ch;
- }
- toglob[idx] = '\0';
+ x_glob_hlp_rem_qchar(toglob);
/*
* Check if globbing failed (returned glob pattern),
@@ -915,9 +939,9 @@ static int holdlen; /* length of holdbu
static bool prompt_redraw; /* false if newline forced after prompt */
static int x_ins(const char *);
-static void x_delete(int, int);
-static int x_bword(void);
-static int x_fword(int);
+static void x_delete(size_t, bool);
+static size_t x_bword(void);
+static size_t x_fword(bool);
static void x_goto(char *);
static void x_bs3(char **);
static int x_size_str(char *);
@@ -949,6 +973,7 @@ static int x_fold_case(int);
#endif
static char *x_lastcp(void);
static void do_complete(int, Comp_type);
+static size_t x_nb2nc(size_t);
static int unget_char = -1;
@@ -1067,6 +1092,17 @@ static struct x_defbindings const x_defb
#endif
};
+static size_t
+x_nb2nc(size_t nb)
+{
+ char *cp;
+ size_t nc = 0;
+
+ for (cp = xcp; cp < (xcp + nb); ++nc)
+ cp += utf_ptradj(cp);
+ return (nc);
+}
+
#ifdef MKSH_SMALL
static void x_modified(void);
static void
@@ -1329,7 +1365,7 @@ x_ins(const char *s)
static int
x_del_back(int c MKSH_A_UNUSED)
{
- int i = 0;
+ ssize_t i = 0;
if (xcp == xbuf) {
x_e_putc2(7);
@@ -1346,7 +1382,7 @@ static int
x_del_char(int c MKSH_A_UNUSED)
{
char *cp, *cp2;
- int i = 0;
+ ssize_t i = 0;
cp = xcp;
while (i < x_arg) {
@@ -1367,9 +1403,9 @@ x_del_char(int c MKSH_A_UNUSED)
/* Delete nc chars to the right of the cursor (including cursor position) */
static void
-x_delete(int nc, int push)
+x_delete(size_t nc, bool push)
{
- int i, nb, nw;
+ size_t i, nb, nw;
char *cp;
if (nc == 0)
@@ -1453,21 +1489,21 @@ x_mv_bword(int c MKSH_A_UNUSED)
static int
x_mv_fword(int c MKSH_A_UNUSED)
{
- x_fword(1);
+ x_fword(true);
return (KSTD);
}
static int
x_del_fword(int c MKSH_A_UNUSED)
{
- x_delete(x_fword(0), true);
+ x_delete(x_fword(false), true);
return (KSTD);
}
-static int
+static size_t
x_bword(void)
{
- int nc = 0, nb = 0;
+ size_t nb = 0;
char *cp = xcp;
if (cp == xbuf) {
@@ -1485,16 +1521,14 @@ x_bword(void)
}
}
x_goto(cp);
- for (cp = xcp; cp < (xcp + nb); ++nc)
- cp += utf_ptradj(cp);
- return (nc);
+ return (x_nb2nc(nb));
}
-static int
-x_fword(int move)
+static size_t
+x_fword(bool move)
{
- int nc = 0;
- char *cp = xcp, *cp2;
+ size_t nc;
+ char *cp = xcp;
if (cp == xep) {
x_e_putc2(7);
@@ -1506,8 +1540,7 @@ x_fword(int move)
while (cp != xep && !is_mfs(*cp))
cp++;
}
- for (cp2 = xcp; cp2 < cp; ++nc)
- cp2 += utf_ptradj(cp2);
+ nc = x_nb2nc(cp - xcp);
if (move)
x_goto(cp);
return (nc);
@@ -2195,20 +2228,18 @@ x_meta2(int c MKSH_A_UNUSED)
static int
x_kill(int c MKSH_A_UNUSED)
{
- int col = xcp - xbuf;
- int lastcol = xep - xbuf;
- int ndel;
-
- if (x_arg_defaulted)
- x_arg = lastcol;
- else if (x_arg > lastcol)
- x_arg = lastcol;
- ndel = x_arg - col;
- if (ndel < 0) {
- x_goto(xbuf + x_arg);
- ndel = -ndel;
- }
- x_delete(ndel, true);
+ size_t col = xcp - xbuf;
+ size_t lastcol = xep - xbuf;
+ size_t ndel, narg;
+
+ if (x_arg_defaulted || (narg = x_arg) > lastcol)
+ narg = lastcol;
+ if (narg < col) {
+ x_goto(xbuf + narg);
+ ndel = col - narg;
+ } else
+ ndel = narg - col;
+ x_delete(x_nb2nc(ndel), true);
return (KSTD);
}
@@ -2256,7 +2287,7 @@ x_meta_yank(int c MKSH_A_UNUSED)
}
len = strlen(killstack[killtp]);
x_goto(xcp - len);
- x_delete(len, false);
+ x_delete(x_nb2nc(len), false);
do {
if (killtp == 0)
killtp = KILLSIZE - 1;
@@ -2576,7 +2607,7 @@ x_set_mark(int c MKSH_A_UNUSED)
static int
x_kill_region(int c MKSH_A_UNUSED)
{
- int rsize;
+ size_t rsize;
char *xr;
if (xmp == NULL) {
@@ -2591,7 +2622,7 @@ x_kill_region(int c MKSH_A_UNUSED)
xr = xmp;
}
x_goto(xr);
- x_delete(rsize, true);
+ x_delete(x_nb2nc(rsize), true);
xmp = xr;
return (KSTD);
}
@@ -2684,7 +2715,7 @@ x_expand(int c MKSH_A_UNUSED)
return (KSTD);
}
x_goto(xbuf + start);
- x_delete(end - start, false);
+ x_delete(x_nb2nc(end - start), false);
i = 0;
while (i < nwords) {
@@ -2708,7 +2739,7 @@ do_complete(
{
char **words;
int start, end, nlen, olen, nwords;
- bool completed = false;
+ bool completed;
nwords = x_cf_glob(&flags, xbuf, xep - xbuf, xcp - xbuf,
&start, &end, &words);
@@ -2726,14 +2757,47 @@ do_complete(
}
olen = end - start;
nlen = x_longest_prefix(nwords, words);
- /* always complete */
- x_goto(xbuf + start);
- x_delete(olen, false);
- x_escape(words[0], nlen, x_do_ins);
- x_adjust();
- /* check if we did add something */
- if (xcp - (xbuf + start) > olen)
+ if (nwords == 1 || (flags & XCF_IS_SUBGLOB)) {
+ /*
+ * always complete the expansion of parameter and
+ * homedir substitution as well as single matches
+ */
completed = true;
+ } else {
+ char *unescaped;
+
+ /* make a copy of the original string part and... */
+ strndupx(unescaped, xbuf + start, olen, ATEMP);
+ /* ... convert it from backslash-escaped via QCHAR-escaped... */
+ x_glob_hlp_add_qchar(unescaped);
+ /* ... to unescaped, for comparison with the matches */
+ x_glob_hlp_rem_qchar(unescaped);
+ /*
+ * match iff entire original string is part of the
+ * longest prefix, implying the latter is at least
+ * the same size (after unescaping)
+ */
+ completed = !strncmp(words[0], unescaped, strlen(unescaped));
+
+ afree(unescaped, ATEMP);
+ }
+ if (type == CT_COMPLIST && nwords > 1) {
+ /*
+ * print expansions, since we didn't get back
+ * just a single match
+ */
+ x_print_expansions(nwords, words,
+ tobool(flags & XCF_IS_COMMAND));
+ }
+ if (completed) {
+ /* expand on the command line */
+ xmp = NULL;
+ xcp = xbuf + start;
+ xep -= olen;
+ memmove(xcp, xcp + olen, xep - xcp + 1);
+ x_escape(words[0], nlen, x_do_ins);
+ }
+ x_adjust();
/*
* append a space if this is a single non-directory match
* and not a parameter or homedir substitution
@@ -2741,15 +2805,7 @@ do_complete(
if (nwords == 1 && words[0][nlen - 1] != '/' &&
!(flags & XCF_IS_SUBGLOB)) {
x_ins(" ");
- completed = true;
}
- if (type == CT_COMPLIST && !completed) {
- x_print_expansions(nwords, words,
- tobool(flags & XCF_IS_COMMAND));
- completed = true;
- }
- if (completed)
- x_redraw(0);
x_free_words(nwords, words);
}
--- mksh-40.9.20120630-1/sh.h 2012-06-28 20:18:25.000000000 +0000
+++ mksh-40.9.20120630-2/sh.h 2012-07-24 09:54:20.000000000 +0000
@@ -412,15 +412,6 @@ extern int wcwidth(__WCHAR_TYPE__);
#define BIT(i) (1 << (i))
#define NELEM(a) (sizeof(a) / sizeof((a)[0]))
-/* these shall be smaller than 100 */
-#ifdef MKSH_CONSERVATIVE_FDS
-#define NUFILE 32 /* Number of user-accessible files */
-#define FDBASE 10 /* First file usable by Shell */
-#else
-#define NUFILE 56 /* Number of user-accessible files */
-#define FDBASE 24 /* First file usable by Shell */
-#endif
-
/*
* Make MAGIC a char that might be printed to make bugs more obvious, but
* not a char that is used often. Also, can't use the high bit as it causes
@@ -545,6 +536,9 @@ im_sorry_dave(void)
#ifndef MKSH_NO_CMDLINE_EDITING
#define MKSH_NO_CMDLINE_EDITING /* defined */
#endif
+#ifndef MKSH_CONSERVATIVE_FDS
+#define MKSH_CONSERVATIVE_FDS /* defined */
+#endif
#undef MKSH_S_NOVI
#define MKSH_S_NOVI 1
#endif
@@ -569,6 +563,15 @@ im_sorry_dave(void)
#define MKSH_UNEMPLOYED 1
#endif
+/* these shall be smaller than 100 */
+#ifdef MKSH_CONSERVATIVE_FDS
+#define NUFILE 32 /* Number of user-accessible files */
+#define FDBASE 10 /* First file usable by Shell */
+#else
+#define NUFILE 56 /* Number of user-accessible files */
+#define FDBASE 24 /* First file usable by Shell */
+#endif
+
/*
* simple grouping allocator
*/
Reply to: