提交 b86d57bb 编写于 作者: A Andy Polyakov

crypto/cryptlib.c: make OPENSS_cpuid_setup safe to use as constructor.

Reviewed-by: NKurt Roeckx <kurt@roeckx.be>
(Merged from https://github.com/openssl/openssl/pull/6752)
上级 f529b5cf
...@@ -19,29 +19,97 @@ ...@@ -19,29 +19,97 @@
extern unsigned int OPENSSL_ia32cap_P[4]; extern unsigned int OPENSSL_ia32cap_P[4];
# if defined(OPENSSL_CPUID_OBJ) && !defined(OPENSSL_NO_ASM) && !defined(I386_ONLY) # if defined(OPENSSL_CPUID_OBJ) && !defined(OPENSSL_NO_ASM) && !defined(I386_ONLY)
#include <stdio.h>
/*
* Purpose of these minimalistic and character-type-agnostic subroutines
* is to break dependency on MSVCRT (on Windows) and locale. This makes
* OPENSSL_cpuid_setup safe to use as "constructor". "Character-type-
* agnostic" means that they work with either wide or 8-bit characters,
* exploiting the fact that first 127 characters can be simply casted
* between the sets, while the rest would be simply rejected by ossl_is*
* subroutines.
*/
# ifdef _WIN32
typedef WCHAR variant_char;
static variant_char *ossl_getenv(const char *name)
{
/*
* Since we pull only one environment variable, it's simpler to
* to just ignore |name| and use equivalent wide-char L-literal.
* As well as to ignore excessively long values...
*/
static WCHAR value[48];
DWORD len = GetEnvironmentVariableW(L"OPENSSL_ia32cap", value, 48);
return (len > 0 && len < 48) ? value : NULL;
}
# else
typedef char variant_char;
# define ossl_getenv getenv
# endif
# include "internal/ctype.h"
static int todigit(variant_char c)
{
if (ossl_isdigit(c))
return c - '0';
else if (ossl_isxdigit(c))
return ossl_tolower(c) - 'a' + 10;
/* return largest base value to make caller terminate the loop */
return 16;
}
static uint64_t ossl_strtouint64(const variant_char *str)
{
uint64_t ret = 0;
unsigned int digit, base = 10;
if (*str == '0') {
base = 8, str++;
if (ossl_tolower(*str) == 'x')
base = 16, str++;
}
while((digit = todigit(*str++)) < base)
ret = ret * base + digit;
return ret;
}
static variant_char *ossl_strchr(const variant_char *str, char srch)
{ variant_char c;
while((c = *str)) {
if (c == srch)
return (variant_char *)str;
str++;
}
return NULL;
}
# define OPENSSL_CPUID_SETUP # define OPENSSL_CPUID_SETUP
typedef uint64_t IA32CAP; typedef uint64_t IA32CAP;
void OPENSSL_cpuid_setup(void) void OPENSSL_cpuid_setup(void)
{ {
static int trigger = 0; static int trigger = 0;
IA32CAP OPENSSL_ia32_cpuid(unsigned int *); IA32CAP OPENSSL_ia32_cpuid(unsigned int *);
IA32CAP vec; IA32CAP vec;
char *env; const variant_char *env;
if (trigger) if (trigger)
return; return;
trigger = 1; trigger = 1;
if ((env = getenv("OPENSSL_ia32cap"))) { if ((env = ossl_getenv("OPENSSL_ia32cap")) != NULL) {
int off = (env[0] == '~') ? 1 : 0; int off = (env[0] == '~') ? 1 : 0;
# if defined(_WIN32)
if (!sscanf(env + off, "%I64i", &vec)) vec = ossl_strtouint64(env + off);
vec = strtoul(env + off, NULL, 0);
# else
if (!sscanf(env + off, "%lli", (long long *)&vec))
vec = strtoul(env + off, NULL, 0);
# endif
if (off) { if (off) {
IA32CAP mask = vec; IA32CAP mask = vec;
vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P) & ~mask; vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P) & ~mask;
...@@ -60,17 +128,12 @@ void OPENSSL_cpuid_setup(void) ...@@ -60,17 +128,12 @@ void OPENSSL_cpuid_setup(void)
vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P); vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P);
} }
if ((env = strchr(env, ':'))) { if ((env = ossl_strchr(env, ':')) != NULL) {
IA32CAP vecx; IA32CAP vecx;
env++; env++;
off = (env[0] == '~') ? 1 : 0; off = (env[0] == '~') ? 1 : 0;
# if defined(_WIN32) vecx = ossl_strtouint64(env + off);
if (!sscanf(env + off, "%I64i", &vecx))
vecx = strtoul(env + off, NULL, 0);
# else
if (!sscanf(env + off, "%lli", (long long *)&vecx))
vecx = strtoul(env + off, NULL, 0);
# endif
if (off) { if (off) {
OPENSSL_ia32cap_P[2] &= ~(unsigned int)vecx; OPENSSL_ia32cap_P[2] &= ~(unsigned int)vecx;
OPENSSL_ia32cap_P[3] &= ~(unsigned int)(vecx >> 32); OPENSSL_ia32cap_P[3] &= ~(unsigned int)(vecx >> 32);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册