CVE-2018-11595 (published 2018-05-31T16:29Z)

Espruino before 1.99 allows attackers to cause a denial of service (application crash) and a potential Escalation of Privileges with a user crafted input file via a Buffer Overflow during syntax parsing, because strncat is misused.

Severity: MEDIUM
CVSS v2 base score: 6.8 (AV:N/AC:M/Au:N/C:P/I:P/A:P)
CVSS v3 base score: 7.8, HIGH (CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-119
cwe_name: Improper Restriction of Operations within the Bounds of a Memory Buffer
description: The product performs operations on a memory buffer, but it reads from or writes to a memory location outside the buffer's intended boundary. This may result in read or write operations on unexpected memory locations that could be linked to other variables, data structures, or internal program data.
extended_description: 
            Certain languages allow direct addressing of memory locations and do not automatically ensure that these locations are valid for the memory buffer that is being referenced. This can cause read or write operations to be performed on memory locations that may be associated with other variables, data structures, or internal program data.
         
         

Fix information:
repo_url: https://github.com/espruino/Espruino
commit_details: repo_url: https://github.com/espruino/Espruino
author: Gordon Williams
author_date: 2018-05-21 10:35:49+01:00
msg: Fix strncat/cpy bounding issues (fix #1425)
repository: repo_url: https://github.com/espruino/Espruino
repo_name: espruino/Espruino
description: The Espruino JavaScript interpreter - Official Repo
repo_language: C
owner: espruino
file_changes: filename: ChangeLog
change_type: ModificationType.MODIFY
diff: @@ -2,6 +2,7 @@
             nRF5x: Make FlashWrite cope with flash writes > 4k
             Increase max size of native strings on platforms that support it - 16 bit to 32 bit (#1432)
             Fix stack size detection on Linux (fix #1427)
+            Fix strncat/cpy bounding issues (fix #1425)
 
      1v98 : Allow Crypto SHA1 without SHA256/512 (for ESP8266 where flash is scarce)
             Add better docs for the form of Wifi callback functions

programming_language: Markdown
filename: jslex.c
change_type: ModificationType.MODIFY
diff: @@ -814,19 +814,14 @@ void jslTokenAsString(int token, char *str, size_t len) {
   }
 
   assert(len>=10);
-  strncpy(str, "?[",len);
-  itostr(token, &str[2], 10);
-  strncat(str, "]",len);
+  espruino_snprintf(str, len, "?[%d]", token);
 }
 
 void jslGetTokenString(char *str, size_t len) {
   if (lex->tk == LEX_ID) {
-    strncpy(str, "ID:", len);
-    strncat(str, jslGetTokenValueAsString(), len);
+    espruino_snprintf(str, len, "ID:%s", jslGetTokenValueAsString());
   } else if (lex->tk == LEX_STR) {
-    strncpy(str, "String:'", len);
-    strncat(str, jslGetTokenValueAsString(), len);
-    strncat(str, "'", len);
+    espruino_snprintf(str, len, "String:'%s'", jslGetTokenValueAsString());
   } else
     jslTokenAsString(lex->tk, str, len);
 }

programming_language: C++
filename: jspin.c
change_type: ModificationType.MODIFY
diff: @@ -179,7 +179,7 @@ void jshGetPinString(char *result, Pin pin) {
 #endif
 #endif
     } else {
-      strncpy(result, "undefined", 10);
+      strcpy(result, "undefined");
     }
   }
 
@@ -379,10 +379,10 @@ void jshPinFunctionToString(JshPinFunction pinFunc, JshPinFunctionToStringFlags
     jsiConsolePrintf("Couldn't convert pin function %d\n", pinFunc);
     return;
   }
-  if (flags & JSPFTS_DEVICE) strncat(buf, devStr, bufSize);
+  if (flags & JSPFTS_DEVICE) strncat(buf, devStr, bufSize-1);
   if (flags & JSPFTS_DEVICE_NUMBER) itostr(devIdx, &buf[strlen(buf)], 10);
-  if (flags & JSPFTS_SPACE) strncat(buf, " ", bufSize);
-  if (infoStr && (flags & JSPFTS_TYPE)) strncat(buf, infoStr, bufSize);
+  if (flags & JSPFTS_SPACE) strncat(buf, " ", bufSize-(strlen(buf)+1));
+  if (infoStr && (flags & JSPFTS_TYPE)) strncat(buf, infoStr, bufSize-(strlen(buf)+1));
 }
 
 /** Prints a list of capable pins, eg:

programming_language: C
filename: jsutils.c
change_type: ModificationType.MODIFY
diff: @@ -604,11 +604,12 @@ void itostr_extra(JsVarInt vals,char *str,bool signedVal, unsigned int base) {
 }
 
 void ftoa_bounded_extra(JsVarFloat val,char *str, size_t len, int radix, int fractionalDigits) {
+  assert(len>9); // in case if strcpy
   const JsVarFloat stopAtError = 0.0000001;
-  if (isnan(val)) strncpy(str,"NaN",len);
+  if (isnan(val)) strcpy(str,"NaN");
   else if (!isfinite(val)) {
-    if (val<0) strncpy(str,"-Infinity",len);
-    else strncpy(str,"Infinity",len);
+    if (val<0) strcpy(str,"-Infinity");
+    else strcpy(str,"Infinity");
   } else {
     if (val<0) {
       if (--len <= 0) { *str=0; return; } // bounds check

programming_language: C++
filename: jsvar.c
change_type: ModificationType.MODIFY
diff: @@ -1186,6 +1186,7 @@ size_t jsvGetString(const JsVar *v, char *str, size_t len) {
   const char *s = jsvGetConstString(v);
   if (s) {
     strncpy(str, s, len);
+    str[len-1] = 0;
     return strlen(s);
   } else if (jsvIsInt(v)) {
     itostr(v->varData.integer, str, 10);
@@ -1218,7 +1219,7 @@ size_t jsvGetString(const JsVar *v, char *str, size_t len) {
       jsvUnLock(stringVar);
       return l;
     } else {
-      strncpy(str, "", len);
+      str[0] = 0;
       jsExceptionHere(JSET_INTERNALERROR, "Variable type cannot be converted to string");
       return 0;
     }

programming_language: C++