ref: b06a5e9b02688e8d5c355544ce4130b4045c5c0b
parent: 453d28fcc0fa9dcd35ecd0050d8cec395bb161f2
author: Tor Andersson <tor.andersson@artifex.com>
date: Tue Sep 7 14:02:28 EDT 2021
Bug 704238: Limit max string lengths. Check string length when creating strings to not exceed a maximum, so we avoid integer overflows when concatenating strings. The string limit must be small enough that we'll not integer overflow in one concatenation (A + B + 1 must not overflow while still exceeding the string limit). Set the limit to 64KB for now. If we need 2GB strings then we will have to use double or int64 variables when calculating string lengths.
--- a/jsarray.c
+++ b/jsarray.c
@@ -123,11 +123,15 @@
n += strlen(r);
if (k == 0) {
- out = js_malloc(J, n);
+ if (n > JS_STRLIMIT)
+ js_rangeerror(J, "invalid string length");
+ out = js_malloc(J, (int)n);
strcpy(out, r);
} else {
n += seplen;
- out = js_realloc(J, out, n);
+ if (n > JS_STRLIMIT)
+ js_rangeerror(J, "invalid string length");
+ out = js_realloc(J, out, (int)n);
strcat(out, sep);
strcat(out, r);
}
--- a/jsi.h
+++ b/jsi.h
@@ -93,6 +93,9 @@
#ifndef JS_ASTLIMIT
#define JS_ASTLIMIT 100 /* max nested expressions */
#endif
+#ifndef JS_STRLIMIT
+#define JS_STRLIMIT (1<<16) /* max string length */
+#endif
/* instruction size -- change to int if you get integer overflow syntax errors */
--- a/jsintern.c
+++ b/jsintern.c
@@ -42,7 +42,9 @@
static js_StringNode *jsS_newstringnode(js_State *J, const char *string, const char **result)
{
- int n = strlen(string);
+ size_t n = strlen(string);
+ if (n > JS_STRLIMIT)
+ js_rangeerror(J, "invalid string length");
js_StringNode *node = js_malloc(J, soffsetof(js_StringNode, string) + n + 1);
node->left = node->right = &jsS_sentinel;
node->level = 1;
--- a/jsrun.c
+++ b/jsrun.c
@@ -119,7 +119,9 @@
void js_pushstring(js_State *J, const char *v)
{
- int n = strlen(v);
+ size_t n = strlen(v);
+ if (n > JS_STRLIMIT)
+ js_rangeerror(J, "invalid string length");
CHECKSTACK(1);
if (n <= soffsetof(js_Value, type)) {
char *s = STACK[TOP].u.shrstr;
@@ -135,6 +137,8 @@
void js_pushlstring(js_State *J, const char *v, int n)
{
+ if (n > JS_STRLIMIT)
+ js_rangeerror(J, "invalid string length");
CHECKSTACK(1);
if (n <= soffsetof(js_Value, type)) {
char *s = STACK[TOP].u.shrstr;
--- a/jsstring.c
+++ b/jsstring.c
@@ -123,7 +123,7 @@
return;
s = checkstring(J, 0);
- n = strlen(s);
+ n = 1 + strlen(s);
if (js_try(J)) {
js_free(J, out);
@@ -130,13 +130,17 @@
js_throw(J);
}
- out = js_malloc(J, n + 1);
+ if (n > JS_STRLIMIT)
+ js_rangeerror(J, "invalid string length");
+ out = js_malloc(J, n);
strcpy(out, s);
for (i = 1; i < top; ++i) {
s = js_tostring(J, i);
n += strlen(s);
- out = js_realloc(J, out, n + 1);
+ if (n > JS_STRLIMIT)
+ js_rangeerror(J, "invalid string length");
+ out = js_realloc(J, out, n);
strcat(out, s);
}