From a293092af78fce508f4d82debb461c7e4eefcadb Mon Sep 17 00:00:00 2001 From: Krush206 <37114863+Krush206@users.noreply.github.com> Date: Thu, 2 May 2024 12:18:33 -0300 Subject: [PATCH 1/8] Character encoding portability for expressions --- sh.set.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/sh.set.c b/sh.set.c index ac73af9f..5783a3ff 100644 --- a/sh.set.c +++ b/sh.set.c @@ -529,16 +529,26 @@ putn(tcsh_number_t n) *putp++ = '-'; } putn1(n); +#ifdef IS_ASCII *putp = 0; +#endif return (Strsave(nbuf)); } static void putn1(tcsh_number_t n) { +#ifndef IS_ASCII + sprintf(putp, "%l" +#ifdef HAVE_LONG_LONG + "l" +#endif /* HAVE_LONG_LONG */ + "u", &n); +#else if (n > 9) putn1(n / 10); *putp++ = (Char)(n % 10 + '0'); +#endif /* !IS_ASCII */ } tcsh_number_t @@ -547,6 +557,9 @@ getn(const Char *cp) tcsh_number_t n; int sign; int base; +#ifndef IS_ASCII + char cps[2]; +#endif if (!cp) /* PWP: extra error checking */ stderror(ERR_NAME | ERR_BADNUM); @@ -566,12 +579,29 @@ getn(const Char *cp) else base = 10; +#ifndef IS_ASCII + cps[1] = +#endif n = 0; while (Isdigit(*cp)) { +#ifndef IS_ASCII + unsigned tcsh_number_t ns; +#endif + if (base == 8 && *cp >= '8') stderror(ERR_NAME | ERR_BADNUM); +#ifndef IS_ASCII + cps[0] = *cp++; + sscanf(cps, "%l" +#ifdef HAVE_LONG_LONG + "l" +#endif /* HAVE_LONG_LONG */ + "u", &ns); + n = n * base + ns; +#else n = n * base + *cp++ - '0'; +#endif /* !IS_ASCII */ } if (*cp) stderror(ERR_NAME | ERR_BADNUM); From 58117f84c9fd7903050349fb1b560fa0dd0d68c1 Mon Sep 17 00:00:00 2001 From: Krush206 <37114863+Krush206@users.noreply.github.com> Date: Thu, 2 May 2024 10:27:56 -0300 Subject: [PATCH 2/8] Signed overflow fix for expressions --- sh.decls.h | 4 ++-- sh.exp.c | 38 +++++++++++++++++++------------------- sh.h | 4 ++-- sh.set.c | 12 ++++++------ 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/sh.decls.h b/sh.decls.h index a863fede..90af8d93 100644 --- a/sh.decls.h +++ b/sh.decls.h @@ -379,8 +379,8 @@ extern void mypipe (int *); extern struct varent *adrof1 (const Char *, struct varent *); extern void doset (Char **, struct command *); extern void dolet (Char **, struct command *); -extern Char *putn (tcsh_number_t); -extern tcsh_number_t getn (const Char *); +extern Char *putn (unsigned tcsh_number_t); +extern unsigned tcsh_number_t getn (const Char *); extern Char *value1 (Char *, struct varent *); extern void setcopy (const Char *, const Char *, int); extern void setv (const Char *, Char *, int); diff --git a/sh.exp.c b/sh.exp.c index f291a59d..837e8ccf 100644 --- a/sh.exp.c +++ b/sh.exp.c @@ -63,7 +63,7 @@ static Char *exp5 (Char ***, int); static Char *exp6 (Char ***, int); static void evalav (Char **); static int isa (Char *, int); -static tcsh_number_t egetn (const Char *); +static unsigned tcsh_number_t egetn (const Char *); #ifdef EDEBUG static void etracc (const char *, const Char *, Char ***); @@ -186,11 +186,11 @@ expr(Char ***vp) tcsh_number_t exp0(Char ***vp, int ignore) { - tcsh_number_t p1 = exp1(vp, ignore); + unsigned tcsh_number_t p1 = exp1(vp, ignore); etraci("exp0 p1", p1, vp); while (**vp && eq(**vp, STRor2)) { - int p2; + unsigned tcsh_number_t p2; (*vp)++; @@ -209,11 +209,11 @@ exp0(Char ***vp, int ignore) static tcsh_number_t exp1(Char ***vp, int ignore) { - tcsh_number_t p1 = exp2x(vp, ignore); + unsigned tcsh_number_t p1 = exp2x(vp, ignore); etraci("exp1 p1", p1, vp); while (**vp && eq(**vp, STRand2)) { - tcsh_number_t p2; + unsigned tcsh_number_t p2; (*vp)++; p2 = compat_expr ? @@ -233,11 +233,11 @@ exp1(Char ***vp, int ignore) static tcsh_number_t exp2x(Char ***vp, int ignore) { - tcsh_number_t p1 = exp2a(vp, ignore); + unsigned tcsh_number_t p1 = exp2a(vp, ignore); etraci("exp2x p1", p1, vp); while (**vp && eq(**vp, STRor)) { - tcsh_number_t p2; + unsigned tcsh_number_t p2; (*vp)++; p2 = compat_expr ? @@ -256,11 +256,11 @@ exp2x(Char ***vp, int ignore) static tcsh_number_t exp2a(Char ***vp, int ignore) { - tcsh_number_t p1 = exp2b(vp, ignore); + unsigned tcsh_number_t p1 = exp2b(vp, ignore); etraci("exp2a p1", p1, vp); while (**vp && eq(**vp, STRcaret)) { - tcsh_number_t p2; + unsigned tcsh_number_t p2; (*vp)++; p2 = compat_expr ? @@ -279,11 +279,11 @@ exp2a(Char ***vp, int ignore) static tcsh_number_t exp2b(Char ***vp, int ignore) { - tcsh_number_t p1 = exp2c(vp, ignore); + unsigned tcsh_number_t p1 = exp2c(vp, ignore); etraci("exp2b p1", p1, vp); while (**vp && eq(**vp, STRand)) { - tcsh_number_t p2; + unsigned tcsh_number_t p2; (*vp)++; p2 = compat_expr ? @@ -304,7 +304,7 @@ exp2c(Char ***vp, int ignore) { Char *p1 = exp3(vp, ignore); Char *p2; - tcsh_number_t i; + unsigned tcsh_number_t i; cleanup_push(p1, xfree); etracc("exp2c p1", p1, vp); @@ -346,7 +346,7 @@ static Char * exp3(Char ***vp, int ignore) { Char *p1, *p2; - tcsh_number_t i; + unsigned tcsh_number_t i; p1 = exp3a(vp, ignore); etracc("exp3 p1", p1, vp); @@ -393,7 +393,7 @@ exp3a(Char ***vp, int ignore) { Char *p1, *p2; const Char *op; - tcsh_number_t i; + unsigned tcsh_number_t i; p1 = exp4(vp, ignore); etracc("exp3a p1", p1, vp); @@ -421,7 +421,7 @@ static Char * exp4(Char ***vp, int ignore) { Char *p1, *p2; - tcsh_number_t i = 0; + unsigned tcsh_number_t i = 0; p1 = exp5(vp, ignore); etracc("exp4 p1", p1, vp); @@ -458,7 +458,7 @@ static Char * exp5(Char ***vp, int ignore) { Char *p1, *p2; - tcsh_number_t i = 0; + unsigned tcsh_number_t i = 0; p1 = exp6(vp, ignore); etracc("exp5 p1", p1, vp); @@ -513,8 +513,8 @@ exp5(Char ***vp, int ignore) static Char * exp6(Char ***vp, int ignore) { - tcsh_number_t ccode; - tcsh_number_t i = 0; + unsigned tcsh_number_t ccode, + i = 0; Char *cp; if (**vp == 0) @@ -1022,7 +1022,7 @@ isa(Char *cp, int what) return (0); } -static tcsh_number_t +static unsigned tcsh_number_t egetn(const Char *cp) { if (*cp && *cp != '-' && !Isdigit(*cp)) diff --git a/sh.h b/sh.h index 19bf10d6..6fcaa8d2 100644 --- a/sh.h +++ b/sh.h @@ -246,9 +246,9 @@ static __inline void tcsh_ignore(intptr_t a) #endif /* __HP_CXD_SPP && !__hpux */ #ifdef HAVE_LONG_LONG -typedef long long tcsh_number_t; +#define tcsh_number_t long long #else -typedef long tcsh_number_t; +#define tcsh_number_t long #endif /* * This macro compares the st_dev field of struct stat. On aix on ibmESA diff --git a/sh.set.c b/sh.set.c index 5783a3ff..f10e255d 100644 --- a/sh.set.c +++ b/sh.set.c @@ -46,7 +46,7 @@ static void asx (Char *, int, Char *); static struct varent *getvx (Char *, int); static Char *xset (Char *, Char ***); static Char *operate (int, Char *, Char *); -static void putn1 (tcsh_number_t); +static void putn1 (unsigned tcsh_number_t); static struct varent *madrof (Char *, struct varent *); static void unsetv1 (struct varent *); static void exportpath (Char **); @@ -519,12 +519,12 @@ operate(int op, Char *vp, Char *p) static Char *putp; Char * -putn(tcsh_number_t n) +putn(unsigned tcsh_number_t n) { Char nbuf[1024]; /* Enough even for octal */ putp = nbuf; - if (n < 0) { + if (n & ~(~(unsigned tcsh_number_t) 0 >> 1)) { n = -n; *putp++ = '-'; } @@ -536,7 +536,7 @@ putn(tcsh_number_t n) } static void -putn1(tcsh_number_t n) +putn1(unsigned tcsh_number_t n) { #ifndef IS_ASCII sprintf(putp, "%l" @@ -551,10 +551,10 @@ putn1(tcsh_number_t n) #endif /* !IS_ASCII */ } -tcsh_number_t +unsigned tcsh_number_t getn(const Char *cp) { - tcsh_number_t n; + unsigned tcsh_number_t n; int sign; int base; #ifndef IS_ASCII From 0c03792294165354953b2c732ea94dd1f425610c Mon Sep 17 00:00:00 2001 From: Krush206 <37114863+Krush206@users.noreply.github.com> Date: Thu, 2 May 2024 13:30:16 -0300 Subject: [PATCH 3/8] sh.set.c: incorrect expression --- sh.set.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sh.set.c b/sh.set.c index f10e255d..4da1897f 100644 --- a/sh.set.c +++ b/sh.set.c @@ -543,7 +543,7 @@ putn1(unsigned tcsh_number_t n) #ifdef HAVE_LONG_LONG "l" #endif /* HAVE_LONG_LONG */ - "u", &n); + "u", n); #else if (n > 9) putn1(n / 10); From e55387e5d83073905a1f4b83675245df07719f70 Mon Sep 17 00:00:00 2001 From: Krush206 <37114863+Krush206@users.noreply.github.com> Date: Thu, 2 May 2024 18:28:39 -0300 Subject: [PATCH 4/8] Type every related part as unsigned --- sh.decls.h | 6 +++--- sh.exp.c | 24 ++++++++++++------------ sh.set.c | 6 +++--- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/sh.decls.h b/sh.decls.h index 90af8d93..395f5e7b 100644 --- a/sh.decls.h +++ b/sh.decls.h @@ -126,8 +126,8 @@ extern int find_cmd (Char *, int); * sh.exp.c */ extern Char *filetest (Char *, Char ***, int); -extern tcsh_number_t expr (Char ***); -extern tcsh_number_t exp0 (Char ***, int); +extern unsigned tcsh_number_t expr (Char ***); +extern unsigned tcsh_number_t exp0 (Char ***, int); /* * sh.file.c @@ -380,7 +380,7 @@ extern struct varent *adrof1 (const Char *, struct varent *); extern void doset (Char **, struct command *); extern void dolet (Char **, struct command *); extern Char *putn (unsigned tcsh_number_t); -extern unsigned tcsh_number_t getn (const Char *); +extern unsigned tcsh_number_t getn (const Char *); extern Char *value1 (Char *, struct varent *); extern void setcopy (const Char *, const Char *, int); extern void setv (const Char *, Char *, int); diff --git a/sh.exp.c b/sh.exp.c index 837e8ccf..a92c4c62 100644 --- a/sh.exp.c +++ b/sh.exp.c @@ -51,11 +51,11 @@ #define NOTEQMATCH 8 static int sh_access (const Char *, int); -static tcsh_number_t exp1 (Char ***, int); -static tcsh_number_t exp2x (Char ***, int); -static tcsh_number_t exp2a (Char ***, int); -static tcsh_number_t exp2b (Char ***, int); -static tcsh_number_t exp2c (Char ***, int); +static unsigned tcsh_number_t exp1 (Char ***, int); +static unsigned tcsh_number_t exp2x (Char ***, int); +static unsigned tcsh_number_t exp2a (Char ***, int); +static unsigned tcsh_number_t exp2b (Char ***, int); +static unsigned tcsh_number_t exp2c (Char ***, int); static Char *exp3 (Char ***, int); static Char *exp3a (Char ***, int); static Char *exp4 (Char ***, int); @@ -177,13 +177,13 @@ sh_access(const Char *fname, int mode) #endif /* !POSIX */ } -tcsh_number_t +unsigned tcsh_number_t expr(Char ***vp) { return (exp0(vp, 0)); } -tcsh_number_t +unsigned tcsh_number_t exp0(Char ***vp, int ignore) { unsigned tcsh_number_t p1 = exp1(vp, ignore); @@ -206,7 +206,7 @@ exp0(Char ***vp, int ignore) return (p1); } -static tcsh_number_t +static unsigned tcsh_number_t exp1(Char ***vp, int ignore) { unsigned tcsh_number_t p1 = exp2x(vp, ignore); @@ -230,7 +230,7 @@ exp1(Char ***vp, int ignore) return (p1); } -static tcsh_number_t +static unsigned tcsh_number_t exp2x(Char ***vp, int ignore) { unsigned tcsh_number_t p1 = exp2a(vp, ignore); @@ -253,7 +253,7 @@ exp2x(Char ***vp, int ignore) return (p1); } -static tcsh_number_t +static unsigned tcsh_number_t exp2a(Char ***vp, int ignore) { unsigned tcsh_number_t p1 = exp2b(vp, ignore); @@ -276,7 +276,7 @@ exp2a(Char ***vp, int ignore) return (p1); } -static tcsh_number_t +static unsigned tcsh_number_t exp2b(Char ***vp, int ignore) { unsigned tcsh_number_t p1 = exp2c(vp, ignore); @@ -299,7 +299,7 @@ exp2b(Char ***vp, int ignore) return (p1); } -static tcsh_number_t +static unsigned tcsh_number_t exp2c(Char ***vp, int ignore) { Char *p1 = exp3(vp, ignore); diff --git a/sh.set.c b/sh.set.c index 4da1897f..1e541ca1 100644 --- a/sh.set.c +++ b/sh.set.c @@ -45,7 +45,7 @@ static Char *getinx (Char *, int *); static void asx (Char *, int, Char *); static struct varent *getvx (Char *, int); static Char *xset (Char *, Char ***); -static Char *operate (int, Char *, Char *); +static Char *operate (Char, Char *, Char *); static void putn1 (unsigned tcsh_number_t); static struct varent *madrof (Char *, struct varent *); static void unsetv1 (struct varent *); @@ -491,13 +491,13 @@ xset(Char *cp, Char ***vp) } static Char * -operate(int op, Char *vp, Char *p) +operate(Char op, Char *vp, Char *p) { Char opr[2]; Char *vec[5]; Char **v = vec; Char **vecp = v; - tcsh_number_t i; + unsigned tcsh_number_t i; if (op != '=') { if (*vp) From 5debfdb4b9998851036ccb59a78491446ed4c333 Mon Sep 17 00:00:00 2001 From: Krush206 <37114863+Krush206@users.noreply.github.com> Date: Thu, 2 May 2024 21:24:35 -0300 Subject: [PATCH 5/8] sh.exp.c: fix relational operators --- sh.exp.c | 45 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/sh.exp.c b/sh.exp.c index a92c4c62..2f7a2985 100644 --- a/sh.exp.c +++ b/sh.exp.c @@ -362,21 +362,58 @@ exp3(Char ***vp, int ignore) etracc("exp3 p2", p2, vp); if (!(ignore & TEXP_IGNORE)) switch ((int)i) { + tcsh_number_t is; case GTR: - i = egetn(p1) > egetn(p2); + if ((i = egetn(p1)) & + ~(~(unsigned tcsh_number_t) 0 >> 1)) + is = -(tcsh_number_t) -i; + else + is = i; + if ((i = egetn(p2)) & + ~(~(unsigned tcsh_number_t) 0 >> 1)) + i = is > -(tcsh_number_t) -i; + else + i = is > (tcsh_number_t) i; break; case GTR | 1: - i = egetn(p1) >= egetn(p2); + if ((i = egetn(p1)) & + ~(~(unsigned tcsh_number_t) 0 >> 1)) + is = -(tcsh_number_t) -i; + else + is = i; + if ((i = egetn(p2)) & + ~(~(unsigned tcsh_number_t) 0 >> 1)) + i = is >= -(tcsh_number_t) -i; + else + i = is >= (tcsh_number_t) i; break; case LSS: - i = egetn(p1) < egetn(p2); + if ((i = egetn(p1)) & + ~(~(unsigned tcsh_number_t) 0 >> 1)) + is = -(tcsh_number_t) -i; + else + is = i; + if ((i = egetn(p2)) & + ~(~(unsigned tcsh_number_t) 0 >> 1)) + i = is < -(tcsh_number_t) -i; + else + i = is < (tcsh_number_t) i; break; case LSS | 1: - i = egetn(p1) <= egetn(p2); + if ((i = egetn(p1)) & + ~(~(unsigned tcsh_number_t) 0 >> 1)) + is = -(tcsh_number_t) -i; + else + is = i; + if ((i = egetn(p2)) & + ~(~(unsigned tcsh_number_t) 0 >> 1)) + i = is <= -(tcsh_number_t) -i; + else + i = is <= (tcsh_number_t) i; break; } cleanup_until(p1); From 30490133494f78e23524b978446732122b63ff12 Mon Sep 17 00:00:00 2001 From: Krush206 <37114863+Krush206@users.noreply.github.com> Date: Fri, 3 May 2024 12:02:07 -0300 Subject: [PATCH 6/8] sh.func.c: fix if expressions --- sh.func.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sh.func.c b/sh.func.c index a9c0dd6f..342f5c1c 100644 --- a/sh.func.c +++ b/sh.func.c @@ -350,7 +350,7 @@ islogin(void) void doif(Char **v, struct command *kp) { - int i; + unsigned tcsh_number_t i; Char **vv; v++; From b1ed7a980f068afec0328f54691d20f338eb0f41 Mon Sep 17 00:00:00 2001 From: Krush206 <37114863+Krush206@users.noreply.github.com> Date: Fri, 3 May 2024 19:42:54 -0300 Subject: [PATCH 7/8] sh.func.c: fix while expressions --- sh.func.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sh.func.c b/sh.func.c index 342f5c1c..9027ddb6 100644 --- a/sh.func.c +++ b/sh.func.c @@ -558,7 +558,7 @@ doforeach(Char **v, struct command *c) void dowhile(Char **v, struct command *c) { - int status; + unsigned tcsh_number_t status; int again = whyles != 0 && SEEKEQ(&whyles->w_start, &lineloc) && whyles->w_fename == 0; From 8132069727fe95fdd7c2c943ffc16ef4463864c5 Mon Sep 17 00:00:00 2001 From: Krush206 <37114863+Krush206@users.noreply.github.com> Date: Fri, 3 May 2024 22:29:40 -0300 Subject: [PATCH 8/8] sh.set.c: fix division and mod --- sh.err.c | 7 +++++-- sh.exp.c | 33 +++++++++++++++++++++++++++------ 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/sh.err.c b/sh.err.c index 9d9600ae..1ed53200 100644 --- a/sh.err.c +++ b/sh.err.c @@ -188,7 +188,9 @@ extern int enterhist; #define ERR_BADCOLORVAR 134 #define ERR_EOF 135 #define ERR_UNAVAILABLE 136 -#define NO_ERRORS 137 +#define ERR_DIVOF 137 +#define ERR_MODOF 138 +#define NO_ERRORS 139 static const char *elst[NO_ERRORS] INIT_ZERO_STRUCT; @@ -367,7 +369,8 @@ errinit(void) elst[ERR_BADCOLORVAR] = CSAVS(1, 137, "Unknown %s color variable '%c%c'"); elst[ERR_EOF] = CSAVS(1, 138, "Unexpected end of file"); elst[ERR_UNAVAILABLE] = CSAVS(1, 139, "%s: Feature is not available for this platform"); - + elst[ERR_DIVOF] = CSAVS(1, 140, "Division overflow"); + elst[ERR_MODOF] = CSAVS(1, 141, "Mod overflow"); } /* Cleanup data. */ diff --git a/sh.exp.c b/sh.exp.c index 2f7a2985..925f776f 100644 --- a/sh.exp.c +++ b/sh.exp.c @@ -519,23 +519,44 @@ exp5(Char ***vp, int ignore) etracc("exp5 p2", p2, vp); if (!(ignore & TEXP_IGNORE)) switch (op[0]) { + tcsh_number_t is; case '*': i = egetn(p1) * egetn(p2); break; case '/': - i = egetn(p2); - if (i == 0) + if ((i = egetn(p2)) == 0) stderror(ERR_DIV0); - i = egetn(p1) / i; + if (i & ~(~(unsigned tcsh_number_t) 0 >> 1)) + is = -(tcsh_number_t) -i; + else + is = i; + if ((i = egetn(p1)) == + ~(~(unsigned tcsh_number_t) 0 >> 1) && + is == -1) + stderror(ERR_DIVOF); + if (i & ~(~(unsigned tcsh_number_t) 0 >> 1)) + i = -(tcsh_number_t) -i / is; + else + i /= is; break; case '%': - i = egetn(p2); - if (i == 0) + if ((i = egetn(p2)) == 0) stderror(ERR_MOD0); - i = egetn(p1) % i; + if (i & ~(~(unsigned tcsh_number_t) 0 >> 1)) + is = -(tcsh_number_t) -i; + else + is = i; + if ((i = egetn(p1)) == + ~(~(unsigned tcsh_number_t) 0 >> 1) && + is == -1) + stderror(ERR_MODOF); + if (i & ~(~(unsigned tcsh_number_t) 0 >> 1)) + i = -(tcsh_number_t) -i % is; + else + i %= is; break; } cleanup_until(p1);