The branch master has been updated via 9830e7ea42b9c0f95ea1f4b09aa2e60fa7d3115f (commit) from 538f38db50e4ead178025689d28bda316b15c242 (commit)
- Log ----------------------------------------------------------------- commit 9830e7ea42b9c0f95ea1f4b09aa2e60fa7d3115f Author: Pauli <paul.d...@oracle.com> Date: Tue May 21 07:42:26 2019 +1000 Params conversion tests. Add ranged checked OSSL_PARAM conversions between the native types. A conversion is legal only if the given value can be exactly represented by the target type. Includes a test case that reads a stanza test case file and verified that param conversions are processed properly. Reviewed-by: Richard Levitte <levi...@openssl.org> (Merged from https://github.com/openssl/openssl/pull/8733) ----------------------------------------------------------------------- Summary of changes: crypto/params.c | 475 +++++++++++++++++---- doc/man3/OSSL_PARAM_TYPE.pod | 3 +- test/build.info | 6 +- test/params_conversion_test.c | 334 +++++++++++++++ ...test_provider.t => 04-test_params_conversion.t} | 17 +- .../native_types.txt | 343 +++++++++++++++ 6 files changed, 1088 insertions(+), 90 deletions(-) create mode 100644 test/params_conversion_test.c copy test/recipes/{04-test_provider.t => 04-test_params_conversion.t} (54%) create mode 100644 test/recipes/04-test_params_conversion_data/native_types.txt diff --git a/crypto/params.c b/crypto/params.c index bdb1fa9..183884f 100644 --- a/crypto/params.c +++ b/crypto/params.c @@ -156,12 +156,54 @@ OSSL_PARAM OSSL_PARAM_construct_ulong(const char *key, unsigned long int *buf, int OSSL_PARAM_get_int32(const OSSL_PARAM *p, int32_t *val) { - if (val == NULL || p == NULL || (p->data_type != OSSL_PARAM_INTEGER)) + int64_t i64; + uint32_t u32; + uint64_t u64; + double d; + + if (val == NULL || p == NULL ) return 0; - if (p->data_size == sizeof(int32_t)) { - *val = *(const int32_t *)p->data; - return 1; + if (p->data_type == OSSL_PARAM_INTEGER) { + switch (p->data_size) { + case sizeof(int32_t): + *val = *(const int32_t *)p->data; + return 1; + case sizeof(int64_t): + i64 = *(const int64_t *)p->data; + if (i64 >= INT32_MIN && i64 <= INT32_MAX) { + *val = (int32_t)i64; + return 1; + } + break; + } + } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) { + switch (p->data_size) { + case sizeof(uint32_t): + u32 = *(const uint32_t *)p->data; + if (u32 <= INT32_MAX) { + *val = (int32_t)u32; + return 1; + } + break; + case sizeof(uint64_t): + u64 = *(const uint64_t *)p->data; + if (u64 <= INT32_MAX) { + *val = (int32_t)u64; + return 1; + } + break; + } + } else if (p->data_type == OSSL_PARAM_REAL) { + switch (p->data_size) { + case sizeof(double): + d = *(const double *)p->data; + if (d >= INT32_MIN && d <= INT32_MAX && d == (int32_t)d) { + *val = (int32_t)d; + return 1; + } + break; + } } return 0; } @@ -171,19 +213,35 @@ int OSSL_PARAM_set_int32(const OSSL_PARAM *p, int32_t val) if (p == NULL) return 0; SET_RETURN_SIZE(p, 0); - if (p->data_type != OSSL_PARAM_INTEGER) - return 0; - - SET_RETURN_SIZE(p, sizeof(int32_t)); /* Minimum expected size */ - switch (p->data_size) { - case sizeof(int32_t): - SET_RETURN_SIZE(p, sizeof(int32_t)); - *(int32_t *)p->data = val; - return 1; - case sizeof(int64_t): - SET_RETURN_SIZE(p, sizeof(int64_t)); - *(int64_t *)p->data = (int64_t)val; - return 1; + if (p->data_type == OSSL_PARAM_INTEGER) { + SET_RETURN_SIZE(p, sizeof(int32_t)); /* Minimum expected size */ + switch (p->data_size) { + case sizeof(int32_t): + *(int32_t *)p->data = val; + return 1; + case sizeof(int64_t): + SET_RETURN_SIZE(p, sizeof(int64_t)); + *(int64_t *)p->data = (int64_t)val; + return 1; + } + } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER && val >= 0) { + SET_RETURN_SIZE(p, sizeof(uint32_t)); /* Minimum expected size */ + switch (p->data_size) { + case sizeof(uint32_t): + *(uint32_t *)p->data = (uint32_t)val; + return 1; + case sizeof(uint64_t): + SET_RETURN_SIZE(p, sizeof(uint64_t)); + *(uint64_t *)p->data = (uint64_t)val; + return 1; + } + } else if (p->data_type == OSSL_PARAM_REAL) { + SET_RETURN_SIZE(p, sizeof(double)); + switch (p->data_size) { + case sizeof(double): + *(double *)p->data = (double)val; + return 1; + } } return 0; } @@ -197,35 +255,96 @@ OSSL_PARAM OSSL_PARAM_construct_int32(const char *key, int32_t *buf, int OSSL_PARAM_get_uint32(const OSSL_PARAM *p, uint32_t *val) { - if (val == NULL - || p == NULL - || (p->data_type != OSSL_PARAM_UNSIGNED_INTEGER)) + int32_t i32; + int64_t i64; + uint64_t u64; + double d; + + if (val == NULL || p == NULL) return 0; - if (p->data_size == sizeof(uint32_t)) { - *val = *(const uint32_t *)p->data; - return 1; + if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) { + switch (p->data_size) { + case sizeof(uint32_t): + *val = *(const uint32_t *)p->data; + return 1; + case sizeof(uint64_t): + u64 = *(const uint64_t *)p->data; + if (u64 <= UINT32_MAX) { + *val = (uint32_t)u64; + return 1; + } + break; + } + } else if (p->data_type == OSSL_PARAM_INTEGER) { + switch (p->data_size) { + case sizeof(int32_t): + i32 = *(const int32_t *)p->data; + if (i32 >= 0) { + *val = i32; + return 1; + } + break; + case sizeof(int64_t): + i64 = *(const int64_t *)p->data; + if (i64 >= 0 && i64 <= UINT32_MAX) { + *val = (uint32_t)i64; + return 1; + } + break; + } + } else if (p->data_type == OSSL_PARAM_REAL) { + switch (p->data_size) { + case sizeof(double): + d = *(const double *)p->data; + if (d >= 0 && d <= UINT32_MAX && d == (uint32_t)d) { + *val = (uint32_t)d; + return 1; + } + break; + } } return 0; } int OSSL_PARAM_set_uint32(const OSSL_PARAM *p, uint32_t val) { - if (p == NULL) return 0; - SET_RETURN_SIZE(p, 0); - if (p->data_type != OSSL_PARAM_UNSIGNED_INTEGER) + if (p == NULL) return 0; + SET_RETURN_SIZE(p, 0); - SET_RETURN_SIZE(p, sizeof(uint32_t)); /* Minimum expected size */ - switch (p->data_size) { - case sizeof(uint32_t): - SET_RETURN_SIZE(p, sizeof(uint32_t)); - *(uint32_t *)p->data = val; - return 1; - case sizeof(uint64_t): - SET_RETURN_SIZE(p, sizeof(uint64_t)); - *(uint64_t *)p->data = (uint64_t)val; - return 1; + if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) { + SET_RETURN_SIZE(p, sizeof(uint32_t)); /* Minimum expected size */ + switch (p->data_size) { + case sizeof(uint32_t): + *(uint32_t *)p->data = val; + return 1; + case sizeof(uint64_t): + SET_RETURN_SIZE(p, sizeof(uint64_t)); + *(uint64_t *)p->data = val; + return 1; + } + } else if (p->data_type == OSSL_PARAM_INTEGER) { + SET_RETURN_SIZE(p, sizeof(int32_t)); /* Minimum expected size */ + switch (p->data_size) { + case sizeof(int32_t): + if (val <= INT32_MAX) { + *(int32_t *)p->data = (int32_t)val; + return 1; + } + break; + case sizeof(int64_t): + SET_RETURN_SIZE(p, sizeof(int64_t)); + *(int64_t *)p->data = (int64_t)val; + return 1; + } + } else if (p->data_type == OSSL_PARAM_REAL) { + SET_RETURN_SIZE(p, sizeof(double)); + switch (p->data_size) { + case sizeof(double): + *(double *)p->data = (double)val; + return 1; + } } return 0; } @@ -239,34 +358,94 @@ OSSL_PARAM OSSL_PARAM_construct_uint32(const char *key, uint32_t *buf, int OSSL_PARAM_get_int64(const OSSL_PARAM *p, int64_t *val) { - if (val == NULL || p == NULL || (p->data_type != OSSL_PARAM_INTEGER)) + uint64_t u64; + double d; + + if (val == NULL || p == NULL ) return 0; - switch (p->data_size) { - case sizeof(int32_t): - *val = (int64_t)*(const int32_t *)p->data; - return 1; - case sizeof(int64_t): - *val = *(const int64_t *)p->data; - return 1; + if (p->data_type == OSSL_PARAM_INTEGER) { + switch (p->data_size) { + case sizeof(int32_t): + *val = *(const int32_t *)p->data; + return 1; + case sizeof(int64_t): + *val = *(const int64_t *)p->data; + return 1; + } + } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) { + switch (p->data_size) { + case sizeof(uint32_t): + *val = *(const uint32_t *)p->data; + return 1; + case sizeof(uint64_t): + u64 = *(const uint64_t *)p->data; + if (u64 <= INT64_MAX) { + *val = (int64_t)u64; + return 1; + } + break; + } + } else if (p->data_type == OSSL_PARAM_REAL) { + switch (p->data_size) { + case sizeof(double): + d = *(const double *)p->data; + if (d >= INT64_MIN && d <= INT64_MAX && d == (int64_t)d) { + *val = (int64_t)d; + return 1; + } + break; + } } return 0; } int OSSL_PARAM_set_int64(const OSSL_PARAM *p, int64_t val) { + uint64_t u64; + if (p == NULL) return 0; SET_RETURN_SIZE(p, 0); - if (p->data_type != OSSL_PARAM_INTEGER) - return 0; - - SET_RETURN_SIZE(p, sizeof(int64_t)); /* Minimum expected size */ - switch (p->data_size) { - case sizeof(int64_t): - SET_RETURN_SIZE(p, sizeof(int64_t)); - *(int64_t *)p->data = val; - return 1; + if (p->data_type == OSSL_PARAM_INTEGER) { + SET_RETURN_SIZE(p, sizeof(int64_t)); /* Expected size */ + switch (p->data_size) { + case sizeof(int32_t): + if (val >= INT32_MIN && val <= INT32_MAX) { + SET_RETURN_SIZE(p, sizeof(int32_t)); + *(int32_t *)p->data = (int32_t)val; + return 1; + } + break; + case sizeof(int64_t): + *(int64_t *)p->data = val; + return 1; + } + } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER && val >= 0) { + SET_RETURN_SIZE(p, sizeof(uint64_t)); /* Expected size */ + switch (p->data_size) { + case sizeof(uint32_t): + if (val <= UINT32_MAX) { + SET_RETURN_SIZE(p, sizeof(uint32_t)); + *(uint32_t *)p->data = (uint32_t)val; + return 1; + } + break; + case sizeof(uint64_t): + *(uint64_t *)p->data = (uint64_t)val; + return 1; + } + } else if (p->data_type == OSSL_PARAM_REAL) { + SET_RETURN_SIZE(p, sizeof(double)); + switch (p->data_size) { + case sizeof(double): + u64 = val < 0 ? -val : val; + if ((u64 >> 53) == 0) { /* 53 significant bits in the mantissa */ + *(double *)p->data = (double)val; + return 1; + } + break; + } } return 0; } @@ -280,18 +459,49 @@ OSSL_PARAM OSSL_PARAM_construct_int64(const char *key, int64_t *buf, int OSSL_PARAM_get_uint64(const OSSL_PARAM *p, uint64_t *val) { - if (val == NULL - || p == NULL - || (p->data_type != OSSL_PARAM_UNSIGNED_INTEGER)) + int32_t i32; + int64_t i64; + double d; + + if (val == NULL || p == NULL) return 0; - switch (p->data_size) { - case sizeof(uint32_t): - *val = (uint64_t)*(const uint32_t *)p->data; - return 1; - case sizeof(uint64_t): - *val = *(const uint64_t *)p->data; - return 1; + if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) { + switch (p->data_size) { + case sizeof(uint32_t): + *val = *(const uint32_t *)p->data; + return 1; + case sizeof(uint64_t): + *val = *(const uint64_t *)p->data; + return 1; + } + } else if (p->data_type == OSSL_PARAM_INTEGER) { + switch (p->data_size) { + case sizeof(int32_t): + i32 = *(const int32_t *)p->data; + if (i32 >= 0) { + *val = (uint64_t)i32; + return 1; + } + break; + case sizeof(int64_t): + i64 = *(const int64_t *)p->data; + if (i64 >= 0) { + *val = (uint64_t)i64; + return 1; + } + break; + } + } else if (p->data_type == OSSL_PARAM_REAL) { + switch (p->data_size) { + case sizeof(double): + d = *(const double *)p->data; + if (d >= 0 && d <= INT64_MAX && d == (uint64_t)d) { + *val = (uint64_t)d; + return 1; + } + break; + } } return 0; } @@ -301,15 +511,48 @@ int OSSL_PARAM_set_uint64(const OSSL_PARAM *p, uint64_t val) if (p == NULL) return 0; SET_RETURN_SIZE(p, 0); - if (p->data_type != OSSL_PARAM_UNSIGNED_INTEGER) - return 0; - SET_RETURN_SIZE(p, sizeof(uint64_t)); /* Minimum expected size */ - switch (p->data_size) { - case sizeof(uint64_t): - SET_RETURN_SIZE(p, sizeof(uint64_t)); - *(uint64_t *)p->data = val; - return 1; + if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) { + SET_RETURN_SIZE(p, sizeof(uint64_t)); /* Expected size */ + switch (p->data_size) { + case sizeof(uint32_t): + if (val <= UINT32_MAX) { + SET_RETURN_SIZE(p, sizeof(uint32_t)); + *(uint32_t *)p->data = (uint32_t)val; + return 1; + } + break; + case sizeof(uint64_t): + *(uint64_t *)p->data = val; + return 1; + } + } else if (p->data_type == OSSL_PARAM_INTEGER) { + SET_RETURN_SIZE(p, sizeof(int64_t)); /* Expected size */ + switch (p->data_size) { + case sizeof(int32_t): + if (val <= INT32_MAX) { + SET_RETURN_SIZE(p, sizeof(int32_t)); + *(int32_t *)p->data = (int32_t)val; + return 1; + } + break; + case sizeof(int64_t): + if (val <= INT64_MAX) { + *(int64_t *)p->data = (int64_t)val; + return 1; + } + break; + } + } else if (p->data_type == OSSL_PARAM_REAL) { + SET_RETURN_SIZE(p, sizeof(double)); + switch (p->data_size) { + case sizeof(double): + if ((val >> 53) == 0) { /* 53 significant bits in the mantissa */ + *(double *)p->data = (double)val; + return 1; + } + break; + } } return 0; } @@ -402,13 +645,45 @@ OSSL_PARAM OSSL_PARAM_construct_BN(const char *key, unsigned char *buf, int OSSL_PARAM_get_double(const OSSL_PARAM *p, double *val) { - if (val == NULL || p == NULL || p->data_type != OSSL_PARAM_REAL) + int64_t i64; + uint64_t u64; + + if (val == NULL || p == NULL) return 0; - switch (p->data_size) { - case sizeof(double): - *val = *(const double *)p->data; - return 1; + if (p->data_type == OSSL_PARAM_REAL) { + switch (p->data_size) { + case sizeof(double): + *val = *(const double *)p->data; + return 1; + } + } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) { + switch (p->data_size) { + case sizeof(uint32_t): + *val = *(const uint32_t *)p->data; + return 1; + case sizeof(uint64_t): + u64 = *(const uint64_t *)p->data; + if ((u64 >> 53) == 0) { /* 53 significant bits in the mantissa */ + *val = (double)u64; + return 1; + } + break; + } + } else if (p->data_type == OSSL_PARAM_INTEGER) { + switch (p->data_size) { + case sizeof(int32_t): + *val = *(const int32_t *)p->data; + return 1; + case sizeof(int64_t): + i64 = *(const int64_t *)p->data; + u64 = i64 < 0 ? -i64 : i64; + if ((u64 >> 53) == 0) { /* 53 significant bits in the mantissa */ + *val = 0.0 + i64; + return 1; + } + break; + } } return 0; } @@ -418,14 +693,50 @@ int OSSL_PARAM_set_double(const OSSL_PARAM *p, double val) if (p == NULL) return 0; SET_RETURN_SIZE(p, 0); - if (p->data_type != OSSL_PARAM_REAL) - return 0; - switch (p->data_size) { - case sizeof(double): + if (p->data_type == OSSL_PARAM_REAL) { SET_RETURN_SIZE(p, sizeof(double)); - *(double *)p->data = val; - return 1; + switch (p->data_size) { + case sizeof(double): + *(double *)p->data = val; + return 1; + } + } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER + && val == (uintmax_t)val) { + SET_RETURN_SIZE(p, sizeof(double)); + switch (p->data_size) { + case sizeof(uint32_t): + if (val >= 0 && val <= UINT32_MAX) { + SET_RETURN_SIZE(p, sizeof(uint32_t)); + *(uint32_t *)p->data = (uint32_t)val; + return 1; + } + break; + case sizeof(uint64_t): + if (val >= 0 && val <= UINT64_MAX) { + SET_RETURN_SIZE(p, sizeof(uint64_t)); + *(uint64_t *)p->data = (uint64_t)val; + return 1; + } + break; } + } else if (p->data_type == OSSL_PARAM_INTEGER && val == (intmax_t)val) { + SET_RETURN_SIZE(p, sizeof(double)); + switch (p->data_size) { + case sizeof(int32_t): + if (val >= INT32_MIN && val <= INT32_MAX) { + SET_RETURN_SIZE(p, sizeof(int32_t)); + *(int32_t *)p->data = (int32_t)val; + return 1; + } + break; + case sizeof(int64_t): + if (val >= INT64_MIN && val <= INT64_MAX) { + SET_RETURN_SIZE(p, sizeof(int64_t)); + *(int64_t *)p->data = (int64_t)val; + return 1; + } + break; + } } return 0; } diff --git a/doc/man3/OSSL_PARAM_TYPE.pod b/doc/man3/OSSL_PARAM_TYPE.pod index 4585f25..1b750b2 100644 --- a/doc/man3/OSSL_PARAM_TYPE.pod +++ b/doc/man3/OSSL_PARAM_TYPE.pod @@ -250,7 +250,8 @@ All other functions return B<1> on success and B<0> on failure. =head1 NOTES -Integral types will be widened and sign extended as required. +Native types will be converted as required only if the value is exactly +representable by the target type or parameter. Apart from that, the functions must be used appropriately for the expected type of the parameter. diff --git a/test/build.info b/test/build.info index 2800c71..5d8448f 100644 --- a/test/build.info +++ b/test/build.info @@ -34,7 +34,7 @@ IF[{- !$disabled{tests} -}] bftest ssltest_old dsatest dsa_no_digest_size_test exptest rsa_test \ evp_test evp_extra_test igetest v3nametest v3ext \ crltest danetest bad_dtls_test lhash_test sparse_array_test \ - conf_include_test params_api_test \ + conf_include_test params_api_test params_conversion_test \ constant_time_test verify_extra_test clienthellotest \ packettest asynctest secmemtest srptest memleaktest stack_test \ dtlsv1listentest ct_test threadstest afalgtest d2i_test \ @@ -314,6 +314,10 @@ IF[{- !$disabled{tests} -}] INCLUDE[params_api_test]=../include ../apps/include DEPEND[params_api_test]=../libcrypto libtestutil.a + SOURCE[params_conversion_test]=params_conversion_test.c + INCLUDE[params_conversion_test]=../include ../apps/include + DEPEND[params_conversion_test]=../libcrypto libtestutil.a + SOURCE[sslapitest]=sslapitest.c ssltestlib.c INCLUDE[sslapitest]=../include ../apps/include .. DEPEND[sslapitest]=../libcrypto ../libssl libtestutil.a diff --git a/test/params_conversion_test.c b/test/params_conversion_test.c new file mode 100644 index 0000000..96d0aaa --- /dev/null +++ b/test/params_conversion_test.c @@ -0,0 +1,334 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <string.h> +#include <inttypes.h> +#include <openssl/params.h> +#include "testutil.h" + +#ifdef OPENSSL_SYS_WINDOWS +# define strcasecmp _stricmp +#endif + +typedef struct { + const OSSL_PARAM *param; + int32_t i32; + int64_t i64; + uint32_t u32; + uint64_t u64; + double d; + int valid_i32, valid_i64, valid_u32, valid_u64, valid_d; + void *ref, *datum; + size_t size; +} PARAM_CONVERSION; + +static int param_conversion_load_stanza(PARAM_CONVERSION *pc, const STANZA *s) +{ + + static int32_t datum_i32, ref_i32; + static int64_t datum_i64, ref_i64; + static uint32_t datum_u32, ref_u32; + static uint64_t datum_u64, ref_u64; + static double datum_d, ref_d; + static const OSSL_PARAM params[] = { + OSSL_PARAM_int32("int32", &datum_i32), + OSSL_PARAM_int64("int64", &datum_i64), + OSSL_PARAM_uint32("uint32", &datum_u32), + OSSL_PARAM_uint64("uint64", &datum_u64), + OSSL_PARAM_double("double", &datum_d), + OSSL_PARAM_END + }; + int def_i32 = 0, def_i64 = 0, def_u32 = 0, def_u64 = 0, def_d = 0; + const PAIR *pp = s->pairs; + const char *type = NULL; + char *p; + int i; + + memset(pc, 0, sizeof(*pc)); + + for (i = 0; i < s->numpairs; i++, pp++) { + p = ""; + if (strcasecmp(pp->key, "type") == 0) { + if (type != NULL) { + TEST_info("Line %d: multiple type lines", s->curr); + return 0; + } + pc->param = OSSL_PARAM_locate(params, type = pp->value); + if (pc->param == NULL) { + TEST_info("Line %d: unknown type line", s->curr); + return 0; + } + } else if (strcasecmp(pp->key, "int32") == 0) { + if (def_i32++) { + TEST_info("Line %d: multiple int32 lines", s->curr); + return 0; + } + if (strcasecmp(pp->value, "invalid") != 0) { + pc->valid_i32 = 1; + pc->i32 = (int32_t)strtoimax(pp->value, &p, 10); + } + } else if (strcasecmp(pp->key, "int64") == 0) { + if (def_i64++) { + TEST_info("Line %d: multiple int64 lines", s->curr); + return 0; + } + if (strcasecmp(pp->value, "invalid") != 0) { + pc->valid_i64 = 1; + pc->i64 = (int64_t)strtoimax(pp->value, &p, 10); + } + } else if (strcasecmp(pp->key, "uint32") == 0) { + if (def_u32++) { + TEST_info("Line %d: multiple uint32 lines", s->curr); + return 0; + } + if (strcasecmp(pp->value, "invalid") != 0) { + pc->valid_u32 = 1; + pc->u32 = (uint32_t)strtoumax(pp->value, &p, 10); + } + } else if (strcasecmp(pp->key, "uint64") == 0) { + if (def_u64++) { + TEST_info("Line %d: multiple uint64 lines", s->curr); + return 0; + } + if (strcasecmp(pp->value, "invalid") != 0) { + pc->valid_u64 = 1; + pc->u64 = (uint64_t)strtoumax(pp->value, &p, 10); + } + } else if (strcasecmp(pp->key, "double") == 0) { + if (def_d++) { + TEST_info("Line %d: multiple double lines", s->curr); + return 0; + } + if (strcasecmp(pp->value, "invalid") != 0) { + pc->valid_d = 1; + pc->d = strtod(pp->value, &p); + } + } else { + TEST_info("Line %d: unknown keyword %s", s->curr, pp->key); + return 0; + } + if (*p != '\0') { + TEST_info("Line %d: extra characters at end '%s' for %s", + s->curr, p, pp->key); + return 0; + } + } + + if (!TEST_ptr(type)) { + TEST_info("Line %d: type not found", s->curr); + return 0; + } + + if (strcasecmp(type, "int32") == 0) { + if (!TEST_true(def_i32) || !TEST_true(pc->valid_i32)) { + TEST_note("errant int32 on line %d", s->curr); + return 0; + } + datum_i32 = ref_i32 = pc->i32; + pc->datum = &datum_i32; + pc->ref = &ref_i32; + pc->size = sizeof(ref_i32); + } else if (strcasecmp(type, "int64") == 0) { + if (!TEST_true(def_i64) || !TEST_true(pc->valid_i64)) { + TEST_note("errant int64 on line %d", s->curr); + return 0; + } + datum_i64 = ref_i64 = pc->i64; + pc->datum = &datum_i64; + pc->ref = &ref_i64; + pc->size = sizeof(ref_i64); + } else if (strcasecmp(type, "uint32") == 0) { + if (!TEST_true(def_u32) || !TEST_true(pc->valid_u32)) { + TEST_note("errant uint32 on line %d", s->curr); + return 0; + } + datum_u32 = ref_u32 = pc->u32; + pc->datum = &datum_u32; + pc->ref = &ref_u32; + pc->size = sizeof(ref_u32); + } else if (strcasecmp(type, "uint64") == 0) { + if (!TEST_true(def_u64) || !TEST_true(pc->valid_u64)) { + TEST_note("errant uint64 on line %d", s->curr); + return 0; + } + datum_u64 = ref_u64 = pc->u64; + pc->datum = &datum_u64; + pc->ref = &ref_u64; + pc->size = sizeof(ref_u64); + } else if (strcasecmp(type, "double") == 0) { + if (!TEST_true(def_d) || !TEST_true(pc->valid_d)) { + TEST_note("errant double on line %d", s->curr); + return 0; + } + datum_d = ref_d = pc->d; + pc->datum = &datum_d; + pc->ref = &ref_d; + pc->size = sizeof(ref_d); + } else { + TEST_error("type unknown at line %d", s->curr); + return 0; + } + return 1; +} + +static int param_conversion_test(const PARAM_CONVERSION *pc, int line) +{ + int32_t i32; + int64_t i64; + uint32_t u32; + uint64_t u64; + double d; + + if (!pc->valid_i32) { + if (!TEST_false(OSSL_PARAM_get_int32(pc->param, &i32))) { + TEST_note("unexpected valid conversion to int32 on line %d", line); + return 0; + } + } else { + if (!TEST_true(OSSL_PARAM_get_int32(pc->param, &i32)) + || !TEST_true(i32 == pc->i32)) { + TEST_note("unexpected conversion to int32 on line %d", line); + return 0; + } + memset(pc->datum, 44, pc->size); + if (!TEST_true(OSSL_PARAM_set_int32(pc->param, i32)) + || !TEST_mem_eq(pc->datum, pc->size, pc->ref, pc->size)) { + TEST_note("unexpected valid conversion from int32 on line %d", + line); + return 0; + } + } + + if (!pc->valid_i64) { + if (!TEST_false(OSSL_PARAM_get_int64(pc->param, &i64))) { + TEST_note("unexpected valid conversion to int64 on line %d", line); + return 0; + } + } else { + if (!TEST_true(OSSL_PARAM_get_int64(pc->param, &i64)) + || !TEST_true(i64 == pc->i64)) { + TEST_note("unexpected conversion to int64 on line %d", line); + return 0; + } + memset(pc->datum, 44, pc->size); + if (!TEST_true(OSSL_PARAM_set_int64(pc->param, i64)) + || !TEST_mem_eq(pc->datum, pc->size, pc->ref, pc->size)) { + TEST_note("unexpected valid conversion from int64 on line %d", + line); + return 0; + } + } + + if (!pc->valid_u32) { + if (!TEST_false(OSSL_PARAM_get_uint32(pc->param, &u32))) { + TEST_note("unexpected valid conversion to uint32 on line %d", line); + return 0; + } + } else { + if (!TEST_true(OSSL_PARAM_get_uint32(pc->param, &u32)) + || !TEST_true(u32 == pc->u32)) { + TEST_note("unexpected conversion to uint32 on line %d", line); + return 0; + } + memset(pc->datum, 44, pc->size); + if (!TEST_true(OSSL_PARAM_set_uint32(pc->param, u32)) + || !TEST_mem_eq(pc->datum, pc->size, pc->ref, pc->size)) { + TEST_note("unexpected valid conversion from uint32 on line %d", + line); + return 0; + } + } + + if (!pc->valid_u64) { + if (!TEST_false(OSSL_PARAM_get_uint64(pc->param, &u64))) { + TEST_note("unexpected valid conversion to uint64 on line %d", line); + return 0; + } + } else { + if (!TEST_true(OSSL_PARAM_get_uint64(pc->param, &u64)) + || !TEST_true(u64 == pc->u64)) { + TEST_note("unexpected conversion to uint64 on line %d", line); + return 0; + } + memset(pc->datum, 44, pc->size); + if (!TEST_true(OSSL_PARAM_set_uint64(pc->param, u64)) + || !TEST_mem_eq(pc->datum, pc->size, pc->ref, pc->size)) { + TEST_note("unexpected valid conversion from uint64 on line %d", + line); + return 0; + } + } + + if (!pc->valid_d) { + if (!TEST_false(OSSL_PARAM_get_double(pc->param, &d))) { + TEST_note("unexpected valid conversion to double on line %d", line); + return 0; + } + } else { + if (!TEST_true(OSSL_PARAM_get_double(pc->param, &d)) + || !TEST_true(d == pc->d)) { + TEST_note("unexpected conversion to double on line %d", line); + return 0; + } + memset(pc->datum, 44, pc->size); + if (!TEST_true(OSSL_PARAM_set_double(pc->param, d)) + || !TEST_mem_eq(pc->datum, pc->size, pc->ref, pc->size)) { + TEST_note("unexpected valid conversion from double on line %d", + line); + return 0; + } + } + + return 1; +} + +static int run_param_file_tests(int i) +{ + STANZA *s; + PARAM_CONVERSION pc; + const char *testfile = test_get_argument(i); + int res = 1; + + if (!TEST_ptr(s = OPENSSL_zalloc(sizeof(*s)))) + return 0; + if (!test_start_file(s, testfile)) { + OPENSSL_free(s); + return 0; + } + + while (!BIO_eof(s->fp)) { + if (!test_readstanza(s)) { + res = 0; + goto end; + } + if (s->numpairs != 0) + if (!param_conversion_load_stanza(&pc, s) + || !param_conversion_test(&pc, s->curr)) + res = 0; + test_clearstanza(s); + } +end: + test_end_file(s); + OPENSSL_free(s); + return res; +} + +OPT_TEST_DECLARE_USAGE("file...\n") + +int setup_tests(void) +{ + size_t n = test_get_argument_count(); + + if (n == 0) + return 0; + + ADD_ALL_TESTS(run_param_file_tests, n); + return 1; +} diff --git a/test/recipes/04-test_provider.t b/test/recipes/04-test_params_conversion.t similarity index 54% copy from test/recipes/04-test_provider.t copy to test/recipes/04-test_params_conversion.t index 9195a42..d15df84 100644 --- a/test/recipes/04-test_provider.t +++ b/test/recipes/04-test_params_conversion.t @@ -7,12 +7,17 @@ # https://www.openssl.org/source/license.html use strict; -use OpenSSL::Test qw(:DEFAULT bldtop_dir); -use OpenSSL::Test::Simple; -use OpenSSL::Test::Utils; +use warnings; -setup("test_provider"); +use OpenSSL::Test qw/:DEFAULT data_file/; -$ENV{"OPENSSL_MODULES"} = bldtop_dir("test"); +setup("test_params_conversion"); -simple_test("test_provider", "provider_test"); +my @files = ( "native_types.txt" ); + +plan tests => scalar(@files); + +foreach my $f ( @files ) { + ok(run(test(["params_conversion_test", data_file("$f")])), + "running params_conversion_test $f"); +} diff --git a/test/recipes/04-test_params_conversion_data/native_types.txt b/test/recipes/04-test_params_conversion_data/native_types.txt new file mode 100644 index 0000000..233a584 --- /dev/null +++ b/test/recipes/04-test_params_conversion_data/native_types.txt @@ -0,0 +1,343 @@ +type=int32 +int32=0 +int64=0 +uint32=0 +uint64=0 +double=0 + +type=int32 +int32=6 +int64=6 +uint32=6 +uint64=6 +double=6 + +type=int32 +int32=-6 +int64=-6 +uint32=invalid +uint64=invalid +double=-6 + + +type=uint32 +int32=0 +int64=0 +uint32=0 +uint64=0 +double=0 + +type=uint32 +int32=6 +int64=6 +uint32=6 +uint64=6 +double=6 + +# 2^31-1 +type=uint32 +int32=2147483647 +int64=2147483647 +uint32=2147483647 +uint64=2147483647 +double=2147483647 + +# 2^31 +type=uint32 +int32=invalid +int64=2147483648 +uint32=2147483648 +uint64=2147483648 +double=2147483648 + + +type=int64 +int32=6 +int64=6 +uint32=6 +uint64=6 +double=6 + +type=int64 +int32=-6 +int64=-6 +uint32=invalid +uint64=invalid +double=-6 + +# 2^31-1 +type=int64 +int32=2147483647 +int64=2147483647 +uint32=2147483647 +uint64=2147483647 +double=2147483647 + +# 2^31 +type=int64 +int32=invalid +int64=2147483648 +uint32=2147483648 +uint64=2147483648 +double=2147483648 + +# -2^31+1 +type=int64 +int32=-2147483647 +int64=-2147483647 +uint32=invalid +uint64=invalid +double=-2147483647 + +# -2^31 +type=int64 +int32=-2147483648 +int64=-2147483648 +uint32=invalid +uint64=invalid +double=-2147483648 + +# -2^31-1 +type=int64 +int32=invalid +int64=-2147483649 +uint32=invalid +uint64=invalid +double=-2147483649 + +# 2^32-1 +type=int64 +int32=invalid +int64=4294967295 +uint32=4294967295 +uint64=4294967295 +double=4294967295 + +# 2^32 +type=int64 +int32=invalid +int64=4294967296 +uint32=invalid +uint64=4294967296 +double=4294967296 + +# -2^32 +type=int64 +int32=invalid +int64=-4294967296 +uint32=invalid +uint64=invalid +double=-4294967296 + +# 2^53-1 +type=int64 +int32=invalid +int64=9007199254740991 +uint32=invalid +uint64=9007199254740991 +double=9007199254740991 + +# 2^53 +type=int64 +int32=invalid +int64=9007199254740992 +uint32=invalid +uint64=9007199254740992 +double=invalid + +# -2^53-1 +type=int64 +int32=invalid +int64=-9007199254740991 +uint32=invalid +uint64=invalid +double=-9007199254740991 + +# -2^53 +type=int64 +int32=invalid +int64=-9007199254740992 +uint32=invalid +uint64=invalid +double=invalid + + +type=uint64 +int32=6 +int64=6 +uint32=6 +uint64=6 +double=6 + +# 2^31-1 +type=uint64 +int32=2147483647 +int64=2147483647 +uint32=2147483647 +uint64=2147483647 +double=2147483647 + +# 2^31 +type=uint64 +int32=invalid +int64=2147483648 +uint32=2147483648 +uint64=2147483648 +double=2147483648 + +# 2^32-1 +type=uint64 +int32=invalid +int64=4294967295 +uint32=4294967295 +uint64=4294967295 +double=4294967295 + +# 2^32 +type=uint64 +int32=invalid +int64=4294967296 +uint32=invalid +uint64=4294967296 +double=4294967296 + +# 2^53-1 +type=uint64 +int32=invalid +int64=9007199254740991 +uint32=invalid +uint64=9007199254740991 +double=9007199254740991 + +# 2^53 +type=uint64 +int32=invalid +int64=9007199254740992 +uint32=invalid +uint64=9007199254740992 +double=invalid + +# 2^63-1 +type=uint64 +int32=invalid +int64=9223372036854775807 +uint32=invalid +uint64=9223372036854775807 +double=invalid + +# 2^63-1 +type=uint64 +int32=invalid +int64=invalid +uint32=invalid +uint64=9223372036854775808 +double=invalid + +type=double +int32=0 +int64=0 +uint32=0 +uint64=0 +double=0 + +type=double +int32=6 +int64=6 +uint32=6 +uint64=6 +double=6 + +type=double +int32=-6 +int64=-6 +uint32=invalid +uint64=invalid +double=-6 + +# -2^31 +type=double +int32=-2147483648 +int64=-2147483648 +uint32=invalid +uint64=invalid +double=-2147483648 + +# -2^31-1 +type=double +int32=invalid +int64=-2147483649 +uint32=invalid +uint64=invalid +double=-2147483649 + +# 2^32-1 +type=double +int32=invalid +int64=4294967295 +uint32=4294967295 +uint64=4294967295 +double=4294967295 + +# 2^32 +type=double +int32=invalid +int64=4294967296 +uint32=invalid +uint64=4294967296 +double=4294967296 + +# -2^32 +type=double +int32=invalid +int64=-4294967296 +uint32=invalid +uint64=invalid +double=-4294967296 + +# 2^53-1 +type=double +int32=invalid +int64=9007199254740991 +uint32=invalid +uint64=9007199254740991 +double=9007199254740991 + +# -2^53+1 +type=double +int32=invalid +int64=-9007199254740991 +uint32=invalid +uint64=invalid +double=-9007199254740991 + +# big +type=double +int32=invalid +int64=invalid +uint32=invalid +uint64=invalid +double=1e100 + +# big +type=double +int32=invalid +int64=invalid +uint32=invalid +uint64=invalid +double=-1e100 + +# infinite +type=double +int32=invalid +int64=invalid +uint32=invalid +uint64=invalid +double=inf + +# fractional +type=double +int32=invalid +int64=invalid +uint32=invalid +uint64=invalid +double=0.5