permit 'read -A/-a arr[idx]' as long as only one element is read;

fix corruption of array indicēs with this construct (LP#1533396)
This commit is contained in:
tg 2016-01-14 22:49:33 +00:00
parent 0141794c2e
commit 1b0e4f54cb
3 changed files with 28 additions and 10 deletions

26
funcs.c
View File

@ -38,7 +38,7 @@
#endif
#endif
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.289 2016/01/13 17:20:49 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.290 2016/01/14 22:49:31 tg Exp $");
#if HAVE_KILLPG
/*
@ -1851,13 +1851,15 @@ c_read(const char **wp)
enum { LINES, BYTES, UPTO, READALL } readmode = LINES;
char delim = '\n';
size_t bytesleft = 128, bytesread;
struct tbl *vp /* FU gcc */ = NULL, *vq;
struct tbl *vp /* FU gcc */ = NULL, *vq = NULL;
char *cp, *allocd = NULL, *xp;
const char *ccp;
XString xs;
size_t xsave = 0;
mksh_ttyst tios;
bool restore_tios = false;
/* to catch read -aN2 foo[i] */
bool subarray = false;
#if HAVE_SELECT
bool hastimeout = false;
struct timeval tv, tvlim;
@ -2102,6 +2104,7 @@ c_read(const char **wp)
XinitN(xs, 128, ATEMP);
if (intoarray) {
vp = global(*wp);
subarray = last_lookup_was_array;
if (vp->flag & RDONLY) {
c_read_splitro:
bi_errorf("read-only: %s", *wp);
@ -2110,10 +2113,10 @@ c_read(const char **wp)
afree(cp, ATEMP);
goto c_read_out;
}
/* exporting an array is currently pointless */
unset(vp, 1);
/* counter for array index */
c = 0;
c = subarray ? arrayindex(vp) : 0;
/* exporting an array is currently pointless */
unset(vp, subarray ? 0 : 1);
}
if (!aschars) {
/* skip initial IFS whitespace */
@ -2215,7 +2218,18 @@ c_read(const char **wp)
c_read_gotword:
Xput(xs, xp, '\0');
if (intoarray) {
vq = arraysearch(vp, c++);
if (subarray) {
/* array element passed, accept first read */
if (vq) {
bi_errorf("nested arrays not yet supported");
goto c_read_spliterr;
}
vq = vp;
if (c)
/* [0] doesn't */
vq->flag |= AINDEX;
} else
vq = arraysearch(vp, c++);
} else {
vq = global(*wp);
/* must be checked before exporting */

6
sh.h
View File

@ -10,7 +10,7 @@
/*-
* Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
* 2011, 2012, 2013, 2014, 2015
* 2011, 2012, 2013, 2014, 2015, 2016
* mirabilos <m@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
@ -175,7 +175,7 @@
#endif
#ifdef EXTERN
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.753 2016/01/13 17:20:52 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.754 2016/01/14 22:49:32 tg Exp $");
#endif
#define MKSH_VERSION "R52 2016/01/13"
@ -1186,6 +1186,8 @@ struct tbl {
};
EXTERN struct tbl vtemp;
/* set by global() and local() */
EXTERN bool last_lookup_was_array;
/* common flag bits */
#define ALLOC BIT(0) /* val.s has been allocated */

6
var.c
View File

@ -28,7 +28,7 @@
#include <sys/sysctl.h>
#endif
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.196 2016/01/14 20:21:39 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.197 2016/01/14 22:49:33 tg Exp $");
/*-
* Variables
@ -295,6 +295,7 @@ global(const char *n)
if (special(vn))
vp->flag |= SPECIAL;
out:
last_lookup_was_array = array;
if (vn != n)
afree(vname.rw, ATEMP);
return (vp);
@ -345,6 +346,7 @@ local(const char *n, bool copy)
if (special(vn))
vp->flag |= SPECIAL;
out:
last_lookup_was_array = array;
if (vn != n)
afree(vname.rw, ATEMP);
return (vp);
@ -1486,7 +1488,7 @@ arrayname(const char *str)
const char *p;
char *rv;
if ((p = cstrchr(str, '[')) == 0)
if (!(p = cstrchr(str, '[')))
/* Shouldn't happen, but why worry? */
strdupx(rv, str, ATEMP);
else