[PATCH]: allow recursive variable inderection in arith

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello.


My patch for allow recursive variable inderection in arith
and simplify allow $(( )). Originaly from my arith in busybox

Before patch:
$ a=b b=2; echo $((a))
dash: 1: Illegal number: b

After patch:
$ a=b b=2; echo $((a))
2
a=b b="a*2"; echo $((a))
./dash: 4: arithmetic expression: expression recursion loop detected: "a"


--w
vodz
--- arith_yacc.c.orig   2020-12-23 11:58:12.000000000 +0400
+++ arith_yacc.c        2021-01-31 13:19:00.790119536 +0400
@@ -34,6 +34,7 @@

 #include <inttypes.h>
 #include <stdlib.h>
+#include <string.h>
 #include "arith_yacc.h"
 #include "expand.h"
 #include "shell.h"
@@ -134,6 +135,50 @@

 static intmax_t assignment(int var, int noeval);

+typedef struct CHK_VAR_RECURSIVE_LOOPED {
+       const char *name;
+       struct CHK_VAR_RECURSIVE_LOOPED *next;
+} chk_var_recursive_looped_t;
+
+static chk_var_recursive_looped_t *prev_chk_var_recursive;
+
+static intmax_t arith_lookup_val(const char *name)
+{
+       const char * p = lookupvar(name);
+
+       if(p) {
+           intmax_t ret;
+
+           /* recursive try as expression */
+           chk_var_recursive_looped_t *cur;
+           chk_var_recursive_looped_t cur_save;
+           const char *arith_buf_s;
+           int lt;
+
+           for(cur = prev_chk_var_recursive; cur; cur = cur->next) {
+               if(!strcmp(cur->name, name))
+                   yyerror("expression recursion loop detected");
+           }
+           /* save current lookuped var name */
+           cur = prev_chk_var_recursive;
+           cur_save.name = name;
+           cur_save.next = cur;
+           prev_chk_var_recursive = &cur_save;
+
+           arith_buf_s = arith_buf;
+           lt = last_token;
+           ret = arith (p, 1);
+           /* restore previous after recursiving */
+           prev_chk_var_recursive = cur;
+           arith_buf = arith_buf_s;
+           last_token = lt;
+           return ret;
+       } else {
+           /* allow undefined var as 0 */
+           return 0;
+       }
+}
+
 static intmax_t primary(int token, union yystype *val, int op, int noeval)
 {
	intmax_t result;
@@ -151,7 +196,7 @@
		return val->val;
	case ARITH_VAR:
		last_token = op;
-               return noeval ? val->val : lookupvarint(val->name);
+               return noeval ? val->val : arith_lookup_val(val->name);
	case ARITH_ADD:
		token = op;
		*val = yylval;
@@ -286,16 +331,27 @@

	return setvarint(val.name,
			 op == ARITH_ASS ? result :
-                        do_binop(op - 11, lookupvarint(val.name), result), 0);
+                        do_binop(op - 11, arith_lookup_val(val.name), result), 0);
 }

-intmax_t arith(const char *s)
+intmax_t arith(const char *s, int r)
 {
	intmax_t result;
+       int l0;

-       arith_buf = arith_startbuf = s;
+       arith_buf = s;
+       last_token = 0;

-       result = assignment(yylex(), 0);
+       if(!r) {
+               prev_chk_var_recursive = (chk_var_recursive_looped_t *)0;
+               arith_startbuf = s;
+       }
+       l0 = yylex();
+       if (l0 == 0) {
+               /* $(( )) */
+               return 0;
+       }
+       result = assignment(l0, 0);

	if (last_token)
		yyerror("expecting EOF");
--- expand.c.orig       2020-12-23 11:58:12.000000000 +0400
+++ expand.c    2021-01-31 12:39:07.083194412 +0400
@@ -460,7 +460,7 @@
		rmescapes(start);

	pushstackmark(&sm, endoff);
-       result = arith(start);
+       result = arith(start, 0);
	popstackmark(&sm);

	len = cvtnum(result, flag);
--- expand.h.orig       2020-12-23 11:58:12.000000000 +0400
+++ expand.h    2021-01-31 12:39:09.435194338 +0400
@@ -73,7 +73,7 @@
 void ifsfree(void);

 /* From arith.y */
-intmax_t arith(const char *);
+intmax_t arith(const char *, int r);
 int expcmd(int , char **);
 #ifdef USE_LEX
 void arith_lex_reset(void);
--- var.c.orig  2020-12-23 11:58:12.000000000 +0400
+++ var.c       2021-01-31 12:30:38.894210308 +0400
@@ -322,12 +322,6 @@
	return NULL;
 }

-intmax_t lookupvarint(const char *name)
-{
-       return atomax(lookupvar(name) ?: nullstr, 0);
-}
-
-

 /*
--- var.h.orig  2020-12-23 11:58:12.000000000 +0400
+++ var.h       2021-01-31 12:30:45.150210113 +0400
@@ -140,7 +140,6 @@
 struct var *setvareq(char *s, int flags);
 struct strlist;
 char *lookupvar(const char *);
-intmax_t lookupvarint(const char *);
 char **listvars(int, int, char ***);
 #define environment() listvars(VEXPORT, VUNSET, 0)
 int showvars(const char *, int, int);

[Index of Archives]     [LARTC]     [Bugtraq]     [Yosemite Forum]     [Photo]

  Powered by Linux