]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Remove remaining atoi()/atol() calls
authorMounir IDRASSI <mounir.idrassi@idrix.fr>
Thu, 25 Jun 2026 13:09:30 +0000 (22:09 +0900)
committerTomas Mraz <tomas@openssl.foundation>
Wed, 29 Jul 2026 17:02:10 +0000 (19:02 +0200)
Remove the remaining direct atoi()/atol() uses across apps, libcrypto,
libssl, providers, demos and tests, and route the replacements through
checked helpers instead of open-coding the conversion at each call site:

  - apps use the existing opt_int()/opt_long()/opt_int_arg() parsers;
  - libcrypto and provider code use the new internal ossl_strtol()/
    ossl_strtoint() helpers, a checked (and, for ossl_strtoint(),
    narrowing) signed counterpart to the public OPENSSL_strtoul();
  - libssl, demos and tests use OPENSSL_strtoul(); the test code shares
    a single test_strtoint() helper rather than repeating the bound check
    and cast per file;
  - unsigned values use OPENSSL_strtoul(), with call-site-specific range
    checks before narrowing where the destination type requires it.

Reject conversion failures and narrow through the helpers rather than
acting on garbage, and preserve the signed RSA-PSS saltlen sentinels
while rejecting invalid numeric strings. Add regression coverage for the
invalid RSA-PSS saltlen string path.

Fixes #8216

Assisted-by: OpenCode:GLM-5.2
Reviewed-by: Tom Cosgrove <tom.cosgrove@arm.com>
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.foundation>
MergeDate: Wed Jul 29 17:02:18 2026
(Merged from https://github.com/openssl/openssl/pull/31731)

31 files changed:
apps/ca.c
apps/cmp.c
apps/lib/apps.c
apps/req.c
apps/s_client.c
apps/s_server.c
apps/speed.c
crypto/evp/ctrl_params_translate.c
crypto/mem.c
crypto/o_str.c
crypto/ppccap.c
crypto/ts/ts_conf.c
demos/digest/EVP_MD_xof.c
demos/pkey/EVP_PKEY_RSA_keygen.c
doc/man3/OPENSSL_malloc.pod
include/internal/cryptlib.h
providers/implementations/rands/seeding/rand_unix.c
providers/implementations/signature/rsa_sig.c
ssl/ssl_conf.c
test/evp_test.c
test/helpers/ssl_test_ctx.c
test/lhash_test.c
test/mfail/mfail.c
test/recipes/30-test_evp_data/evppkey_rsa_common.txt
test/ssl_old_test.c
test/testutil.h
test/testutil/driver.c
test/testutil/helper.c
test/timing_load_creds.c
util/platform_symbols/unix-symbols.txt
util/platform_symbols/windows-symbols.txt

index 8f98bc9a6a479a65c18bf872a80feec4da8bd95e..c7b5a1c22d58ad067178cce8bd84301473437b0a 100644 (file)
--- a/apps/ca.c
+++ b/apps/ca.c
@@ -484,13 +484,16 @@ int ca_main(int argc, char **argv)
             crl_nextupdate = opt_arg();
             break;
         case OPT_CRLDAYS:
-            crldays = atol(opt_arg());
+            if (!opt_long(opt_arg(), &crldays))
+                goto opthelp;
             break;
         case OPT_CRLHOURS:
-            crlhours = atol(opt_arg());
+            if (!opt_long(opt_arg(), &crlhours))
+                goto opthelp;
             break;
         case OPT_CRLSEC:
-            crlsec = atol(opt_arg());
+            if (!opt_long(opt_arg(), &crlsec))
+                goto opthelp;
             break;
         case OPT_INFILES:
             req = 1;
index abe6de5cb99783eac9b00f3067a94f3680fdf007..e75ed35a48236d44428c38c28f8254a18b2ba8f0 100644 (file)
@@ -3706,9 +3706,13 @@ static int handle_opts_upfront(int argc, char **argv)
                 opt_section = argv[++i];
             else if (strcmp(argv[i] + 1,
                          cmp_options[OPT_VERBOSITY - OPT_HELP].name)
-                    == 0
-                && !set_verbosity(atoi(argv[++i])))
-                return 0;
+                == 0) {
+                int level;
+
+                ++i;
+                if (!opt_int(argv[i], &level) || !set_verbosity(level))
+                    return 0;
+            }
         }
     }
     if (opt_section[0] == '\0') /* empty string */
index 63a8c8c00db08dfa2f8787d199bb92062827da57..5d082992ec41059837fe1d19709252bd8f364223 100644 (file)
@@ -252,10 +252,8 @@ static char *app_get_pass(const char *arg, int keepbio)
         } else if (CHECK_AND_SKIP_PREFIX(arg, "fd:")) {
             BIO *btmp;
 
-            i = atoi(arg);
-            if (i >= 0)
-                pwdbio = BIO_new_fd(i, BIO_NOCLOSE);
-            if ((i < 0) || pwdbio == NULL) {
+            if (!opt_int(arg, &i) || i < 0
+                || (pwdbio = BIO_new_fd(i, BIO_NOCLOSE)) == NULL) {
                 BIO_printf(bio_err, "Can't access file descriptor %s\n", arg);
                 return NULL;
             }
index 83ac38ef86401133f571e00ae3c9f497b7105d92..19933ea35209fcbe6fe64a08c2e5a6439d5d13c5 100644 (file)
@@ -1557,10 +1557,12 @@ static EVP_PKEY_CTX *set_keygen_ctx(const char *gstr,
     /* Treat the second part of gstr, if there is one */
     if (gstr != NULL) {
         /* If the second part starts with a digit, we assume it's a size */
-        if (!expect_paramfile && gstr[0] >= '0' && gstr[0] <= '9')
-            keylen = atol(gstr);
-        else
+        if (!expect_paramfile && gstr[0] >= '0' && gstr[0] <= '9') {
+            if (!opt_long(gstr, &keylen))
+                return NULL;
+        } else {
             paramfile = gstr;
+        }
     }
 
     if (paramfile != NULL) {
index 65aff3eb42afaa5051d1acd0c384eb26cf15474f..80bb0f5305c8d72662622b251284d94cfffdc617 100644 (file)
@@ -15,6 +15,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include <limits.h>
 #include <openssl/e_os2.h>
 #include "internal/nelem.h"
 #include "internal/sockets.h" /* for openssl_fdset() */
@@ -1520,7 +1521,8 @@ int s_client_main(int argc, char **argv)
             break;
         case OPT_MTU:
 #ifndef OPENSSL_NO_DTLS
-            socket_mtu = atol(opt_arg());
+            if (!opt_long(opt_arg(), &socket_mtu))
+                goto opthelp;
 #endif
             break;
         case OPT_FALLBACKSCSV:
@@ -1625,7 +1627,20 @@ int s_client_main(int argc, char **argv)
             len = (int)strlen(p);
             for (start = 0, i = 0; i <= len; ++i) {
                 if (i == len || p[i] == ',') {
-                    serverinfo_types[serverinfo_count] = atoi(p + start);
+                    char *end;
+                    unsigned long ul;
+
+                    /*
+                     * Parse only the current comma-separated component.
+                     * OPENSSL_strtoul() with an endptr consumes the leading
+                     * digits; we require it to stop exactly at the delimiter
+                     * (or NUL) and to fit in an unsigned short.
+                     */
+                    if (!OPENSSL_strtoul(p + start, &end, 10, &ul)
+                        || end != p + i
+                        || ul > USHRT_MAX)
+                        goto opthelp;
+                    serverinfo_types[serverinfo_count] = (unsigned short)ul;
                     if (++serverinfo_count == MAX_SI_TYPES)
                         break;
                     start = i + 1;
index 4d99e5442b2cc8d456a68be7d5a89f74dbedff2d..2fc193980c29225840db4a6a7be63f6875eb7760 100644 (file)
@@ -1885,7 +1885,7 @@ int s_server_main(int argc, char *argv[])
             break;
 #endif
         case OPT_NACCEPT:
-            naccept = atol(opt_arg());
+            naccept = opt_int_arg();
             break;
         case OPT_VERIFY:
             s_server_verify = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
@@ -2254,7 +2254,8 @@ int s_server_main(int argc, char *argv[])
             break;
         case OPT_MTU:
 #ifndef OPENSSL_NO_DTLS
-            socket_mtu = atol(opt_arg());
+            if (!opt_long(opt_arg(), &socket_mtu))
+                goto opthelp;
 #endif
             break;
         case OPT_LISTEN:
index b1732744d3afb4dc17d45dee7a7bcd4384b0e843..569f438a395b0c48841c3721fd9fcd22a0209c9c 100644 (file)
@@ -3946,11 +3946,15 @@ int speed_main(int argc, char **argv)
             }
 
             if (strncmp(sig_name, "dsa", 3) == 0) {
+                int dsa_nbits = 0;
+
+                if (!opt_int(sig_name + 3, &dsa_nbits))
+                    goto sig_err_break;
                 ctx_params = EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, NULL);
                 if (ctx_params == NULL
                     || EVP_PKEY_paramgen_init(ctx_params) <= 0
                     || EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx_params,
-                           atoi(sig_name + 3))
+                           dsa_nbits)
                         <= 0
                     || EVP_PKEY_paramgen(ctx_params, &pkey_params) <= 0
                     || (sig_gen_ctx = EVP_PKEY_CTX_new(pkey_params, NULL)) == NULL
index c515c6cbbf9d6a76fcfb8c88f13bca7011e6ee83..d0529166d783fb10809c8861a9246745fa699d5a 100644 (file)
@@ -1046,9 +1046,19 @@ static int fix_dh_nid5114(enum state state,
     case PRE_CTRL_STR_TO_PARAMS:
         if (ctx->p2 == NULL)
             return 0;
-        if ((ctx->p2 = (char *)ossl_ffc_named_group_get_name(ossl_ffc_uid_to_dh_named_group(atoi(ctx->p2)))) == NULL) {
-            ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_VALUE);
-            return 0;
+        {
+            int uid;
+
+            if (!ossl_strtoint(ctx->p2, NULL, 10, &uid)) {
+                ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_VALUE);
+                return 0;
+            }
+            ctx->p2 = (char *)ossl_ffc_named_group_get_name(
+                ossl_ffc_uid_to_dh_named_group(uid));
+            if (ctx->p2 == NULL) {
+                ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_VALUE);
+                return 0;
+            }
         }
 
         ctx->p1 = 0;
@@ -1076,8 +1086,14 @@ static int fix_dh_paramgen_type(enum state state,
         return 0;
 
     if (state == PRE_CTRL_STR_TO_PARAMS) {
-        if ((ctx->p2 = (char *)ossl_dh_gen_type_id2name(atoi(ctx->p2)))
-            == NULL) {
+        int id;
+
+        if (!ossl_strtoint(ctx->p2, NULL, 10, &id)) {
+            ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_VALUE);
+            return 0;
+        }
+        ctx->p2 = (char *)ossl_dh_gen_type_id2name(id);
+        if (ctx->p2 == NULL) {
             ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_VALUE);
             return 0;
         }
@@ -1433,8 +1449,14 @@ static int fix_rsa_pss_saltlen(enum state state,
                 break;
         }
 
-        val = i == OSSL_NELEM(str_value_map) ? atoi(ctx->p2)
-                                             : (int)str_value_map[i].id;
+        if (i == OSSL_NELEM(str_value_map)) {
+            if (!ossl_strtoint(ctx->p2, NULL, 10, &val)) {
+                ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_VALUE);
+                return 0;
+            }
+        } else {
+            val = (int)str_value_map[i].id;
+        }
         if (state == POST_CTRL_TO_PARAMS) {
             /*
              * EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN weirdness explained further
index 476d6b25293e985c43959b8d1031df90e2b0ff68..408c8edfc0bc4dabd49f7dfbcbab447757c40d0f 100644 (file)
@@ -112,12 +112,19 @@ static void parseit(void)
 {
     char *semi = strchr(md_failstring, ';');
     char *atsign;
+    char *end;
 
     if (semi != NULL)
         *semi++ = '\0';
 
-    /* Get the count (atol will stop at the @ if there), and percentage */
-    md_count = atol(md_failstring);
+    /*
+     * Get the count (parsing stops at the '@' if present), and percentage.
+     * Ignore an unparsable/overflowing count rather than acting on garbage.
+     * Validate that the count is followed by '@' or end-of-string.
+     */
+    if (!ossl_strtol(md_failstring, &end, 10, &md_count)
+        || (*end != '\0' && *end != '@'))
+        md_count = 0;
     atsign = strchr(md_failstring, '@');
     md_fail_percent = atsign == NULL ? 0 : (int)(atof(atsign + 1) * 100 + 0.5);
 
@@ -179,10 +186,19 @@ void ossl_malloc_setup_failures(void)
             parseit();
         }
     }
-    if ((cp = getenv("OPENSSL_MALLOC_FD")) != NULL)
-        md_tracefd = atoi(cp);
-    if ((cp = getenv("OPENSSL_MALLOC_SEED")) != NULL)
-        srandom(atoi(cp));
+    if ((cp = getenv("OPENSSL_MALLOC_FD")) != NULL) {
+        int fd;
+
+        if (ossl_strtoint(cp, NULL, 10, &fd) && fd >= 0)
+            md_tracefd = fd;
+    }
+    if ((cp = getenv("OPENSSL_MALLOC_SEED")) != NULL) {
+        unsigned long seed;
+
+        /* Any value is a usable seed; just truncate it to the srandom() type. */
+        if (OPENSSL_strtoul(cp, NULL, 10, &seed))
+            srandom((unsigned int)seed);
+    }
 }
 #endif
 
index 2192d48775dd88a515f2d98214b586b4a912e5f5..d48b43df17d5c1d7a744f98ce9071bfbbe3a1c32 100644 (file)
@@ -161,6 +161,52 @@ int OPENSSL_strtoul(const char *str, char **endptr, int base,
     return 1;
 }
 
+/*
+ * Internal signed counterpart to OPENSSL_strtoul().  Parses a signed long with
+ * the same validation rules: it fails on a conversion error (including
+ * overflow/underflow), if no digits were consumed, or, when |endptr| is NULL,
+ * if the whole string was not consumed.  Returns 1 on success (storing the
+ * result in |*result|), 0 otherwise.
+ */
+int ossl_strtol(const char *str, char **endptr, int base, long *result)
+{
+    char *tmp_endptr;
+    char **internal_endptr = endptr == NULL ? &tmp_endptr : endptr;
+
+    errno = 0;
+
+    *internal_endptr = (char *)str;
+
+    if (result == NULL || str == NULL)
+        return 0;
+
+    *result = strtol(str, internal_endptr, base);
+    if (errno != 0
+        || (endptr == NULL && **internal_endptr != '\0')
+        || str == *internal_endptr)
+        return 0;
+
+    return 1;
+}
+
+/*
+ * As ossl_strtol() but stores the result in an int, additionally failing if
+ * the parsed value does not fit in an int.  Returns 1 on success (storing the
+ * result in |*result|), 0 otherwise.
+ */
+int ossl_strtoint(const char *str, char **endptr, int base, int *result)
+{
+    long l;
+
+    if (result == NULL || !ossl_strtol(str, endptr, base, &l))
+        return 0;
+    if (l < INT_MIN || l > INT_MAX)
+        return 0;
+
+    *result = (int)l;
+    return 1;
+}
+
 int OPENSSL_hexchar2int(unsigned char c)
 {
 #ifdef CHARSET_EBCDIC
index e029eb3051af68194ed9e79f14552ee059955a3e..189c9e03d4673bdc0470f8112fb1d6a3bef3142d 100644 (file)
@@ -160,11 +160,16 @@ void OPENSSL_cpuid_setup(void)
 
     if (sizeof(size_t) == 4) {
         struct utsname uts;
+        long major;
+        char *end;
 #if defined(_SC_AIX_KERNEL_BITMODE)
         if (sysconf(_SC_AIX_KERNEL_BITMODE) != 64)
             return;
 #endif
-        if (uname(&uts) != 0 || atoi(uts.version) < 6)
+        if (uname(&uts) != 0
+            || !ossl_strtol(uts.version, &end, 10, &major)
+            || (*end != '\0' && *end != '.')
+            || major < 6)
             return;
     }
 
index f8d01813df53259104be29516f54bc5dd2140704..1c23eaca89681777e31e6f0832f1bd79c9e5ac78 100644 (file)
@@ -358,14 +358,26 @@ int TS_CONF_set_accuracy(CONF *conf, const char *section, TS_RESP_CTX *ctx)
     for (i = 0; i < sk_CONF_VALUE_num(list); ++i) {
         CONF_VALUE *val = sk_CONF_VALUE_value(list, i);
         if (strcmp(val->name, ENV_VALUE_SECS) == 0) {
-            if (val->value)
-                secs = atoi(val->value);
+            if (val->value != NULL
+                && (!ossl_strtoint(val->value, NULL, 10, &secs)
+                    || secs < 0)) {
+                ts_CONF_invalid(section, ENV_ACCURACY);
+                goto err;
+            }
         } else if (strcmp(val->name, ENV_VALUE_MILLISECS) == 0) {
-            if (val->value)
-                millis = atoi(val->value);
+            if (val->value != NULL
+                && (!ossl_strtoint(val->value, NULL, 10, &millis)
+                    || millis < 0)) {
+                ts_CONF_invalid(section, ENV_ACCURACY);
+                goto err;
+            }
         } else if (strcmp(val->name, ENV_VALUE_MICROSECS) == 0) {
-            if (val->value)
-                micros = atoi(val->value);
+            if (val->value != NULL
+                && (!ossl_strtoint(val->value, NULL, 10, &micros)
+                    || micros < 0)) {
+                ts_CONF_invalid(section, ENV_ACCURACY);
+                goto err;
+            }
         } else {
             ts_CONF_invalid(section, ENV_ACCURACY);
             goto err;
index f0c9de3e5fd62e2215c5eb1545ddad6eedf4cf7f..d31bd82d128c0f8d5b1d96c008cf3874f8f06e3d 100644 (file)
@@ -9,8 +9,10 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <limits.h>
 #include <openssl/err.h>
 #include <openssl/evp.h>
+#include <openssl/crypto.h>
 #include <openssl/core_names.h>
 
 /*
@@ -53,7 +55,13 @@ int main(int argc, char **argv)
 
     /* Allow digest length to be changed for demonstration purposes. */
     if (argc > 1) {
-        digest_len_i = atoi(argv[1]);
+        unsigned long ul;
+
+        if (!OPENSSL_strtoul(argv[1], NULL, 10, &ul) || ul > INT_MAX) {
+            fprintf(stderr, "Specify a non-negative digest length\n");
+            goto end;
+        }
+        digest_len_i = (int)ul;
         if (digest_len_i <= 0) {
             fprintf(stderr, "Specify a non-negative digest length\n");
             goto end;
index a889ab6f77d4b6fc2cd319370bfd0dbc4260f1d6..343bc5f296b84a0393b990cb322d3fb0f32352fe 100644 (file)
 
 #include <string.h>
 #include <stdio.h>
+#include <limits.h>
 #include <openssl/err.h>
 #include <openssl/evp.h>
+#include <openssl/crypto.h>
 #include <openssl/rsa.h>
 #include <openssl/core_names.h>
 #include <openssl/pem.h>
@@ -253,7 +255,13 @@ int main(int argc, char **argv)
     }
 
     if (argc > 1) {
-        bits_i = atoi(argv[1]);
+        unsigned long ul;
+
+        if (!OPENSSL_strtoul(argv[1], NULL, 10, &ul) || ul > INT_MAX) {
+            fprintf(stderr, "Invalid RSA key size\n");
+            return EXIT_FAILURE;
+        }
+        bits_i = (int)ul;
         if (bits_i < 512) {
             fprintf(stderr, "Invalid RSA key size\n");
             return EXIT_FAILURE;
index 1907469fcd111df238b2075b1a344c65d6b94836..a22099ac3e1b1566ab070557978b685b631c88c1 100644 (file)
@@ -47,7 +47,7 @@ OPENSSL_MALLOC_SEED
  char *OPENSSL_strndup(const char *str, size_t s);
  size_t OPENSSL_strlcat(char *dst, const char *src, size_t size);
  size_t OPENSSL_strlcpy(char *dst, const char *src, size_t size);
- int OPENSSL_strtoul(char *src, char **endptr, int base, unsigned long *num);
+ int OPENSSL_strtoul(const char *str, char **endptr, int base, unsigned long *num);
  void *OPENSSL_memdup(void *data, size_t s);
  void *OPENSSL_clear_realloc(void *p, size_t old_len, size_t num);
  void *OPENSSL_clear_realloc_array(void *p, size_t old_len, size_t num,
@@ -226,8 +226,8 @@ work on all platforms):
   ...app invocation... 3>/tmp/log$$
 
 If the environment variable B<OPENSSL_MALLOC_SEED> is set, its value
-is interpreted as an integer using atoi(3) and supplied to the srandom(3)
-call for the random number generator initialisation.
+is parsed using OPENSSL_strtoul() and supplied to the srandom(3) call for
+the random number generator initialisation.
 
 =head1 RETURN VALUES
 
index 0dcc6b6acd3fe5f984e8b0ef06297aef14119ce7..8bc22e39ce32379fa7d971de0f380d8ab87a04e1 100644 (file)
@@ -162,6 +162,19 @@ char *ossl_buf2hexstr_sep(const unsigned char *buf, long buflen, char sep);
 unsigned char *ossl_hexstr2buf_sep(const char *str, long *buflen,
     const char sep);
 
+/*
+ * Parse a signed long with validation; see OPENSSL_strtoul() for the rules.
+ * Returns 1 on success (and stores the result in |*result|), 0 on failure.
+ */
+int ossl_strtol(const char *str, char **endptr, int base, long *result);
+
+/*
+ * As ossl_strtol() but stores the result in an int, additionally failing if
+ * the parsed value does not fit in an int.
+ * Returns 1 on success (and stores the result in |*result|), 0 on failure.
+ */
+int ossl_strtoint(const char *str, char **endptr, int base, int *result);
+
 /**
  *  Writes |n| value in hex format into |buf|,
  *  and returns the number of bytes written
index 67b38cb719910c2c4bbe5e6fe9eb7fcf82774628..d1bda5c68e69b0c81e8ae2637f003b80bd753a22 100644 (file)
@@ -451,9 +451,19 @@ static int wait_random_seeded(void)
              * this alternative but essentially identical source moot.
              */
             if (uname(&un) == 0) {
-                kernel[0] = atoi(un.release);
+                int val;
+                char *end;
+
+                kernel[0] = (ossl_strtoint(un.release, &end, 10, &val)
+                                && (*end == '.' || *end == '\0'))
+                    ? val
+                    : 0;
                 p = strchr(un.release, '.');
-                kernel[1] = p == NULL ? 0 : atoi(p + 1);
+                kernel[1] = (p != NULL
+                                && ossl_strtoint(p + 1, &end, 10, &val)
+                                && (*end == '.' || *end == '\0'))
+                    ? val
+                    : 0;
                 if (kernel[0] > kernel_version[0]
                     || (kernel[0] == kernel_version[0]
                         && kernel[1] >= kernel_version[1])) {
index 232414935f354d0bd34096f53957edb88bb2cf64..7b35fec02823b29f6e78126b441f87ffed9013bd 100644 (file)
@@ -1695,8 +1695,11 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[])
                 saltlen = RSA_PSS_SALTLEN_AUTO;
             else if (strcmp(p.slen->data, OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO_DIGEST_MAX) == 0)
                 saltlen = RSA_PSS_SALTLEN_AUTO_DIGEST_MAX;
-            else
-                saltlen = atoi(p.slen->data);
+            else if (!ossl_strtoint(p.slen->data, NULL, 10, &saltlen)) {
+                ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH,
+                    "invalid RSA-PSS saltlen value");
+                return 0;
+            }
         }
 
         /*
index a7293512b9b1e7619b6a0178dc656e0eda4ec56c..d065b649d5ac7bd3761650b2b78005050fcba2ee 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "internal/e_os.h"
 
+#include <limits.h>
 #include <stdio.h>
 #include "ssl_local.h"
 #include <openssl/conf.h>
@@ -723,9 +724,11 @@ out:
 static int cmd_NumTickets(SSL_CONF_CTX *cctx, const char *value)
 {
     int rv = 0;
-    int num_tickets = atoi(value);
+    unsigned long ul;
+
+    if (OPENSSL_strtoul(value, NULL, 10, &ul) && ul <= INT_MAX) {
+        int num_tickets = (int)ul;
 
-    if (num_tickets >= 0) {
         if (cctx->ctx)
             rv = SSL_CTX_set_num_tickets(cctx->ctx, num_tickets);
         if (cctx->ssl)
index 77029f40db9b9da1a31dfb75b8741cd9781e69af..ef6dea96643ce8fb6e14685db979fc3490ec5544 100644 (file)
@@ -475,10 +475,9 @@ static int evp_test_buffer_ncopy(const char *value,
     EVP_TEST_BUFFER *db;
     unsigned char *tbuf, *p;
     size_t tbuflen;
-    int ncopy = atoi(value);
-    int i;
+    int ncopy = 0, i;
 
-    if (ncopy <= 0)
+    if (!test_strtoint(value, &ncopy) || ncopy <= 0)
         return 0;
     if (sk == NULL || sk_EVP_TEST_BUFFER_num(sk) == 0)
         return 0;
@@ -501,9 +500,9 @@ static int evp_test_buffer_set_count(const char *value,
     STACK_OF(EVP_TEST_BUFFER) *sk)
 {
     EVP_TEST_BUFFER *db;
-    int count = atoi(value);
+    int count = 0;
 
-    if (count <= 0)
+    if (!test_strtoint(value, &count) || count <= 0)
         return 0;
 
     if (sk == NULL || sk_EVP_TEST_BUFFER_num(sk) == 0)
@@ -764,14 +763,13 @@ static int digest_test_parse(EVP_TEST *t,
     if (strcmp(keyword, "Ncopy") == 0)
         return evp_test_buffer_ncopy(value, mdata->input);
     if (strcmp(keyword, "Padding") == 0)
-        return (mdata->pad_type = atoi(value)) > 0;
+        return test_strtoint(value, &mdata->pad_type) && mdata->pad_type > 0;
     if (strcmp(keyword, "XOF") == 0)
-        return (mdata->xof = atoi(value)) > 0;
+        return test_strtoint(value, &mdata->xof) && mdata->xof > 0;
     if (strcmp(keyword, "OutputSize") == 0) {
         int sz;
 
-        sz = atoi(value);
-        if (sz < 0)
+        if (!test_strtoint(value, &sz))
             return -1;
         mdata->digest_size = sz;
         return 1;
@@ -1065,8 +1063,7 @@ static int cipher_test_parse(EVP_TEST *t, const char *keyword,
     if (strcmp(keyword, "Key") == 0)
         return parse_bin(value, &cdat->key, &cdat->key_len);
     if (strcmp(keyword, "Rounds") == 0) {
-        i = atoi(value);
-        if (i < 0)
+        if (!test_strtoint(value, &i))
             return -1;
         cdat->rounds = (unsigned int)i;
         return 1;
@@ -1080,8 +1077,7 @@ static int cipher_test_parse(EVP_TEST *t, const char *keyword,
     if (strcmp(keyword, "Ciphertext") == 0)
         return parse_bin(value, &cdat->ciphertext, &cdat->ciphertext_len);
     if (strcmp(keyword, "KeyBits") == 0) {
-        i = atoi(value);
-        if (i < 0)
+        if (!test_strtoint(value, &i))
             return -1;
         cdat->key_bits = (size_t)i;
         return 1;
@@ -1838,14 +1834,12 @@ static int mac_test_parse(EVP_TEST *t,
     if (strcmp(keyword, "Ctrl") == 0)
         return ctrladd(mdata->controls, value);
     if (strcmp(keyword, "OutputSize") == 0) {
-        mdata->output_size = atoi(value);
-        if (mdata->output_size < 0)
+        if (!test_strtoint(value, &mdata->output_size))
             return -1;
         return 1;
     }
     if (strcmp(keyword, "BlockSize") == 0) {
-        mdata->block_size = atoi(value);
-        if (mdata->block_size < 0)
+        if (!test_strtoint(value, &mdata->block_size))
             return -1;
         return 1;
     }
@@ -3451,8 +3445,7 @@ static int pbkdf2_test_parse(EVP_TEST *t,
     PBE_DATA *pdata = t->data;
 
     if (strcmp(keyword, "iter") == 0) {
-        pdata->iter = atoi(value);
-        if (pdata->iter <= 0)
+        if (!test_strtoint(value, &pdata->iter) || pdata->iter <= 0)
             return -1;
         return 1;
     }
@@ -3471,8 +3464,7 @@ static int pkcs12_test_parse(EVP_TEST *t,
     PBE_DATA *pdata = t->data;
 
     if (strcmp(keyword, "id") == 0) {
-        pdata->id = atoi(value);
-        if (pdata->id <= 0)
+        if (!test_strtoint(value, &pdata->id) || pdata->id <= 0)
             return -1;
         return 1;
     }
@@ -3901,7 +3893,8 @@ static int rand_test_parse(EVP_TEST *t,
     int n;
 
     if ((p = strchr(keyword, '.')) != NULL) {
-        n = atoi(++p);
+        if (!test_strtoint(++p, &n))
+            return 0;
         if (n >= MAX_RAND_REPEATS)
             return 0;
         if (n > rdata->n)
@@ -3935,17 +3928,21 @@ static int rand_test_parse(EVP_TEST *t,
         if (strcmp(keyword, "Digest") == 0)
             return TEST_ptr(rdata->digest = OPENSSL_strdup(value));
         if (strcmp(keyword, "DerivationFunction") == 0) {
-            rdata->use_df = atoi(value) != 0;
+            n = 0;
+            (void)test_strtoint(value, &n);
+            rdata->use_df = n != 0;
             return 1;
         }
         if (strcmp(keyword, "GenerateBits") == 0) {
-            if ((n = atoi(value)) <= 0 || n % 8 != 0)
+            if (!test_strtoint(value, &n) || n <= 0 || n % 8 != 0)
                 return 0;
             rdata->generate_bits = (unsigned int)n;
             return 1;
         }
         if (strcmp(keyword, "PredictionResistance") == 0) {
-            rdata->prediction_resistance = atoi(value) != 0;
+            n = 0;
+            (void)test_strtoint(value, &n);
+            rdata->prediction_resistance = n != 0;
             return 1;
         }
         if (strcmp(keyword, "CtrlInit") == 0)
@@ -5612,7 +5609,10 @@ start:
             }
             t->reason = take_value(pp);
         } else if (strcmp(pp->key, "Threads") == 0) {
-            if (OSSL_set_max_threads(libctx, atoi(pp->value)) == 0) {
+            int nthreads = 0;
+
+            (void)test_strtoint(pp->value, &nthreads);
+            if (OSSL_set_max_threads(libctx, nthreads) == 0) {
                 TEST_info("skipping, '%s' threads not available: %s:%d",
                     pp->value, t->s.test_file, t->s.start);
                 t->skip = 1;
@@ -5630,8 +5630,9 @@ start:
                 TEST_info("Line %d: multiple security category lines", t->s.curr);
                 return 0;
             }
-            t->security_category = atoi(pp->value);
-            if (t->security_category < 0 || t->security_category > 5) {
+            t->security_category = 0;
+            if (!test_strtoint(pp->value, &t->security_category)
+                || t->security_category > 5) {
                 TEST_info("Line %d: invalid security category, should be 0..5",
                     t->s.curr);
                 return 0;
index 321d1a378a9a408b8d3005b8d68328ec182c44f1..f8b88df861201c5cd4231daf36fc4acc580f08ac 100644 (file)
@@ -56,7 +56,8 @@ static int parse_boolean(const char *value, int *result)
 #define IMPLEMENT_SSL_TEST_INT_OPTION(struct_type, name, field)            \
     static int parse_##name##_##field(struct_type *ctx, const char *value) \
     {                                                                      \
-        ctx->field = atoi(value);                                          \
+        if (!test_strtoint(value, &ctx->field))                            \
+            ctx->field = 0;                                                \
         return 1;                                                          \
     }
 
index 87dc71f829a68419b031710865f0014f3fc6a8e1..394321151f3f654564db4be2f6e9b0bc912ddd1b 100644 (file)
@@ -590,14 +590,16 @@ static int setup_num_workers(void)
     char *lhash_workers = getenv("LHASH_WORKERS");
     /* If we have HARNESS_JOBS set, don't eat more than a quarter */
     if (harness_jobs != NULL) {
-        int jobs = atoi(harness_jobs);
-        if (jobs > 0)
+        int jobs;
+
+        if (test_strtoint(harness_jobs, &jobs) && jobs > 0)
             num_workers = jobs / 4;
     }
     /* But if we have explicitly set LHASH_WORKERS use that */
     if (lhash_workers != NULL) {
-        int jobs = atoi(lhash_workers);
-        if (jobs > 0)
+        int jobs;
+
+        if (test_strtoint(lhash_workers, &jobs) && jobs > 0)
             num_workers = jobs;
     }
 
index ec391c8e85ecb2f0bf3a35b03ee3a544f43f4fc9..70f575afc92e82dbd963f23df679f5c150fcf661 100644 (file)
@@ -12,6 +12,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <limits.h>
 #include <openssl/crypto.h>
 
 #if defined(__has_feature)
@@ -69,7 +70,12 @@ static int env_is_true(const char *name)
 static int env_int(const char *name, int dflt)
 {
     const char *value = getenv(name);
-    return (value != NULL && *value != '\0') ? atoi(value) : dflt;
+    unsigned long ul;
+
+    if (value != NULL && *value != '\0'
+        && OPENSSL_strtoul(value, NULL, 10, &ul) && ul <= INT_MAX)
+        return (int)ul;
+    return dflt;
 }
 
 static void mfail_print_bt(void)
index e97ff64c0954c2e76ba6b93a9e96f305b72bbaa1..58ac329afecc1136dcb238c3d1a8d24648aa2e88 100644 (file)
@@ -966,6 +966,12 @@ Input="0123456789ABCDEF0123456789ABCDEF"
 Output=4DE433D5844043EF08D354DA03CB29068780D52706D7D1E4D50EFB7D58C9D547D83A747DDD0635A96B28F854E50145518482CB49E963054621B53C60C498D07C16E9C2789C893CF38D4D86900DE71BDE463BD2761D1271E358C7480A1AC0BAB930DDF39602AD1BC165B5D7436B516B7A7858E8EB7AB1C420EEB482F4D207F0E462B1724959320A084E13848D11D10FB593E66BF680BF6D3F345FC3E9C3DE60ABBAC37E1C6EC80A268C8D9FC49626C679097AA690BC1AA662B95EB8DB70390861AA0898229F9349B4B5FDD030D4928C47084708A933144BE23BD3C6E661B85B2C0EF9ED36D498D5B7320E8194D363D4AD478C059BAE804181965E0B81B663158A
 Result = VERIFY_ERROR
 
+# Invalid numeric salt length string
+Verify = RSA-2048-PUBLIC
+Ctrl = rsa_padding_mode:pss
+Ctrl = rsa_pss_saltlen:1x
+Result = PKEY_CTRL_ERROR
+
 # Verify using default parameters, explicitly setting parameters
 Verify = RSA-PSS-DEFAULT
 Ctrl = rsa_padding_mode:pss
index 40df6536e359ec1c8cbf84c2aaf21360671a2c52..48e3f61cf33415e6d7ac7a761ed1ad1cae5fecc8 100644 (file)
@@ -1043,13 +1043,16 @@ int main(int argc, char *argv[])
         } else if (HAS_PREFIX(*argv, "-num")) {
             if (--argc < 1)
                 goto bad;
-            number = atoi(*(++argv));
+            (void)test_strtoint(*(++argv), &number);
             if (number == 0)
                 number = 1;
         } else if (strcmp(*argv, "-bytes") == 0) {
+            unsigned long ul = 0;
+
             if (--argc < 1)
                 goto bad;
-            bytes = atol(*(++argv));
+            if (OPENSSL_strtoul(*(++argv), NULL, 10, &ul) && ul <= LONG_MAX)
+                bytes = (long)ul;
             if (bytes == 0L)
                 bytes = 1L;
             i = (int)strlen(argv[0]);
@@ -1191,9 +1194,12 @@ int main(int argc, char *argv[])
                 goto bad;
             client_sess_in = *(++argv);
         } else if (strcmp(*argv, "-should_reuse") == 0) {
+            int reuse_arg = 0;
+
             if (--argc < 1)
                 goto bad;
-            should_reuse = !!atoi(*(++argv));
+            (void)test_strtoint(*(++argv), &reuse_arg);
+            should_reuse = reuse_arg != 0;
         } else if (strcmp(*argv, "-no_ticket") == 0) {
             no_ticket = 1;
         } else if (strcmp(*argv, "-client_ktls") == 0) {
index 7e23f538278b528e19eab6bed7d7ccb2f43c8cdd..cda7716cdf441bad7aaaf617c95314fd9c319e48 100644 (file)
@@ -712,6 +712,14 @@ STACK_OF(X509) *load_certs_pem(const char *file);
 X509_REQ *load_csr_der(const char *file, OSSL_LIB_CTX *libctx);
 int test_asn1_string_to_time_t(const char *asn1_string, time_t *out_time_t);
 int compare_with_reference_file(BIO *membio, const char *reffile);
+
+/*
+ * Parse a non-negative decimal integer from |value| into |*result|.  Returns 1
+ * on success, 0 on failure (NULL/empty/non-numeric/negative/overflowing input,
+ * or trailing garbage).  Test binaries link only against the public ABI, so
+ * this wraps OPENSSL_strtoul() rather than the libcrypto-internal helpers.
+ */
+int test_strtoint(const char *value, int *result);
 /*
  * Create an X509 from an array of strings.
  */
index bfcb65b7bc62ff4908747c05766ddeabdd8abbf3..8e3637acfeb88cee348ce145e391763fb960f8e7 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <string.h>
 #include <assert.h>
+#include <limits.h>
 
 #include "internal/nelem.h"
 #include <openssl/bio.h>
@@ -138,14 +139,22 @@ int setup_test_framework(int argc, char *argv[])
     char *test_rand_seed = getenv("OPENSSL_TEST_RAND_SEED");
     char *TAP_levels = getenv("HARNESS_OSSL_LEVEL");
 
-    if (TAP_levels != NULL)
-        level = 4 * atoi(TAP_levels);
+    if (TAP_levels != NULL) {
+        int n;
+
+        if (test_strtoint(TAP_levels, &n) && n <= INT_MAX / 4)
+            level = 4 * n;
+    }
     test_adjust_streams_tap_level(level);
     if (test_rand_order != NULL) {
+        int n;
+
         rand_order = 1;
-        set_seed(atoi(test_rand_order));
+        set_seed(test_strtoint(test_rand_order, &n) ? n : 0);
     } else if (test_rand_seed != NULL) {
-        set_seed(atoi(test_rand_seed));
+        int n;
+
+        set_seed(test_strtoint(test_rand_seed, &n) ? n : 0);
     } else {
         set_seed(0);
     }
@@ -178,8 +187,12 @@ static int check_single_test_params(char *name, char *testname, char *itname)
                 break;
             }
         }
-        if (i >= num_tests)
-            single_test = atoi(name);
+        if (i >= num_tests) {
+            int n;
+
+            if (test_strtoint(name, &n))
+                single_test = n;
+        }
     }
 
     /* if only iteration is specified, assume we want the first test */
index 551b9a200bc3c985cfbd27dcf3dd895cf164b37f..a23e8c2f23022cfde98f9e0a2cccdc8e578cb88c 100644 (file)
@@ -7,12 +7,24 @@
  * https://www.openssl.org/source/license.html
  */
 #include <time.h>
+#include <limits.h>
 
 #include <openssl/asn1t.h>
 #include <openssl/posix_time.h>
+#include <openssl/crypto.h>
 
 #include "../testutil.h"
 
+int test_strtoint(const char *value, int *result)
+{
+    unsigned long ul;
+
+    if (!OPENSSL_strtoul(value, NULL, 10, &ul) || ul > INT_MAX)
+        return 0;
+    *result = (int)ul;
+    return 1;
+}
+
 int test_asn1_string_to_time_t(const char *asn1_string, time_t *out_time_t)
 {
     int ret = 0;
index 5e9e2bf6c0a2a601ecc5da98018fafd0dfa4f97b..45cdc2e1da8e2b1fd5629c0aab358896837f8e29 100644 (file)
@@ -9,8 +9,10 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <limits.h>
 
 #include <openssl/e_os2.h>
+#include <openssl/crypto.h>
 
 #ifdef OPENSSL_SYS_UNIX
 #include <sys/stat.h>
@@ -120,10 +122,14 @@ int main(int ac, char **av)
         default:
             usage();
             break;
-        case 'c':
-            if ((count = atoi(optarg)) < 0)
+        case 'c': {
+            unsigned long ul;
+
+            if (!OPENSSL_strtoul(optarg, NULL, 10, &ul) || ul > INT_MAX)
                 usage();
+            count = (int)ul;
             break;
+        }
         case 'd':
             debug = 1;
             break;
index 62720f35fd3ab3949747a690a7a2b55e22af48a0..bfd60a51b7e83f7657d94977859e6367eb8da7cc 100644 (file)
@@ -1,7 +1,6 @@
 abort
 accept
 aligned_alloc
-atoi
 bcmp
 bind
 calloc
index 7ae58a3f182a1e2bab7acc6c0a0d5a6a03dc3548..cd41c7ec0289304326eab9c567e9409c92951f80 100644 (file)
@@ -125,7 +125,6 @@ _stat64i32
 _strdup
 _time64
 _wfopen
-atoi
 calloc
 clearerr
 fclose