CVE-2020-22873 (C, published 2021-07-13T15:15Z)
Description: value: Buffer overflow vulnerability in function NumberToPrecisionCmd in jsish before 3.0.7, allows remote attackers to execute arbitrary code.
Severity: HIGH (CVSS v3 base score: 9.8)
Weakness: CWE-120 \u2014 Buffer Copy without Checking Size of Input ('Classic Buffer Overflow')
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.
Repository: https://github.com/pcmacdon/jsish
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 message: Release "3.0.7": Fix toPrecision bug "stack overflow #4".

FossilOrigin-Name: 6c7f0c37027d7f890b57cb38f776af39b8f81f03e60ceeb0a231a1d21e24b5de

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;