summaryrefslogtreecommitdiffstats
path: root/crypto/conf
diff options
context:
space:
mode:
authorPauli <paul.dale@oracle.com>2018-07-04 09:30:43 +1000
committerPauli <paul.dale@oracle.com>2018-07-11 09:03:22 +1000
commitc9ecb13191fe902c1e78e3bca7c36c293bba4bc6 (patch)
tree41187ab74bc9d5c05b2a8df79d6fe2d2b44b3929 /crypto/conf
parent4431107d6c430950c2c2e19c03b8dff6355ccfdb (diff)
NCONF_get_number refix.
Fix the NULL check lack in a different way that is more compatible with non-NULL branch. Refer #6632 Also mark and pop the error stack instead of clearing all errors when something goes awry in CONF_get_number. Reviewed-by: Rich Salz <rsalz@openssl.org> Reviewed-by: Andy Polyakov <appro@openssl.org> (Merged from https://github.com/openssl/openssl/pull/6643)
Diffstat (limited to 'crypto/conf')
-rw-r--r--crypto/conf/conf_err.c1
-rw-r--r--crypto/conf/conf_lib.c44
2 files changed, 33 insertions, 12 deletions
diff --git a/crypto/conf/conf_err.c b/crypto/conf/conf_err.c
index 01f98da87a..f7613584ec 100644
--- a/crypto/conf/conf_err.c
+++ b/crypto/conf/conf_err.c
@@ -60,6 +60,7 @@ static const ERR_STRING_DATA CONF_str_reasons[] = {
{ERR_PACK(ERR_LIB_CONF, 0, CONF_R_NO_SECTION), "no section"},
{ERR_PACK(ERR_LIB_CONF, 0, CONF_R_NO_SUCH_FILE), "no such file"},
{ERR_PACK(ERR_LIB_CONF, 0, CONF_R_NO_VALUE), "no value"},
+ {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_NUMBER_TOO_LARGE), "number too large"},
{ERR_PACK(ERR_LIB_CONF, 0, CONF_R_RECURSIVE_DIRECTORY_INCLUDE),
"recursive directory include"},
{ERR_PACK(ERR_LIB_CONF, 0, CONF_R_SSL_COMMAND_SECTION_EMPTY),
diff --git a/crypto/conf/conf_lib.c b/crypto/conf/conf_lib.c
index 5f976f35c4..1833b15ebe 100644
--- a/crypto/conf/conf_lib.c
+++ b/crypto/conf/conf_lib.c
@@ -11,6 +11,7 @@
#include <stdio.h>
#include <string.h>
#include "internal/conf.h"
+#include "internal/ctype.h"
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/conf.h>
@@ -123,6 +124,7 @@ long CONF_get_number(LHASH_OF(CONF_VALUE) *conf, const char *group,
int status;
long result = 0;
+ ERR_set_mark();
if (conf == NULL) {
status = NCONF_get_number_e(NULL, group, name, &result);
} else {
@@ -130,12 +132,8 @@ long CONF_get_number(LHASH_OF(CONF_VALUE) *conf, const char *group,
CONF_set_nconf(&ctmp, conf);
status = NCONF_get_number_e(&ctmp, group, name, &result);
}
-
- if (status == 0) {
- /* This function does not believe in errors... */
- ERR_clear_error();
- }
- return result;
+ ERR_pop_to_mark();
+ return status == 0 ? 0L : result;
}
void CONF_free(LHASH_OF(CONF_VALUE) *conf)
@@ -277,10 +275,23 @@ char *NCONF_get_string(const CONF *conf, const char *group, const char *name)
return NULL;
}
+static int default_is_number(const CONF *conf, char c)
+{
+ return ossl_isdigit(c);
+}
+
+static int default_to_int(const CONF *conf, char c)
+{
+ return (int)(c - '0');
+}
+
int NCONF_get_number_e(const CONF *conf, const char *group, const char *name,
long *result)
{
char *str;
+ long res;
+ int (*is_number)(const CONF *, char) = &default_is_number;
+ int (*to_int)(const CONF *, char) = &default_to_int;
if (result == NULL) {
CONFerr(CONF_F_NCONF_GET_NUMBER_E, ERR_R_PASSED_NULL_PARAMETER);
@@ -292,14 +303,23 @@ int NCONF_get_number_e(const CONF *conf, const char *group, const char *name,
if (str == NULL)
return 0;
- if (conf == NULL)
- *result = strtol(str, &str, 10);
- else
- for (*result = 0; conf->meth->is_number(conf, *str);) {
- *result = (*result) * 10 + conf->meth->to_int(conf, *str);
- str++;
+ if (conf != NULL) {
+ if (conf->meth->is_number != NULL)
+ is_number = conf->meth->is_number;
+ if (conf->meth->to_int != NULL)
+ to_int = conf->meth->to_int;
+ }
+ for (res = 0; is_number(conf, *str); str++) {
+ const int d = to_int(conf, *str);
+
+ if (res > (LONG_MAX - d) / 10L) {
+ CONFerr(CONF_F_NCONF_GET_NUMBER_E, CONF_R_NUMBER_TOO_LARGE);
+ return 0;
}
+ res = res * 10 + d;
+ }
+ *result = res;
return 1;
}