CVE-2020-22873: Buffer Copy without Checking Size of Input ('Classic Buffer Overflow') (CWE-120)
value: Buffer overflow vulnerability in function NumberToPrecisionCmd in jsish before 3.0.7, allows remote attackers to execute arbitrary code.
CWE description: The product copies an input buffer to an output buffer without verifying that the size of the input buffer is less than the size of the output buffer, leading to a buffer overflow.
CVSS v3 base score: 9.8
Published: 2021-07-13T15:15Z
Repository: https://github.com/pcmacdon/jsish
Language: C
Files changed: src/jsi.h, src/jsiCmds.c, src/jsiCode.c, src/jsiEval.c, src/jsiFilesys.c, src/jsiFunc.c, src/jsiHash.c, src/jsiInterp.c, src/jsiJSON.c, src/jsiMySql.c, src/jsiNumber.c, src/jsiOptions.c, src/jsiPstate.c, src/jsiRegexp.c, src/jsiSqlite.c, src/jsiString.c, src/jsiTree.c, src/jsiUtils.c, src/jsiValue.c, src/jsiWebSocket.c
Commit date: 2020-04-13 19:04:14 +0000
Commit message: Release "3.0.7": Fix toPrecision bug "stack overflow #4".

FossilOrigin-Name: 6c7f0c37027d7f890b57cb38f776af39b8f81f03e60ceeb0a231a1d21e24b5de
Diff: diff --git a/src/jsi.h b/src/jsi.h
index 19b4d59..ba55da4 100644
--- a/src/jsi.h
+++ b/src/jsi.h
@@ -2,11 +2,11 @@
 #ifndef __JSI_H__
 #define __JSI_H__
 
 #define JSI_VERSION_MAJOR   3
 #define JSI_VERSION_MINOR   0
-#define JSI_VERSION_RELEASE 6
+#define JSI_VERSION_RELEASE 7
 
 #define JSI_VERSION (JSI_VERSION_MAJOR + ((Jsi_Number)JSI_VERSION_MINOR/100.0) + ((Jsi_Number)JSI_VERSION_RELEASE/10000.0))
 
 #ifndef JSI_EXTERN
 #define JSI_EXTERN extern
@@ -211,11 +211,11 @@ typedef enum {
     JSI_DBI_READONLY     =0x0001, /* Db is created readonly */
     JSI_DBI_NOCREATE     =0x0002, /* Db must already exist. */
     JSI_DBI_NO_MUTEX     =0x0004, /* Disable mutex. */
     JSI_DBI_FULL_MUTEX   =0x0008, /* Use full mutex. */
     
-    JSI_MAX_NUMBER_STRING=50,
+    JSI_MAX_NUMBER_STRING=100,
     JSI_BUFSIZ=8192
 
 } Jsi_Enums; /* Debugging is easier with enums than #define. */
 
 /* -- */
diff --git a/src/jsiCmds.c b/src/jsiCmds.c
index e61d25a..e2565f9 100644
--- a/src/jsiCmds.c
+++ b/src/jsiCmds.c
@@ -843,11 +843,11 @@ Jsi_RC jsi_PkgDumpInfo(Jsi_Interp *interp, const char *name, Jsi_Value **ret) {
         Jsi_Obj *nobj = Jsi_ObjNew(interp);
         Jsi_ValueMakeObject(interp, ret, nobj);
         Jsi_ObjInsert(interp, nobj, "name", Jsi_ValueNewStringDup(interp, name), 0);
         Jsi_ObjInsert(interp, nobj, "version", Jsi_ValueNewNumber(interp, ptr->version), 0);
         Jsi_ObjInsert(interp, nobj, "lastReq", Jsi_ValueNewNumber(interp, ptr->lastReq), 0);
-        char buf[200];
+        char buf[JSI_MAX_NUMBER_STRING*2];
         jsi_VersionNormalize(ptr->version, buf, sizeof(buf));
         Jsi_ObjInsert(interp, nobj, "verStr", Jsi_ValueNewStringDup(interp, buf), 0);
         const char *cp = (ptr->loadFile?ptr->loadFile:"");
         Jsi_ObjInsert(interp, nobj, "loadFile", Jsi_ValueNewStringDup(interp, cp), 0);
         Jsi_Value *fval2, *fval = Jsi_NameLookup(interp, name);
@@ -1190,11 +1190,11 @@ static Jsi_RC SysGetEnvCmd(Jsi_Interp *interp, Jsi_Value *args, Jsi_Value *_this
     }
    /* Single object containing result members. */
     Jsi_Value *vres;
     Jsi_Obj  *ores = Jsi_ObjNew(interp);
     Jsi_Value *nnv;
-    char *val, nam[200];
+    char *val, nam[JSI_BUFSIZ/2];
     //Jsi_ObjIncrRefCount(interp, ores);
     vres = Jsi_ValueMakeObject(interp, NULL, ores);
     //Jsi_IncrRefCount(interp, vres);
     
     for (i=0; ; i++) {
@@ -2698,11 +2698,11 @@ static Jsi_RC DebugAddCmd(Jsi_Interp *interp, Jsi_Value *args, Jsi_Value *_this,
             bp.func = Jsi_KeyAdd(interp, val);
         }
     }
     if (bp.line<=0 && !bp.func) 
         return Jsi_LogError("bad number");
-    char nbuf[100];
+    char nbuf[JSI_MAX_NUMBER_STRING];
     bp.id = ++interp->debugOpts.breakIdx;
     bp.enabled = 1;
     snprintf(nbuf, sizeof(nbuf), "%d", bp.id);
     bptr = (jsi_BreakPoint*)Jsi_Malloc(sizeof(*bptr));
     *bptr = bp;
@@ -2716,11 +2716,11 @@ static Jsi_RC DebugRemoveCmd_(Jsi_Interp *interp, Jsi_Value *args, Jsi_Value *_t
 {
     Jsi_Value *val = Jsi_ValueArrayIndex(interp, args, 0);
     if (interp->breakpointHash)
     {
         int num;
-        char nbuf[100];
+        char nbuf[JSI_MAX_NUMBER_STRING];
         if (Jsi_GetIntFromValue(interp, val, &num) != JSI_OK) 
             return Jsi_LogError("bad number");
         
         snprintf(nbuf, sizeof(nbuf), "%d", num);
         Jsi_HashEntry *hPtr = Jsi_HashEntryFind(interp->breakpointHash, nbuf);
@@ -2764,11 +2764,11 @@ static Jsi_RC DebugInfoCmd(Jsi_Interp *interp, Jsi_Value *args, Jsi_Value *_this
     int argc = Jsi_ValueGetLength(interp, args);
     if (argc == 0)
         return Jsi_HashKeysDump(interp, interp->breakpointHash, ret, 0);
     Jsi_Value *val = Jsi_ValueArrayIndex(interp, args, 0);
     int num;
-    char nbuf[100];
+    char nbuf[JSI_MAX_NUMBER_STRING];
     if (Jsi_GetIntFromValue(interp, val, &num) != JSI_OK) 
         return Jsi_LogError("bad number");
     
     snprintf(nbuf, sizeof(nbuf), "%d", num);
     Jsi_HashEntry *hPtr = Jsi_HashEntryFind(interp->breakpointHash, nbuf);
@@ -3798,11 +3798,11 @@ static Jsi_RC SysVerConvertCmd(Jsi_Interp *interp, Jsi_Value *args, Jsi_Value *_
 {
     Jsi_Value *val = Jsi_ValueArrayIndex(interp, args, 0);
     Jsi_Value *flag = Jsi_ValueArrayIndex(interp, args, 1);
     if (!val) goto bail;
     if (Jsi_ValueIsNumber(interp, val)) {
-        char buf[200];
+        char buf[JSI_MAX_NUMBER_STRING*2];
         Jsi_Number n;
         if (Jsi_GetNumberFromValue(interp, val, &n) != JSI_OK)
             goto bail;
         jsi_VersionNormalize(n, buf, sizeof(buf));
         int trunc = 0;
@@ -3951,11 +3951,11 @@ static Jsi_RC SysTimesCmd(Jsi_Interp *interp, Jsi_Value *args, Jsi_Value *_this,
         Jsi_GetBoolFromValue(interp, func, &bv);
         double now = jsi_GetTimestamp();
         if (bv)
             interp->timesStart = now;
         else {
-            char buf[100];
+            char buf[JSI_MAX_NUMBER_STRING];
             snprintf(buf, sizeof(buf), " (times = %.6f sec)\n", (now-interp->timesStart));
             Jsi_Puts(interp, jsi_Stderr, buf, -1);
         }
         Jsi_ValueMakeNumber(interp, ret, 0);
         return JSI_OK;
diff --git a/src/jsiCode.c b/src/jsiCode.c
index d0f5e46..f77800e 100644
--- a/src/jsiCode.c
+++ b/src/jsiCode.c
@@ -434,11 +434,11 @@ const char* jsi_opcode_string(uint opCode)
 void jsi_code_decode(Jsi_Interp *interp, jsi_OpCode *op, int currentip, char *buf, int bsiz)
 {
     if (_JSICASTINT(op->op) < 0 || op->op >= OP_LASTOP) {
         snprintf(buf, bsiz, "Bad opcode[%d] at %d", op->op, currentip);
     }
-    char nbuf[100];
+    char nbuf[JSI_MAX_NUMBER_STRING];
     snprintf(nbuf, sizeof(nbuf), "%d#%d", currentip, op->Line);
     snprintf(buf, bsiz, "%-8s %s ", nbuf, jsi_op_names[op->op]);
 
     int sl = Jsi_Strlen(buf);
     char *bp = buf + sl;
diff --git a/src/jsiEval.c b/src/jsiEval.c
index 2194719..020a3b2 100644
--- a/src/jsiEval.c
+++ b/src/jsiEval.c
@@ -285,27 +285,27 @@ static Jsi_RC jsi_logic_less(Jsi_Interp* interp, int i1, int i2) {
     return JSI_OK;
 }
 
 static const char *jsi_evalprint(Jsi_Value *v)
 {
-    static char buf[100];
+    static char buf[JSI_MAX_NUMBER_STRING];
     if (!v)
         return "nil";
     if (v->vt == JSI_VT_NUMBER) {
-        snprintf(buf, 100, "NUM:%" JSI_NUMGFMT " ", v->d.num);
+        snprintf(buf, sizeof(buf), "NUM:%" JSI_NUMGFMT " ", v->d.num);
     } else if (v->vt == JSI_VT_BOOL) {
-        snprintf(buf, 100, "BOO:%d", v->d.val);
+        snprintf(buf, sizeof(buf), "BOO:%d", v->d.val);
     } else if (v->vt == JSI_VT_STRING) {
-        snprintf(buf, 100, "STR:'%s'", v->d.s.str);
+        snprintf(buf, sizeof(buf), "STR:'%s'", v->d.s.str);
     } else if (v->vt == JSI_VT_VARIABLE) {
-        snprintf(buf, 100, "VAR:%p", v->d.lval);
+        snprintf(buf, sizeof(buf), "VAR:%p", v->d.lval);
     } else if (v->vt == JSI_VT_NULL) {
-        snprintf(buf, 100, "NULL");
+        snprintf(buf, sizeof(buf), "NULL");
     } else if (v->vt == JSI_VT_OBJECT) {
-        snprintf(buf, 100, "OBJ:%p", v->d.obj);
+        snprintf(buf, sizeof(buf), "OBJ:%p", v->d.obj);
     } else if (v->vt == JSI_VT_UNDEF) {
-        snprintf(buf, 100, "UNDEFINED");
+        snprintf(buf, sizeof(buf), "UNDEFINED");
     }
     return buf;
 }
 /* destroy top of trylist */
 #define pop_try(head) jsi_pop_try(interp, &head)
@@ -401,11 +401,11 @@ static jsi_TryList *jsi_trylist_new(jsi_try_op_type t, jsi_ScopeChain *scope_sav
 
 static void jsiDumpInstr(Jsi_Interp *interp, jsi_Pstate *ps, Jsi_Value *_this,
     jsi_TryList *trylist, jsi_OpCode *ip, Jsi_OpCodes *opcodes)
 {
     int i;
-    char buf[200];
+    char buf[JSI_MAX_NUMBER_STRING*2];
     jsi_code_decode(interp, ip, ip - opcodes->codes, buf, sizeof(buf));
     Jsi_Printf(interp, jsi_Stderr, "%p: %-30.200s : THIS=%s, STACK=[", ip, buf, jsi_evalprint(_this));
     for (i = 0; i < interp->framePtr->Sp; ++i) {
         Jsi_Printf(interp, jsi_Stderr, "%s%s", (i>0?", ":""), jsi_evalprint(_jsi_STACKIDX(i)));
     }
@@ -1536,11 +1536,11 @@ Jsi_RC jsi_evalcode_sub(jsi_Pstate *ps, Jsi_OpCodes *opcodes,
                     Jsi_ValueMakeBool(interp, &_jsi_TOQ, 0);
                     jsiPop(interp,1);
                     break;
                 }
                 int bval = 0;
-                char nbuf[100];
+                char nbuf[JSI_MAX_NUMBER_STRING];
                 Jsi_Value *vv;
                 Jsi_Obj *obj = v->d.obj;
                 if (!cp) {
                     snprintf(nbuf, sizeof(nbuf), "%d", (int)nval);
                     cp = nbuf;
@@ -2153,11 +2153,11 @@ Jsi_RC jsi_evalcode(jsi_Pstate *ps, Jsi_Func *func, Jsi_OpCodes *opcodes,
     interp->refCount++;
     interp->level++;
     Jsi_IncrRefCount(interp, fargs);
     rc = jsi_evalcode_sub(ps, opcodes, scope, fargs, _this, *vret);
     Jsi_DecrRefCount(interp, fargs);
-    if (interp->didReturn == 0 && !interp->exited) {
+    if (interp->didReturn == 0 && !interp->exited && rc == JSI_OK) {
         if ((interp->evalFlags&JSI_EVAL_RETURN)==0)
             Jsi_ValueMakeUndef(interp, vret);
         /*if (interp->framePtr->Sp != oldSp) //TODO: at some point after memory refs???
             Jsi_LogBug("Stack not balance after execute script");*/
     }
diff --git a/src/jsiFilesys.c b/src/jsiFilesys.c
index fac83b7..7271275 100644
--- a/src/jsiFilesys.c
+++ b/src/jsiFilesys.c
@@ -1175,11 +1175,11 @@ const char *jsi_GetHomeDir(Jsi_Interp *interp) {
     str = getenv("USERPROFILE"); /* TODO: windows home dir. */
 #else
         
     if ((str = getenv("HOME")) == NULL) {
         struct passwd pwd, *pw;
-        char buf[20000];
+        char buf[JSI_BUFSIZ*3];
         if (getpwuid_r(getuid(), &pwd, buf, sizeof(buf), &pw) == 0 && pw->pw_dir)        
             str = pw->pw_dir;
     }
 #endif
     if (!str) {
diff --git a/src/jsiFunc.c b/src/jsiFunc.c
index 6a50823..e8ffcaf 100644
--- a/src/jsiFunc.c
+++ b/src/jsiFunc.c
@@ -187,11 +187,11 @@ const char *jsiFuncInfo(Jsi_Interp *interp, Jsi_DString *dStr, Jsi_Func* func, J
 
 // Check argument matches type.  If func is null, this is a parse. An index of 0 is the return value.
 Jsi_RC jsi_ArgTypeCheck(Jsi_Interp *interp, int typ,  Jsi_Value *arg, const char *p1,
     const char *p2, int index, Jsi_Func *func, bool isdefault) {
     Jsi_RC rc = JSI_OK;
-    char idxBuf[200];
+    char idxBuf[JSI_MAX_NUMBER_STRING*2];
     idxBuf[0] = 0;
     if (func && arg->vt == JSI_VT_UNDEF && !interp->typeCheck.noundef && index>0 && !isdefault && !(typ&JSI_TT_UNDEFINED)) {
         snprintf(idxBuf, sizeof(idxBuf), " arg %d", index);
         jsi_TypeMismatch(interp);
        
@@ -293,11 +293,11 @@ Jsi_RC jsi_StaticArgTypeCheck(Jsi_Interp *interp, int atyp, const char *p1, cons
 done:
     {
         Jsi_DString dStr = {};
         const char *exp = jsi_typeName(interp, typ, &dStr);
         const char *vtyp = jsi_TypeName(interp, (Jsi_ttype)atyp);
-        char idxBuf[200];
+        char idxBuf[JSI_MAX_NUMBER_STRING*2];
         idxBuf[0] = 0;
         if (index>0)
             snprintf(idxBuf, sizeof(idxBuf), " arg %d", index);
         if (line)
             interp->parseLine = line;
@@ -337,11 +337,11 @@ Jsi_RC jsi_RunFuncCallCheck(Jsi_Interp *interp, Jsi_Func *func, int argc, const
     Jsi_CmdSpec *spec = func->cmdSpec;
     Jsi_ScopeStrs *ss = func->argnames;
     if (ss==NULL && spec == NULL)
         return JSI_OK;
     int i, minArgs, maxArgs, mis = 0, varargs = 0;
-    char nbuf[100];
+    char nbuf[JSI_MAX_NUMBER_STRING];
     if (func->type == FC_BUILDIN) {
         varargs =  (spec->maxArgs<0);
         maxArgs = spec->maxArgs + func->callflags.bits.addargs;
         minArgs = spec->minArgs + func->callflags.bits.addargs;
     } else {
diff --git a/src/jsiHash.c b/src/jsiHash.c
index fd64a89..9dbf121 100644
--- a/src/jsiHash.c
+++ b/src/jsiHash.c
@@ -621,11 +621,11 @@ static Jsi_Value *jsi_hashFmtKey(Jsi_MapEntry* h, struct Jsi_MapOpts *opts, int
 {
     Jsi_HashEntry* hPtr = (Jsi_HashEntry*)h;
     void *key = Jsi_HashKeyGet(hPtr);
     if (opts->keyType == JSI_KEYS_ONEWORD)
         return Jsi_ValueNewNumber(opts->interp, (Jsi_Number)(intptr_t)key);
-    char nbuf[100];
+    char nbuf[JSI_MAX_NUMBER_STRING];
     snprintf(nbuf, sizeof(nbuf), "%p", key);
     return Jsi_ValueNewStringDup(opts->interp, nbuf);
 }
 
 Jsi_RC Jsi_HashKeysDump(Jsi_Interp *interp, Jsi_Hash *tablePtr, Jsi_Value **ret, int flags) {
diff --git a/src/jsiInterp.c b/src/jsiInterp.c
index c7dfd19..508f62f 100644
--- a/src/jsiInterp.c
+++ b/src/jsiInterp.c
@@ -698,11 +698,11 @@ static Jsi_RC jsi_InterpDelete(Jsi_Interp *interp, void *ptr) {
     return JSI_OK;
 }
 
 Jsi_Interp* Jsi_Main(Jsi_InterpOpts *opts)
 {
-    int rc = 0;
+    Jsi_RC rc = JSI_OK;
     Jsi_Interp* interp = NULL;
     int argc = 0, first = 1;
     char **argv = NULL;
     if (opts) {
         interp = opts->interp;
@@ -927,22 +927,22 @@ dofile:
 
         }
     }
     if (jsi_deleted) //TODO: rationalize jsi_deleted, jsi_exitCode, etc
         return jsi_DoExit(rc==JSI_EXIT?NULL:interp, jsi_exitCode);
-    if (rc == 0) {
+    if (rc == JSI_OK) {
         /* Skip output from an ending semicolon which evaluates to undefined */
         Jsi_Value *ret = Jsi_ReturnValue(interp);
         if (!Jsi_ValueIsType(interp, ret, JSI_VT_UNDEF)) {
             Jsi_DString dStr = {};
             fputs(Jsi_ValueGetDString(interp, ret, &dStr, 0), stdout);
             Jsi_DSFree(&dStr);
             fputs("\n", stdout);
         }
     } else {
         if (!interp->parent && !interp->isHelp)
-            fputs("ERROR\n", stderr);
+            fprintf(stderr, "ERROR: %s\n", interp->errMsgBuf);
         return jsi_DoExit(interp, 1);
     }
 
 done:
     if (rc == JSI_EXIT) {
diff --git a/src/jsiJSON.c b/src/jsiJSON.c
index cf13c97..19a56e6 100644
--- a/src/jsiJSON.c
+++ b/src/jsiJSON.c
@@ -4,11 +4,11 @@
 #include "jsiInt.h"
 #endif
 
 static void jsonNewDString(Jsi_Interp *interp, Jsi_DString *dStr, const char* str, int len)
 {
-    char buf[100], *dp = buf;
+    char buf[JSI_MAX_NUMBER_STRING], *dp = buf;
     const char *cp = str;
     int ulen;
     
     while ((cp-str)<len) {
         if (*cp == '\\') {
diff --git a/src/jsiMySql.c b/src/jsiMySql.c
index 3c51487..5f86d89 100644
--- a/src/jsiMySql.c
+++ b/src/jsiMySql.c
@@ -1167,11 +1167,11 @@ static void mdbDeleteCmd(MySqlObj *jdb)
 ** Return a JSON formatted value for the iCol'th column of the row currently pointed to by
 ** the MyDbEvalContext structure passed as the first argument.
 */
 static void mdbEvalSetColumnJSON(MyDbEvalContext *p, int iCol, Jsi_DString *dStr) {
     Jsi_Interp *interp = p->jdb->interp;
-    char nbuf[200];
+    char nbuf[JSI_MAX_NUMBER_STRING];
     MysqlPrep *prep = p->prep;
     SqlFieldResults *field = prep->fieldResult+iCol;
     if (field->isnull) {
         Jsi_DSAppend(dStr, "null", NULL);
         return;
@@ -1217,11 +1217,11 @@ static void mdbEvalSetColumnJSON(MyDbEvalContext *p, int iCol, Jsi_DString *dStr
     }
 }
 
 static void mdbEvalSetColumn(MyDbEvalContext *p, int iCol, Jsi_DString *dStr) {
     //Jsi_Interp *interp = p->jdb->interp;
-    char nbuf[200];
+    char nbuf[JSI_MAX_NUMBER_STRING];
     MysqlPrep *prep = p->prep;
     SqlFieldResults *field = prep->fieldResult+iCol;
     Jsi_Interp *interp = p->jdb->interp;
     if (field->isnull)
         return;
diff --git a/src/jsiNumber.c b/src/jsiNumber.c
index 2326369..c493bcc 100644
--- a/src/jsiNumber.c
+++ b/src/jsiNumber.c
@@ -121,11 +121,11 @@ static Jsi_RC NumberConstructor(Jsi_Interp *interp, Jsi_Value *args, Jsi_Value *
     }
     
 static Jsi_RC NumberToFixedCmd(Jsi_Interp *interp, Jsi_Value *args, Jsi_Value *_this,
     Jsi_Value **ret, Jsi_Func *funcPtr)
 {
-    char buf[100];
+    char buf[JSI_MAX_NUMBER_STRING+1];
     int prec = 0, skip = 0;
     Jsi_Number num;
     Jsi_Value *v;
     ChkStringN(_this, funcPtr, v);
     Jsi_Value *pa = Jsi_ValueArrayIndex(interp, args, skip);
@@ -139,18 +139,18 @@ static Jsi_RC NumberToFixedCmd(Jsi_Interp *interp, Jsi_Value *args, Jsi_Value *_
 }
 
 static Jsi_RC NumberToPrecisionCmd(Jsi_Interp *interp, Jsi_Value *args, Jsi_Value *_this,
     Jsi_Value **ret, Jsi_Func *funcPtr)
 {
-    char buf[100];
+    char buf[JSI_MAX_NUMBER_STRING*2];
     int prec = 0, skip = 0;
     Jsi_Number num;
     Jsi_Value *v;
     ChkStringN(_this, funcPtr, v);
     if (Jsi_GetIntFromValue(interp, Jsi_ValueArrayIndex(interp, args, skip), &prec) != JSI_OK)
         return JSI_ERROR;
-    if (prec<=0) return JSI_ERROR;
+    if (prec<=0 || prec>JSI_MAX_NUMBER_STRING) return Jsi_LogError("precision must be between 1 and %d", JSI_MAX_NUMBER_STRING);
     Jsi_GetDoubleFromValue(interp, v, &num);
     snprintf(buf, sizeof(buf),"%.*" JSI_NUMFFMT, prec, num);
     if (num<0)
         prec++;
     buf[prec+1] = 0;
@@ -161,11 +161,11 @@ static Jsi_RC NumberToPrecisionCmd(Jsi_Interp *interp, Jsi_Value *args, Jsi_Valu
 }
 
 static Jsi_RC NumberToExponentialCmd(Jsi_Interp *interp, Jsi_Value *args, Jsi_Value *_this,
     Jsi_Value **ret, Jsi_Func *funcPtr)
 {
-    char buf[100];
+    char buf[JSI_MAX_NUMBER_STRING+1];
     int prec = 0, skip = 0;
     Jsi_Number num;
     Jsi_Value *v;
     ChkStringN(_this, funcPtr, v);
     if (Jsi_GetIntFromValue(interp, Jsi_ValueArrayIndex(interp, args, skip), &prec) != JSI_OK)
@@ -189,11 +189,11 @@ static Jsi_RC NumberToExponentialCmd(Jsi_Interp *interp, Jsi_Value *args, Jsi_Va
 }
 
 static Jsi_RC NumberToStringCmd(Jsi_Interp *interp, Jsi_Value *args, Jsi_Value *_this,
     Jsi_Value **ret, Jsi_Func *funcPtr)
 {
-    char buf[500];
+    char buf[JSI_MAX_NUMBER_STRING+1];
     int radix = 10, skip = 0, argc = Jsi_ValueGetLength(interp, args);
     Jsi_Number num;
     Jsi_Value *v;
     ChkStringN(_this, funcPtr, v);
     Jsi_GetDoubleFromValue(interp, v, &num);
diff --git a/src/jsiOptions.c b/src/jsiOptions.c
index 9a9cfae..34a940f 100644
--- a/src/jsiOptions.c
+++ b/src/jsiOptions.c
@@ -1874,11 +1874,11 @@ static Jsi_RC jsi_BitfieldToValue(Jsi_Interp *interp, Jsi_OptionSpec* spec, Jsi_
             JSI_OPT_END(struct numStruct)
         };
         if (JSI_OK != jsi_EnumToValue(interp, eSpec, outValue, outStr, (void*)&nval, flags))
             return JSI_ERROR;
     } else if (outStr) {
-        char obuf[100];
+        char obuf[JSI_MAX_NUMBER_STRING];
         snprintf(obuf, sizeof(obuf), "%" PRId64, inum);
         Jsi_DSAppend(outStr, obuf, NULL);
     } else {
         Jsi_Number num = (Jsi_Number)inum;
         Jsi_ValueMakeNumber(interp, outValue, num);
diff --git a/src/jsiPstate.c b/src/jsiPstate.c
index a0eb2b9..cf6f83e 100644
--- a/src/jsiPstate.c
+++ b/src/jsiPstate.c
@@ -237,12 +237,12 @@ int jsi_PstateSetFile(jsi_Pstate *ps, Jsi_Channel fp, int skipbang)
     jsi_PstateClear(ps);
     l->ltype = LT_FILE;
     l->d.fp = fp;
     Jsi_Rewind(ps->interp, fp);
     if (skipbang) {
-        char buf[1000];
-        if (Jsi_Gets(ps->interp, fp, buf, 1000) && (buf[0] != '#' || buf[1] != '!')) {
+        char buf[JSI_BUFSIZ];
+        if (Jsi_Gets(ps->interp, fp, buf, sizeof(buf)) && (buf[0] != '#' || buf[1] != '!')) {
             Jsi_Rewind(ps->interp, fp);
         }
     }
             
     return JSI_OK;
diff --git a/src/jsiRegexp.c b/src/jsiRegexp.c
index 56d2efa..30c5c96 100644
--- a/src/jsiRegexp.c
+++ b/src/jsiRegexp.c
@@ -160,11 +160,11 @@ Jsi_RC Jsi_RegExpMatch(Jsi_Interp *interp, Jsi_Value *pattern, const char *v, in
         Jsi_DSInit(dStr);
         
     int r  = regexec(reg, v, 1, &pos, regexec_flags);
 
     if (r >= REG_BADPAT) {
-        char buf[100];
+        char buf[JSI_MAX_NUMBER_STRING];
 
         regerror(r, reg, buf, sizeof(buf));
         return Jsi_LogError("error while matching pattern: %s", buf);
     }
     if (r != REG_NOMATCH) {
diff --git a/src/jsiSqlite.c b/src/jsiSqlite.c
index 73c59e0..7667b26 100644
--- a/src/jsiSqlite.c
+++ b/src/jsiSqlite.c
@@ -1393,11 +1393,11 @@ static void jsiSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv)
     if (items != itemsStatic)
         Jsi_Free(items);
 
     bool b;
     if( rc != JSI_OK) {
-        char buf[250];
+        char buf[JSI_BUFSIZ];
         snprintf(buf, sizeof(buf), "error in function: %.200s", p->zName);
         sqlite3_result_error(context, buf, -1);
 
     } else if (Jsi_ValueIsBoolean(interp, ret)) {
         Jsi_GetBoolFromValue(interp, ret, &b);
@@ -1758,11 +1758,11 @@ static void dbEvalRowInfo(
 ** Return a JSON formatted value for the iCol'th column of the row currently pointed to by
 ** the DbEvalContext structure passed as the first argument.
 */
 static void dbEvalSetColumnJSON(DbEvalContext *p, int iCol, Jsi_DString *dStr) {
     Jsi_Interp *interp = p->jdb->interp;
-    char nbuf[200];
+    char nbuf[JSI_MAX_NUMBER_STRING];
 
     sqlite3_stmt *pStmt = p->pPreStmt->pStmt;
 
     switch( sqlite3_column_type(pStmt, iCol) ) {
     case SQLITE_BLOB: {
@@ -1808,11 +1808,11 @@ static void dbEvalSetColumnJSON(DbEvalContext *p, int iCol, Jsi_DString *dStr) {
     Jsi_JSONQuote(interp, str?str:"", -1, dStr);
 }
 
 static void dbEvalSetColumn(DbEvalContext *p, int iCol, Jsi_DString *dStr) {
     Jsi_Interp *interp = p->jdb->interp;
-    char nbuf[200];
+    char nbuf[JSI_MAX_NUMBER_STRING];
 
     sqlite3_stmt *pStmt = p->pPreStmt->pStmt;
 
     switch( sqlite3_column_type(pStmt, iCol) ) {
     case SQLITE_BLOB: {
@@ -2558,11 +2558,11 @@ static void dbOutputQuotedString(Jsi_DString *dStr, const char *z) {
 /*
 ** Output the given string as a hex-encoded blob (eg. X'1234' )
 */
 static void dbOutputHexBlob(Jsi_DString *dStr, const void *pBlob, int nBlob){
   int i;
-  char out[100], *zBlob = (char *)pBlob;
+  char out[JSI_MAX_NUMBER_STRING], *zBlob = (char *)pBlob;
   Jsi_DSAppend(dStr, "X'", NULL);
   for(i=0; i<nBlob; i++){ snprintf(out, sizeof(out),"%02x",zBlob[i]&0xff);Jsi_DSAppend(dStr, out, NULL); }
   Jsi_DSAppend(dStr, "'", NULL);
 }
 
@@ -4391,11 +4391,11 @@ static int jsi_DbQuery(Jsi_Db *jdb, Jsi_CDataDb *dbopts, const char *query)
     if (!Jsi_Strncasecmp(query, "SELECT", 6))
         return dbOptSelect(jdb, query, &ob, dbopts);
         
     DbEvalContext sEval = {};
     int insert = 0, replace = 0, update = 0;
-    char nbuf[100], *bPtr;
+    char nbuf[JSI_MAX_NUMBER_STRING], *bPtr;
 #ifdef JSI_DB_DSTRING_SIZE
     JSI_DSTRING_VAR(dStr, JSI_DB_DSTRING_SIZE);
 #else
     Jsi_DString sStr, *dStr = &sStr;
     Jsi_DSInit(dStr);
diff --git a/src/jsiString.c b/src/jsiString.c
index 0a10352..efa3d07 100644
--- a/src/jsiString.c
+++ b/src/jsiString.c
@@ -722,11 +722,11 @@ static Jsi_RC StringReplaceCmd(Jsi_Interp *interp, Jsi_Value *args, Jsi_Value *_
             break;
         }
         int match = regexec(regex, p, MAX_SUBREGEX, pmatch, regexec_flags);
 
         if (match >= REG_BADPAT) {
-            char buf[100];
+            char buf[JSI_MAX_NUMBER_STRING];
 
             regerror(match, regex, buf, sizeof(buf));
             Jsi_LogError("error while matching pattern: %s", buf);
             Jsi_DSFree(&dStr);
             return JSI_ERROR;
@@ -893,11 +893,11 @@ static Jsi_RC StringSearchCmd(Jsi_Interp *interp, Jsi_Value *args, Jsi_Value *_t
         if (r == REG_NOMATCH) {
             Jsi_ValueMakeNumber(interp, ret, -1.0);
             return JSI_OK;
         }
         if (r >= REG_BADPAT) {
-            char buf[100];
+            char buf[JSI_MAX_NUMBER_STRING];
 
             regerror(r, reg, buf, sizeof(buf));
             Jsi_LogError("error while matching pattern: %s", buf);
             return JSI_ERROR;
         }
diff --git a/src/jsiTree.c b/src/jsiTree.c
index 4a66f22..9b0fc97 100644
--- a/src/jsiTree.c
+++ b/src/jsiTree.c
@@ -944,11 +944,11 @@ static void TreeTest(Jsi_Interp* interp) {
     Jsi_TreeSearch srch;
     struct tdata {
         int n;
         int m;
     } t1, t2;
-    char nbuf[100];
+    char nbuf[JSI_MAX_NUMBER_STRING];
     
     wt = Jsi_TreeNew(interp, JSI_KEYS_ONEWORD, NULL);
     mt = Jsi_TreeNew(interp, sizeof(struct tdata), NULL);
 
     Jsi_TreeSet(wt, wt,(void*)0x88);
@@ -1036,11 +1036,11 @@ static Jsi_Value *jsi_treeFmtKey(Jsi_MapEntry* h, struct Jsi_MapOpts *opts, int
 {
     Jsi_TreeEntry* hPtr = (Jsi_TreeEntry*)h;
     void *key = Jsi_TreeKeyGet(hPtr);
     if (opts->keyType == JSI_KEYS_ONEWORD)
         return Jsi_ValueNewNumber(opts->interp, (Jsi_Number)(intptr_t)key);
-    char nbuf[100];
+    char nbuf[JSI_MAX_NUMBER_STRING];
     snprintf(nbuf, sizeof(nbuf), "%p", key);
     return Jsi_ValueNewStringDup(opts->interp, nbuf);
 }
 
 Jsi_RC Jsi_TreeKeysDump(Jsi_Interp *interp, Jsi_Tree *tablePtr, Jsi_Value **ret, int flags) {
diff --git a/src/jsiUtils.c b/src/jsiUtils.c
index e7ca2fd..14b347b 100644
--- a/src/jsiUtils.c
+++ b/src/jsiUtils.c
@@ -623,11 +623,11 @@ static Jsi_RC _object_get_callback(Jsi_Tree *tree, Jsi_TreeEntry *hPtr, void *da
 }
 
 /* Format value into dStr.  Toplevel caller does init/free. */
 static Jsi_RC jsiValueGetString(Jsi_Interp *interp, Jsi_Value* v, Jsi_DString *dStr, objwalker *owPtr)
 {
-    char buf[100], *str;
+    char buf[JSI_MAX_NUMBER_STRING], *str;
     Jsi_DString eStr;
     Jsi_DSInit(&eStr);
     if (interp->maxDepth>0 && owPtr->depth > interp->maxDepth)
         return Jsi_LogError("recursive ToString");
     int quote = owPtr->quote;
@@ -941,11 +941,11 @@ char *jsiLNhints(const char *buf, int *color, int *bold) {
     }
     return NULL;
 }
 
 static void jsiLNGetMatches(const char *str, linenoiseCompletions *lc) {
-    char buf[1000], pre[1000], hpre[6] = {};
+    char buf[JSI_BUFSIZ], pre[JSI_BUFSIZ], hpre[6] = {};
     const char *cp, *fnam = "Info.completions";
     int i = 0, len;
     int rc, isfile = 0, start = 0, end = Jsi_Strlen(str);
     Jsi_Interp* interp = jsi_interactiveInterp;
     if (!Jsi_Strncmp(str, "help ", 5)) {
diff --git a/src/jsiValue.c b/src/jsiValue.c
index e6543c4..a9fa8a2 100644
--- a/src/jsiValue.c
+++ b/src/jsiValue.c
@@ -399,11 +399,11 @@ Jsi_Value *Jsi_ValueArrayIndex(Jsi_Interp *interp, Jsi_Value *args, int index)
     Jsi_Obj *obj = args->d.obj;
     Jsi_Value *v;
     assert(args->vt == JSI_VT_OBJECT);
     if (obj->isarrlist && obj->arr)
         return ((index < 0 || (uint)index >= obj->arrCnt) ? NULL : obj->arr[index]);
-    char unibuf[100];
+    char unibuf[JSI_MAX_NUMBER_STRING];
     Jsi_NumberItoA10(index, unibuf, sizeof(unibuf));
     v = Jsi_TreeObjGetValue(args->d.obj, unibuf, 0);
     return v;
 }
 
@@ -529,11 +529,11 @@ const char* Jsi_ValueToString(Jsi_Interp *interp, Jsi_Value *v, int *lenPtr)
     int isKey = 0;
     char *key = NULL;
     if (!v)
         goto done;
     if (lenPtr) *lenPtr = 0;
-    char unibuf[200];
+    char unibuf[JSI_MAX_NUMBER_STRING*2];
     switch(v->vt) {
         case JSI_VT_STRING:
             ntxt = v->d.s.str;
             goto done;
         case JSI_VT_UNDEF:
@@ -1180,11 +1180,11 @@ Jsi_Value* jsi_ValueSubscript(Jsi_Interp *interp, Jsi_Value *target, Jsi_Value *
                 }
             }
             if (Jsi_ValueIsString(interp, key)) {
                 char *kstr = Jsi_ValueString(interp, key, NULL);
                 if (!Jsi_Strcmp(kstr,"call") || !Jsi_Strcmp(kstr,"apply") || !Jsi_Strcmp(kstr,"bind")) {
-                    char fbuf[100];
+                    char fbuf[JSI_MAX_NUMBER_STRING];
                     snprintf(fbuf, sizeof(fbuf), "Function.%s", kstr);
                     Jsi_Value *vv = Jsi_NameLookup(interp, fbuf);
                     if (vv)
                         return vv;
                 }
@@ -1377,11 +1377,11 @@ Jsi_RC Jsi_ValueInsertArray(Jsi_Interp *interp, Jsi_Value *target, int key, Jsi_
             Jsi_ObjArraySet(interp, obj, val, key);
             return JSI_OK;
         }
         return JSI_ERROR;
     }
-    char unibuf[100];
+    char unibuf[JSI_MAX_NUMBER_STRING];
     Jsi_NumberItoA10(key, unibuf, sizeof(unibuf));
     Jsi_ObjInsert(interp, obj, unibuf, val, flags);
     return JSI_OK;
 }
 
diff --git a/src/jsiWebSocket.c b/src/jsiWebSocket.c
index 823ff82..81db922 100644
--- a/src/jsiWebSocket.c
+++ b/src/jsiWebSocket.c
@@ -206,11 +206,11 @@ typedef struct { /* Per session connection (to each server) */
     Jsi_DString dHdrs; // Store header string here.
     Jsi_Stack *stack;
     Jsi_DString recvBuf; // To buffer recv when recvJSON is true.
     Jsi_Value *onClose, *onFilter, *onRecv, *onUpload, *onGet, *onUnknown, *rootdir, *headers;
     char *lastData;
-    char key[100]; // Lookup key.
+    char key[JSI_MAX_NUMBER_STRING]; // Lookup key.
 #if (LWS_LIBRARY_VERSION_MAJOR>1)
     char filename[PATH_MAX];
     long file_length;
     struct lws_spa *spa;
     Jsi_DString resultStr, paramDS, url;
@@ -567,11 +567,11 @@ jsi_wsHeader(jsi_wsPss *pss, const char *name, int *lenPtr)
 
 static int
 jsi_wsGetHeaders(jsi_wsPss *pss, struct lws *wsi, Jsi_DString* dStr, int lens[], int hmax)
 {
     int n = 0, i = 0, nlen;
-    char buf[1000];
+    char buf[JSI_BUFSIZ];
     const char *cp;
     while ((cp = (char*)lws_token_to_string((enum lws_token_indexes)n))) {
         int len = lws_hdr_copy(wsi, buf, sizeof(buf), ( enum lws_token_indexes)n);
         n++;
         if (i>=(n*2+2)) break;
@@ -1342,11 +1342,11 @@ static int jsi_wsHttp(Jsi_Interp *interp, jsi_wsCmdObj *cmdPtr, struct lws *wsi,
 
     snprintf(buf, sizeof(buf), "%s/%s", cmdPtr->curRoot, inPtr);
     Jsi_DSFree(&sStr);
     if (cmdPtr->debug>1)
         fprintf(stderr, "FILE: %s in %s | %s\n", buf, cmdPtr->curRoot, Jsi_ValueString(interp, cmdPtr->rootdir, NULL));
-    char extBuf[100], *cpde = Jsi_Strrchr(buf, '/');
+    char extBuf[JSI_BUFSIZ], *cpde = Jsi_Strrchr(buf, '/');
     isJsiWeb = (cpde && cmdPtr->jsiFnPattern && Jsi_GlobMatch(cmdPtr->jsiFnPattern, cpde+1, 0));
     bool isgzip = 0;
     if (!ext || !ext[1])
         mime = "text/html";
     else {
@@ -1834,11 +1834,11 @@ static int jsi_wscallback_http(struct lws *wsi,
 
     case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER:
         if (cmdPtr->post) {
             unsigned char **p = (unsigned char **)in, *end = (*p) + len;
             int n = 0;
-            char buf[100];
+            char buf[JSI_MAX_NUMBER_STRING];
             Jsi_ValueString(interp, cmdPtr->post, &n);
             snprintf(buf, sizeof(buf), "%d", n);
 
             if (lws_add_http_header_by_token(wsi,
                     WSI_TOKEN_HTTP_CONTENT_LENGTH,
@@ -2226,11 +2226,11 @@ jsi_wscallback_websock(struct lws *wsi,
         break;
 
     case LWS_CALLBACK_CLIENT_ESTABLISHED:
     case LWS_CALLBACK_ESTABLISHED:
         if (cmdPtr->bufferPwr2>0) {
-            char nbuf[100];
+            char nbuf[JSI_MAX_NUMBER_STRING];
             snprintf(nbuf, sizeof(nbuf), "%d", cmdPtr->bufferPwr2);
             lws_set_extension_option(wsi, "permessage-deflate", "rx_buf_size", nbuf);
             lws_set_extension_option(wsi, "permessage-deflate", "tx_buf_size", nbuf);
         }
         if (!pss)
@@ -2868,11 +2868,11 @@ static Jsi_RC WebSocketVersionCmd(Jsi_Interp *interp, Jsi_Value *args, Jsi_Value
     Jsi_Value **ret, Jsi_Func *funcPtr)
 {
     const char *verStr = NULL;
     verStr = lws_get_library_version();
     if (verStr) {
-        char buf[100], *cp;
+        char buf[JSI_MAX_NUMBER_STRING], *cp;
         snprintf(buf, sizeof(buf), "%s", verStr);
         cp = Jsi_Strchr(buf, ' ');
         if (cp) *cp = 0;
         Jsi_ValueMakeStringDup(interp, ret, buf);
     }

Vulnerable code: #define JSI_VERSION_RELEASE 6
    JSI_MAX_NUMBER_STRING=50,
        char buf[200];
    char *val, nam[200];
    char nbuf[100];
        char nbuf[100];
    char nbuf[100];
        char buf[200];
            char buf[100];
    char nbuf[100];
    static char buf[100];
        snprintf(buf, 100, "NUM:%" JSI_NUMGFMT " ", v->d.num);
        snprintf(buf, 100, "BOO:%d", v->d.val);
        snprintf(buf, 100, "STR:'%s'", v->d.s.str);
        snprintf(buf, 100, "VAR:%p", v->d.lval);
        snprintf(buf, 100, "NULL");
        snprintf(buf, 100, "OBJ:%p", v->d.obj);
        snprintf(buf, 100, "UNDEFINED");
    char buf[200];
                char nbuf[100];
    if (interp->didReturn == 0 && !interp->exited) {
        char buf[20000];
    char idxBuf[200];
        char idxBuf[200];
    char nbuf[100];
    char nbuf[100];
    int rc = 0;
    if (rc == 0) {
            fputs("ERROR\n", stderr);
    char buf[100], *dp = buf;
    char nbuf[200];
    char nbuf[200];
    char buf[100];
    char buf[100];
    if (prec<=0) return JSI_ERROR;
    char buf[100];
    char buf[500];
        char obuf[100];
        char buf[1000];
        if (Jsi_Gets(ps->interp, fp, buf, 1000) && (buf[0] != '#' || buf[1] != '!')) {
        char buf[100];
        char buf[250];
    char nbuf[200];
    char nbuf[200];
  char out[100], *zBlob = (char *)pBlob;
    char nbuf[100], *bPtr;
            char buf[100];
            char buf[100];
    char nbuf[100];
    char nbuf[100];
    char buf[100], *str;
    char buf[1000], pre[1000], hpre[6] = {};
    char unibuf[100];
    char unibuf[200];
                    char fbuf[100];
    char unibuf[100];
    char key[100]; // Lookup key.
    char buf[1000];
    char extBuf[100], *cpde = Jsi_Strrchr(buf, '/');
            char buf[100];
            char nbuf[100];
        char buf[100], *cp;
Fixed code: #define JSI_VERSION_RELEASE 7
    JSI_MAX_NUMBER_STRING=100,
        char buf[JSI_MAX_NUMBER_STRING*2];
    char *val, nam[JSI_BUFSIZ/2];
    char nbuf[JSI_MAX_NUMBER_STRING];
        char nbuf[JSI_MAX_NUMBER_STRING];
    char nbuf[JSI_MAX_NUMBER_STRING];
        char buf[JSI_MAX_NUMBER_STRING*2];
            char buf[JSI_MAX_NUMBER_STRING];
    char nbuf[JSI_MAX_NUMBER_STRING];
    static char buf[JSI_MAX_NUMBER_STRING];
        snprintf(buf, sizeof(buf), "NUM:%" JSI_NUMGFMT " ", v->d.num);
        snprintf(buf, sizeof(buf), "BOO:%d", v->d.val);
        snprintf(buf, sizeof(buf), "STR:'%s'", v->d.s.str);
        snprintf(buf, sizeof(buf), "VAR:%p", v->d.lval);
        snprintf(buf, sizeof(buf), "NULL");
        snprintf(buf, sizeof(buf), "OBJ:%p", v->d.obj);
        snprintf(buf, sizeof(buf), "UNDEFINED");
    char buf[JSI_MAX_NUMBER_STRING*2];
                char nbuf[JSI_MAX_NUMBER_STRING];
    if (interp->didReturn == 0 && !interp->exited && rc == JSI_OK) {
        char buf[JSI_BUFSIZ*3];
    char idxBuf[JSI_MAX_NUMBER_STRING*2];
        char idxBuf[JSI_MAX_NUMBER_STRING*2];
    char nbuf[JSI_MAX_NUMBER_STRING];
    char nbuf[JSI_MAX_NUMBER_STRING];
    Jsi_RC rc = JSI_OK;
    if (rc == JSI_OK) {
            fprintf(stderr, "ERROR: %s\n", interp->errMsgBuf);
    char buf[JSI_MAX_NUMBER_STRING], *dp = buf;
    char nbuf[JSI_MAX_NUMBER_STRING];
    char nbuf[JSI_MAX_NUMBER_STRING];
    char buf[JSI_MAX_NUMBER_STRING+1];
    char buf[JSI_MAX_NUMBER_STRING*2];
    if (prec<=0 || prec>JSI_MAX_NUMBER_STRING) return Jsi_LogError("precision must be between 1 and %d", JSI_MAX_NUMBER_STRING);
    char buf[JSI_MAX_NUMBER_STRING+1];
    char buf[JSI_MAX_NUMBER_STRING+1];
        char obuf[JSI_MAX_NUMBER_STRING];
        char buf[JSI_BUFSIZ];
        if (Jsi_Gets(ps->interp, fp, buf, sizeof(buf)) && (buf[0] != '#' || buf[1] != '!')) {
        char buf[JSI_MAX_NUMBER_STRING];
        char buf[JSI_BUFSIZ];
    char nbuf[JSI_MAX_NUMBER_STRING];
    char nbuf[JSI_MAX_NUMBER_STRING];
  char out[JSI_MAX_NUMBER_STRING], *zBlob = (char *)pBlob;
    char nbuf[JSI_MAX_NUMBER_STRING], *bPtr;
            char buf[JSI_MAX_NUMBER_STRING];
            char buf[JSI_MAX_NUMBER_STRING];
    char nbuf[JSI_MAX_NUMBER_STRING];
    char nbuf[JSI_MAX_NUMBER_STRING];
    char buf[JSI_MAX_NUMBER_STRING], *str;
    char buf[JSI_BUFSIZ], pre[JSI_BUFSIZ], hpre[6] = {};
    char unibuf[JSI_MAX_NUMBER_STRING];
    char unibuf[JSI_MAX_NUMBER_STRING*2];
                    char fbuf[JSI_MAX_NUMBER_STRING];
    char unibuf[JSI_MAX_NUMBER_STRING];
    char key[JSI_MAX_NUMBER_STRING]; // Lookup key.
    char buf[JSI_BUFSIZ];
    char extBuf[JSI_BUFSIZ], *cpde = Jsi_Strrchr(buf, '/');
            char buf[JSI_MAX_NUMBER_STRING];
            char nbuf[JSI_MAX_NUMBER_STRING];
        char buf[JSI_MAX_NUMBER_STRING], *cp;