summaryrefslogtreecommitdiffstats
path: root/crypto/conf/conf_def.c
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2017-03-10 10:51:35 +0000
committerMatt Caswell <matt@openssl.org>2017-03-12 00:19:14 +0000
commit8a585601fea1091022034dd14b961c1ecd5916c3 (patch)
tree89aabb7a9041e1c7cd13a87265551adb6b469581 /crypto/conf/conf_def.c
parenta3b0d466930ec45bc3ddf4c9e853d73d37783f44 (diff)
Fix out-of-memory condition in conf
conf has the ability to expand variables in config files. Repeatedly doing this can lead to an exponential increase in the amount of memory required. This places a limit on the length of a value that can result from an expansion. Credit to OSS-Fuzz for finding this problem. Reviewed-by: Rich Salz <rsalz@openssl.org> Reviewed-by: Richard Levitte <levitte@openssl.org> (Merged from https://github.com/openssl/openssl/pull/2894)
Diffstat (limited to 'crypto/conf/conf_def.c')
-rw-r--r--crypto/conf/conf_def.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/crypto/conf/conf_def.c b/crypto/conf/conf_def.c
index 8861b3a5a0..a7b11d1598 100644
--- a/crypto/conf/conf_def.c
+++ b/crypto/conf/conf_def.c
@@ -20,6 +20,12 @@
#include <openssl/buffer.h>
#include <openssl/err.h>
+/*
+ * The maximum length we can grow a value to after variable expansion. 64k
+ * should be more than enough for all reasonable uses.
+ */
+#define MAX_CONF_VALUE_LENGTH 65536
+
static char *eat_ws(CONF *conf, char *p);
static char *eat_alpha_numeric(CONF *conf, char *p);
static void clear_comments(CONF *conf, char *p);
@@ -457,6 +463,8 @@ static int str_copy(CONF *conf, char *section, char **pto, char *from)
} else if (IS_EOF(conf, *from))
break;
else if (*from == '$') {
+ size_t newsize;
+
/* try to expand it */
rrp = NULL;
s = &(from[1]);
@@ -511,8 +519,12 @@ static int str_copy(CONF *conf, char *section, char **pto, char *from)
CONFerr(CONF_F_STR_COPY, CONF_R_VARIABLE_HAS_NO_VALUE);
goto err;
}
- if (!BUF_MEM_grow_clean(buf,
- (strlen(p) + buf->length - (e - from)))) {
+ newsize = strlen(p) + buf->length - (e - from);
+ if (newsize > MAX_CONF_VALUE_LENGTH) {
+ CONFerr(CONF_F_STR_COPY, CONF_R_VARIABLE_EXPANSION_TOO_LONG);
+ goto err;
+ }
+ if (!BUF_MEM_grow_clean(buf, newsize)) {
CONFerr(CONF_F_STR_COPY, ERR_R_MALLOC_FAILURE);
goto err;
}