diff --git a/src/cmd/ksh93/sh/arith.c b/src/cmd/ksh93/sh/arith.c --- a/src/cmd/ksh93/sh/arith.c +++ b/src/cmd/ksh93/sh/arith.c @@ -513,21 +513,34 @@ Sfdouble_t sh_strnum(register const char *str, char** ptr, int mode) char base=(shp->inarith?0:10), *last; if(*str==0) { - if(ptr) - *ptr = (char*)str; - return(0); - } - errno = 0; - d = strtonll(str,&last,&base,-1); - if(*last || errno) - { - if(!last || *last!='.' || last[1]!='.') - d = strval(shp,str,&last,arith,mode); - if(!ptr && *last && mode>0) - errormsg(SH_DICT,ERROR_exit(1),e_lexbadchar,*last,str); + d = 0.0; + last = (char*)str; + } else { + errno = 0; + d = strtonll(str,&last,&base,-1); + if (*last && !shp->inarith && sh_isstate(SH_INIT)) { + // This call is to handle "base#value" literals if we're importing untrusted env vars. + errno = 0; + d = strtonll(str, &last, NULL, -1); + } + + if(*last || errno) + { + if (sh_isstate(SH_INIT)) { + // Initializing means importing untrusted env vars. Since the string does not appear + // to be a recognized numeric literal give up. We can't safely call strval() since + // that allows arbitrary expressions which would create a security vulnerability. + d = 0.0; + } else { + if(!last || *last!='.' || last[1]!='.') + d = strval(shp,str,&last,arith,mode); + if(!ptr && *last && mode>0) + errormsg(SH_DICT,ERROR_exit(1),e_lexbadchar,*last,str); + } + } else if (!d && *str=='-') { + d = -0.0; + } } - else if (!d && *str=='-') - d = -0.0; if(ptr) *ptr = last; return(d);