CVE-2020-22874 (published 2021-07-13T15:15Z)

Integer overflow vulnerability in function Jsi_ObjArraySizer in jsish before 3.0.8, allows remote attackers to execute arbitrary code.

Severity: HIGH
CVSS v2 base score: 7.5 (AV:N/AC:L/Au:N/C:P/I:P/A:P)
CVSS v3 base score: 9.8, CRITICAL (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-190
cwe_name: Integer Overflow or Wraparound
description: The product performs a calculation that can
         produce an integer overflow or wraparound when the logic
         assumes that the resulting value will always be larger than
         the original value. This occurs when an integer value is
         incremented to a value that is too large to store in the
         associated representation. When this occurs, the value may
         become a very small or negative number.
extended_description: 
            
            
            
            
         
         

Fix information:
repo_url: https://github.com/pcmacdon/jsish
commit_details: repo_url: https://github.com/pcmacdon/jsish
author: pmacdona
author_date: 2020-04-13 21:13:17+00:00
msg: Release "3.0.8": Address Array alloc sizing issues from issue "integer overflow and buffer overflow #5".

FossilOrigin-Name: 8c46a1d465b358110dcfb271721d35fe843a1b52f2fa24ccc10094eb8aaf6fe4
repository: repo_url: https://github.com/pcmacdon/jsish
repo_name: pcmacdon/jsish
description: Jsi is a small, C-embeddable javascript interpreter with tightly woven Web and DB support.
repo_language: C
owner: pcmacdon
file_changes: filename: Reference.md
change_type: ModificationType.MODIFY
diff: @@ -600,7 +600,7 @@ Otherwise waits until the sub-interp is idle, to make call and return result.</t
 <tr><td>lockTimeout</td><td><i>INT</i></td><td>Thread time-out for mutex lock acquires (milliseconds).</td><td><i></i></td></tr>
 <tr><td>logOpts</td><td><i><a href='#logOptsOptions'>options</a></i></td><td>Options for log output to add file/line/time.</td><td><i></i></td></tr>
 <tr><td>maxDepth</td><td><i>INT</i></td><td>Depth limit of recursive function calls (1000).</td><td><i></i></td></tr>
-<tr><td>maxArrayList</td><td><i>INT</i></td><td>Maximum array convertable to list (100000).</td><td><i></i></td></tr>
+<tr><td>maxArrayList</td><td><i>UINT</i></td><td>Maximum array convertable to list (100000).</td><td><i></i></td></tr>
 <tr><td>maxIncDepth</td><td><i>INT</i></td><td>Maximum allowed source/require nesting depth (50).</td><td><i></i></td></tr>
 <tr><td>maxInterpDepth</td><td><i>INT</i></td><td>Maximum nested subinterp create depth (10).</td><td><i></i></td></tr>
 <tr><td>maxUserObjs</td><td><i>INT</i></td><td>Maximum number of 'new' object calls, eg. File, RegExp, etc.</td><td><i></i></td></tr>

programming_language: HTML
filename: jsi.h
change_type: ModificationType.MODIFY
diff: @@ -4,7 +4,7 @@
 
 #define JSI_VERSION_MAJOR   3
 #define JSI_VERSION_MINOR   0
-#define JSI_VERSION_RELEASE 7
+#define JSI_VERSION_RELEASE 8
 
 #define JSI_VERSION (JSI_VERSION_MAJOR + ((Jsi_Number)JSI_VERSION_MINOR/100.0) + ((Jsi_Number)JSI_VERSION_RELEASE/10000.0))
 

programming_language: C
filename: jsiArray.c
change_type: ModificationType.MODIFY
diff: @@ -267,7 +267,7 @@ static Jsi_RC jsi_ArrayFlatSub(Jsi_Interp *interp, Jsi_Obj* nobj, Jsi_Value *arr
             rc = jsi_ArrayFlatSub(interp, nobj, t , depth-1);
         else if (!Jsi_ValueIsUndef(interp, t))
             Jsi_ObjArrayAdd(interp, nobj, t);
-        if ((++n + clen)>interp->maxArrayList)
+        if ((uint)(++n + clen)>interp->maxArrayList)
             return Jsi_LogError("array size exceeded");
     }
     return rc;

programming_language: C
filename: jsiCData.c
change_type: ModificationType.MODIFY
diff: @@ -1276,8 +1276,8 @@ static Jsi_RC CDataStructDefineCmd(Jsi_Interp *interp, Jsi_Value *args, Jsi_Valu
             sf->flags |= JSI_OPT_BITSET_ENUM;
         }
         if (sf->arrSize) {
-            if (sf->arrSize>MAX_ARRAY_LIST) {
-                rc = Jsi_LogError("array size too big: %d >= %d", sf->arrSize, MAX_ARRAY_LIST);
+            if (sf->arrSize>interp->maxArrayList) {
+                rc = Jsi_LogError("array size too big: %d >= %d", sf->arrSize, interp->maxArrayList);
                 goto bail;
             }
             if (sf->bits || isEnum) {

programming_language: C
filename: jsiInt.h
change_type: ModificationType.MODIFY
diff: @@ -1259,7 +1259,7 @@ struct Jsi_Interp {
     Jsi_Value *Top_object;
     Jsi_ScopeStrs *scopes[JSI_MAX_SCOPE];
     int cur_scope;
-    int maxArrayList;
+    uint maxArrayList;
     int delRBCnt;
     Jsi_Func *activeFunc;  // Currently active function call.
     Jsi_Func *prevActiveFunc;  // Prev active function call.

programming_language: C
filename: jsiInterp.c
change_type: ModificationType.MODIFY
diff: @@ -100,7 +100,7 @@ static Jsi_OptionSpec InterpOptions[] = {
     JSI_OPT(INT,   Jsi_Interp, lockTimeout, .help="Thread time-out for mutex lock acquires (milliseconds)" ),
     JSI_OPT(CUSTOM,Jsi_Interp, logOpts,     .help="Options for log output to add file/line/time", .flags=0, .custom=Jsi_Opt_SwitchSuboption, .data=jsi_InterpLogOptions),
     JSI_OPT(INT,   Jsi_Interp, maxDepth,    .help="Depth limit of recursive function calls (1000)", .flags=JSI_OPT_LOCKSAFE),
-    JSI_OPT(INT,   Jsi_Interp, maxArrayList,.help="Maximum array convertable to list (100000)", .flags=JSI_OPT_LOCKSAFE),
+    JSI_OPT(UINT,  Jsi_Interp, maxArrayList,.help="Maximum array convertable to list (100000)", .flags=JSI_OPT_LOCKSAFE),
     JSI_OPT(INT,   Jsi_Interp, maxIncDepth, .help="Maximum allowed source/require nesting depth (50)", .flags=JSI_OPT_LOCKSAFE),
     JSI_OPT(INT,   Jsi_Interp, maxInterpDepth,.help="Maximum nested subinterp create depth (10)", .flags=JSI_OPT_LOCKSAFE),
     JSI_OPT(INT,   Jsi_Interp, maxUserObjs, .help="Maximum number of 'new' object calls, eg. File, RegExp, etc", .flags=JSI_OPT_LOCKSAFE ),
@@ -1146,6 +1146,7 @@ static Jsi_Interp* jsi_InterpNew(Jsi_Interp *parent, Jsi_Value *opts, Jsi_Interp
     }
     interp->maxDepth = JSI_MAX_EVAL_DEPTH;
     interp->maxIncDepth = JSI_MAX_INCLUDE_DEPTH;
+    interp->maxArrayList = MAX_ARRAY_LIST;
     interp->typeWarnMax = 50;
     interp->subOpts.dblPrec = __DBL_DECIMAL_DIG__-1;
     interp->subOpts.prompt = "$ ";
@@ -1482,7 +1483,6 @@ static Jsi_Interp* jsi_InterpNew(Jsi_Interp *parent, Jsi_Value *opts, Jsi_Interp
 #endif
     if (interp->typeCheck.all|interp->typeCheck.parse|interp->typeCheck.funcsig)
         interp->staticFuncsTbl = Jsi_HashNew(interp, JSI_KEYS_STRING, NULL);
-    interp->maxArrayList = MAX_ARRAY_LIST;
     if (!jsiIntData.isInit) {
         jsiIntData.isInit = 1;
         jsi_InitValue(interp, 0);

programming_language: C
filename: jsiObj.c
change_type: ModificationType.MODIFY
diff: @@ -76,7 +76,7 @@ static Jsi_RC ObjListifyCallback(Jsi_Tree *tree, Jsi_TreeEntry *hPtr, void *data
         if (!cp || !isdigit(*cp))
             return JSI_OK;
         n = (int)strtol(cp, &ep, 0);
-        if (n<0 || n >= interp->maxArrayList)
+        if (n<0 || (uint)n >= interp->maxArrayList)
             return JSI_OK;
         hPtr->f.bits.isarrlist = 1;
         if (Jsi_ObjArraySizer(interp, obj, n) <= 0) 
@@ -414,12 +414,12 @@ int Jsi_ObjDecrRefCount(Jsi_Interp *interp, Jsi_Obj *obj)  {
 
 int Jsi_ObjArraySizer(Jsi_Interp *interp, Jsi_Obj *obj, uint len)
 {
-    int nsiz = len + 1, mod = ALLOC_MOD_SIZE;
+    uint nsiz = len + 1, mod = ALLOC_MOD_SIZE;
     assert(obj->isarrlist);
     if (mod>1)
         nsiz = nsiz + ((mod-1) - (nsiz + mod - 1)%mod);
-    if (nsiz > MAX_ARRAY_LIST) {
-        Jsi_LogError("array size too large");
+    if (len >= interp->maxArrayList || nsiz > interp->maxArrayList) {
+        Jsi_LogError("array size too big: %u >= %u", len, interp->maxArrayList);
         return 0;
     }
     if (len >= obj->arrMaxSize) {

programming_language: C
filename: jsiValue.c
change_type: ModificationType.MODIFY
diff: @@ -1036,7 +1036,7 @@ Jsi_Value *jsi_ValueObjKeyAssign(Jsi_Interp *interp, Jsi_Value *target, Jsi_Valu
     }
     /* TODO: array["1"] also extern the length of array */
     
-    if (arrayindex >= 0 && arrayindex < MAX_ARRAY_LIST &&
+    if (arrayindex >= 0 && (uint)arrayindex < interp->maxArrayList &&
         target->vt == JSI_VT_OBJECT && target->d.obj->arr) {
         return jsi_ObjArraySetDup(interp, target->d.obj, value, arrayindex);
     }
@@ -1373,7 +1373,7 @@ Jsi_RC Jsi_ValueInsertArray(Jsi_Interp *interp, Jsi_Value *target, int key, Jsi_
     Jsi_Obj *obj = target->d.obj;
     
     if (obj->isarrlist) {
-        if (key >= 0 && key < interp->maxArrayList) {
+        if (key >= 0 && (uint)key < interp->maxArrayList) {
             Jsi_ObjArraySet(interp, obj, val, key);
             return JSI_OK;
         }

programming_language: C++
filename: protos.jsi
change_type: ModificationType.MODIFY
diff: @@ -1,4 +1,4 @@
-//JSI Command Prototypes: version 3.0.6
+//JSI Command Prototypes: version 3.0.8
 throw("NOT EXECUTABLE: USE FILE IN GEANY EDITOR FOR CMD LINE COMPLETION + GOTO TAG");
 
 var Array = function(cmd,args) {};

programming_language: Lua
filename: reference.wiki
change_type: ModificationType.MODIFY
diff: @@ -633,7 +633,7 @@ Otherwise waits until the sub-interp is idle, to make call and return result.</t
 <tr><td>lockTimeout</td><td><i>INT</i></td><td>Thread time-out for mutex lock acquires (milliseconds).</td><td><i></i></td></tr>
 <tr><td>logOpts</td><td><i><a href='#logOptsOptions'>options</a></i></td><td>Options for log output to add file/line/time.</td><td><i></i></td></tr>
 <tr><td>maxDepth</td><td><i>INT</i></td><td>Depth limit of recursive function calls (1000).</td><td><i></i></td></tr>
-<tr><td>maxArrayList</td><td><i>INT</i></td><td>Maximum array convertable to list (100000).</td><td><i></i></td></tr>
+<tr><td>maxArrayList</td><td><i>UINT</i></td><td>Maximum array convertable to list (100000).</td><td><i></i></td></tr>
 <tr><td>maxIncDepth</td><td><i>INT</i></td><td>Maximum allowed source/require nesting depth (50).</td><td><i></i></td></tr>
 <tr><td>maxInterpDepth</td><td><i>INT</i></td><td>Maximum nested subinterp create depth (10).</td><td><i></i></td></tr>
 <tr><td>maxUserObjs</td><td><i>INT</i></td><td>Maximum number of 'new' object calls, eg. File, RegExp, etc.</td><td><i></i></td></tr>

programming_language: HTML