X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fo_str.c;h=6780188cda273459cee3df6ee2f16e70eb41c256;hp=b0e7524820ce4af5555f101ab7c5b00416482cf4;hb=bacaa618c26411d212015493d0eb82076a3e76a1;hpb=efdb2d6c797112e58e304d3e5300f169dbb16e95 diff --git a/crypto/o_str.c b/crypto/o_str.c index b0e7524820..6780188cda 100644 --- a/crypto/o_str.c +++ b/crypto/o_str.c @@ -1,84 +1,26 @@ /* - * Copyright 2003-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2003-2017 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 +#include "e_os.h" #include -#include #include #include "internal/cryptlib.h" -#include "internal/o_str.h" - -#if !defined(OPENSSL_IMPLEMENTS_strncasecmp) && \ - !defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_SYS_WINCE) && \ - !defined(NETWARE_CLIB) -# include -#endif - -int OPENSSL_strncasecmp(const char *str1, const char *str2, size_t n) -{ -#if defined(OPENSSL_IMPLEMENTS_strncasecmp) - while (*str1 && *str2 && n) { - int res = toupper(*str1) - toupper(*str2); - if (res) - return res < 0 ? -1 : 1; - str1++; - str2++; - n--; - } - if (n == 0) - return 0; - if (*str1) - return 1; - if (*str2) - return -1; - return 0; -#else - /* - * Recursion hazard warning! Whenever strncasecmp is #defined as - * OPENSSL_strncasecmp, OPENSSL_IMPLEMENTS_strncasecmp must be defined as - * well. - */ - return strncasecmp(str1, str2, n); -#endif -} - -int OPENSSL_strcasecmp(const char *str1, const char *str2) -{ -#if defined(OPENSSL_IMPLEMENTS_strncasecmp) - return OPENSSL_strncasecmp(str1, str2, (size_t)-1); -#else - return strcasecmp(str1, str2); -#endif -} - -int OPENSSL_memcmp(const void *v1, const void *v2, size_t n) -{ - const unsigned char *c1 = v1, *c2 = v2; - int ret = 0; - - while (n && (ret = *c1 - *c2) == 0) - n--, c1++, c2++; - - return ret; -} char *CRYPTO_strdup(const char *str, const char* file, int line) { char *ret; - size_t size; if (str == NULL) return NULL; - size = strlen(str) + 1; - ret = CRYPTO_malloc(size, file, line); + ret = CRYPTO_malloc(strlen(str) + 1, file, line); if (ret != NULL) - memcpy(ret, str, size); + strcpy(ret, str); return ret; } @@ -190,73 +132,125 @@ int OPENSSL_hexchar2int(unsigned char c) /* * Give a string of hex digits convert to a buffer */ -unsigned char *OPENSSL_hexstr2buf(const char *str, long *len) +int OPENSSL_hexstr2buf_ex(unsigned char *buf, size_t buf_n, size_t *buflen, + const char *str) { - unsigned char *hexbuf, *q; + unsigned char *q; unsigned char ch, cl; int chi, cli; const unsigned char *p; - size_t s; + size_t cnt; - s = strlen(str); - if ((hexbuf = OPENSSL_malloc(s >> 1)) == NULL) { - CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF, ERR_R_MALLOC_FAILURE); - return NULL; - } - for (p = (const unsigned char *)str, q = hexbuf; *p; ) { + for (p = (const unsigned char *)str, q = buf, cnt = 0; *p; ) { ch = *p++; if (ch == ':') continue; cl = *p++; if (!cl) { - CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF, + CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF_EX, CRYPTO_R_ODD_NUMBER_OF_DIGITS); - OPENSSL_free(hexbuf); - return NULL; + return 0; } cli = OPENSSL_hexchar2int(cl); chi = OPENSSL_hexchar2int(ch); if (cli < 0 || chi < 0) { - OPENSSL_free(hexbuf); - CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF, CRYPTO_R_ILLEGAL_HEX_DIGIT); - return NULL; + CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF_EX, + CRYPTO_R_ILLEGAL_HEX_DIGIT); + return 0; + } + cnt++; + if (q != NULL) { + if (cnt > buf_n) { + CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF_EX, + CRYPTO_R_TOO_SMALL_BUFFER); + return 0; + } + *q++ = (unsigned char)((chi << 4) | cli); } - *q++ = (unsigned char)((chi << 4) | cli); } - if (len) - *len = q - hexbuf; - return hexbuf; + if (buflen != NULL) + *buflen = cnt; + return 1; } -/* - * Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its - * hex representation @@@ (Contents of buffer are always kept in ASCII, also - * on EBCDIC machines) - */ -char *OPENSSL_buf2hexstr(const unsigned char *buffer, long len) +unsigned char *OPENSSL_hexstr2buf(const char *str, long *buflen) { - const static char hexdig[] = "0123456789ABCDEF"; - char *tmp, *q; - const unsigned char *p; - int i; + unsigned char *buf; + size_t buf_n, tmp_buflen; - if ((tmp = OPENSSL_malloc(len * 3 + 1)) == NULL) { - CRYPTOerr(CRYPTO_F_OPENSSL_BUF2HEXSTR, ERR_R_MALLOC_FAILURE); + buf_n = strlen(str) >> 1; + if ((buf = OPENSSL_malloc(buf_n)) == NULL) { + CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF, ERR_R_MALLOC_FAILURE); return NULL; } - q = tmp; - for (i = 0, p = buffer; i < len; i++, p++) { + + if (buflen != NULL) + *buflen = 0; + tmp_buflen = 0; + if (OPENSSL_hexstr2buf_ex(buf, buf_n, &tmp_buflen, str)) { + if (buflen != NULL) + *buflen = (long)tmp_buflen; + return buf; + } + OPENSSL_free(buf); + return NULL; +} + +int OPENSSL_buf2hexstr_ex(char *str, size_t str_n, size_t *strlen, + const unsigned char *buf, size_t buflen) +{ + static const char hexdig[] = "0123456789ABCDEF"; + const unsigned char *p; + char *q; + size_t i; + + if (strlen != NULL) + *strlen = buflen * 3; + if (str == NULL) + return 1; + + if (str_n < (unsigned long)buflen * 3) { + CRYPTOerr(CRYPTO_F_OPENSSL_BUF2HEXSTR_EX, CRYPTO_R_TOO_SMALL_BUFFER); + return 0; + } + + q = str; + for (i = 0, p = buf; i < buflen; i++, p++) { *q++ = hexdig[(*p >> 4) & 0xf]; *q++ = hexdig[*p & 0xf]; *q++ = ':'; } q[-1] = 0; #ifdef CHARSET_EBCDIC - ebcdic2ascii(tmp, tmp, q - tmp - 1); + ebcdic2ascii(str, str, q - str - 1); #endif + return 1; +} + +/* + * Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its + * hex representation @@@ (Contents of buffer are always kept in ASCII, also + * on EBCDIC machines) + */ +char *OPENSSL_buf2hexstr(const unsigned char *buf, long buflen) +{ + char *tmp; + size_t tmp_n; + + if (buflen == 0) + return OPENSSL_zalloc(1); + + tmp_n = buflen * 3; + if ((tmp = OPENSSL_malloc(tmp_n)) == NULL) { + CRYPTOerr(CRYPTO_F_OPENSSL_BUF2HEXSTR, ERR_R_MALLOC_FAILURE); + return NULL; + } - return tmp; + if (OPENSSL_buf2hexstr_ex(tmp, tmp_n, NULL, buf, buflen)) + return tmp; + OPENSSL_free(tmp); + return NULL; } int openssl_strerror_r(int errnum, char *buf, size_t buflen) @@ -264,8 +258,28 @@ int openssl_strerror_r(int errnum, char *buf, size_t buflen) #if defined(_MSC_VER) && _MSC_VER>=1400 return !strerror_s(buf, buflen, errnum); #elif defined(_GNU_SOURCE) - return strerror_r(errnum, buf, buflen) != NULL; -#elif (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) + char *err; + + /* + * GNU strerror_r may not actually set buf. + * It can return a pointer to some (immutable) static string in which case + * buf is left unused. + */ + err = strerror_r(errnum, buf, buflen); + if (err == NULL || buflen == 0) + return 0; + /* + * If err is statically allocated, err != buf and we need to copy the data. + * If err points somewhere inside buf, OPENSSL_strlcpy can handle this, + * since src and dest are not annotated with __restrict and the function + * reads src byte for byte and writes to dest. + * If err == buf we do not have to copy anything. + */ + if (err != buf) + OPENSSL_strlcpy(buf, err, buflen); + return 1; +#elif (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || \ + (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600) /* * We can use "real" strerror_r. The OpenSSL version differs in that it * gives 1 on success and 0 on failure for consistency with other OpenSSL @@ -274,6 +288,7 @@ int openssl_strerror_r(int errnum, char *buf, size_t buflen) return !strerror_r(errnum, buf, buflen); #else char *err; + /* Fall back to non-thread safe strerror()...its all we can do */ if (buflen < 2) return 0; @@ -281,8 +296,7 @@ int openssl_strerror_r(int errnum, char *buf, size_t buflen) /* Can this ever happen? */ if (err == NULL) return 0; - strncpy(buf, err, buflen - 1); - buf[buflen - 1] = '\0'; + OPENSSL_strlcpy(buf, err, buflen); return 1; #endif }