X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=crypto%2FLPdir_win.c;h=8f674d305b74b75adfdfc81f287a6760a435f051;hb=c62ee12574e661a111238954b07ea1d5f0786bec;hp=4ff514f8856bac927b97afbe84020d33906a137c;hpb=16f8d4ebf0fd4847fa83d9c61f4150273cb4f533;p=oweals%2Fopenssl.git diff --git a/crypto/LPdir_win.c b/crypto/LPdir_win.c index 4ff514f885..8f674d305b 100644 --- a/crypto/LPdir_win.c +++ b/crypto/LPdir_win.c @@ -1,3 +1,12 @@ +/* + * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (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 + */ + /* * Copyright (c) 2004, Richard Levitte * All rights reserved. @@ -23,8 +32,10 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + #include #include +#include "internal/numbers.h" #ifndef LPDIR_H # include "LPdir.h" #endif @@ -45,6 +56,12 @@ # define NAME_MAX 255 #endif +#ifdef CP_UTF8 +# define CP_DEFAULT CP_UTF8 +#else +# define CP_DEFAULT CP_ACP +#endif + struct LP_dir_context_st { WIN32_FIND_DATA ctx; HANDLE handle; @@ -60,11 +77,9 @@ const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory) errno = 0; if (*ctx == NULL) { - const char *extdir = directory; - char *extdirbuf = NULL; size_t dirlen = strlen(directory); - if (dirlen == 0) { + if (dirlen == 0 || dirlen > INT_MAX - 3) { errno = ENOENT; return 0; } @@ -76,50 +91,76 @@ const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory) } memset(*ctx, 0, sizeof(**ctx)); - if (directory[dirlen - 1] != '*') { - extdirbuf = (char *)malloc(dirlen + 3); - if (extdirbuf == NULL) { - free(*ctx); - *ctx = NULL; - errno = ENOMEM; - return 0; - } - if (directory[dirlen - 1] != '/' && directory[dirlen - 1] != '\\') - extdir = strcat(strcpy(extdirbuf, directory), "/*"); - else - extdir = strcat(strcpy(extdirbuf, directory), "*"); - } - if (sizeof(TCHAR) != sizeof(char)) { TCHAR *wdir = NULL; /* len_0 denotes string length *with* trailing 0 */ - size_t index = 0, len_0 = strlen(extdir) + 1; - - wdir = (TCHAR *)calloc(len_0, sizeof(TCHAR)); - if (wdir == NULL) { - if (extdirbuf != NULL) { - free(extdirbuf); - } - free(*ctx); - *ctx = NULL; - errno = ENOMEM; - return 0; - } + size_t index = 0, len_0 = dirlen + 1; #ifdef LP_MULTIBYTE_AVAILABLE - if (!MultiByteToWideChar - (CP_ACP, 0, extdir, len_0, (WCHAR *)wdir, len_0)) + int sz = 0; + UINT cp; + + do { +# ifdef CP_UTF8 + if ((sz = MultiByteToWideChar((cp = CP_UTF8), 0, + directory, len_0, + NULL, 0)) > 0 || + GetLastError() != ERROR_NO_UNICODE_TRANSLATION) + break; +# endif + sz = MultiByteToWideChar((cp = CP_ACP), 0, + directory, len_0, + NULL, 0); + } while (0); + + if (sz > 0) { + /* + * allocate two additional characters in case we need to + * concatenate asterisk, |sz| covers trailing '\0'! + */ + wdir = _alloca((sz + 2) * sizeof(TCHAR)); + if (!MultiByteToWideChar(cp, 0, directory, len_0, + (WCHAR *)wdir, sz)) { + free(*ctx); + *ctx = NULL; + errno = EINVAL; + return 0; + } + } else #endif + { + sz = len_0; + /* + * allocate two additional characters in case we need to + * concatenate asterisk, |sz| covers trailing '\0'! + */ + wdir = _alloca((sz + 2) * sizeof(TCHAR)); for (index = 0; index < len_0; index++) - wdir[index] = (TCHAR)extdir[index]; + wdir[index] = (TCHAR)directory[index]; + } - (*ctx)->handle = FindFirstFile(wdir, &(*ctx)->ctx); + sz--; /* wdir[sz] is trailing '\0' now */ + if (wdir[sz - 1] != TEXT('*')) { + if (wdir[sz - 1] != TEXT('/') && wdir[sz - 1] != TEXT('\\')) + _tcscpy(wdir + sz, TEXT("/*")); + else + _tcscpy(wdir + sz, TEXT("*")); + } - free(wdir); + (*ctx)->handle = FindFirstFile(wdir, &(*ctx)->ctx); } else { - (*ctx)->handle = FindFirstFile((TCHAR *)extdir, &(*ctx)->ctx); - } - if (extdirbuf != NULL) { - free(extdirbuf); + if (directory[dirlen - 1] != '*') { + char *buf = _alloca(dirlen + 3); + + strcpy(buf, directory); + if (buf[dirlen - 1] != '/' && buf[dirlen - 1] != '\\') + strcpy(buf + dirlen, "/*"); + else + strcpy(buf + dirlen, "*"); + + directory = buf; + } + + (*ctx)->handle = FindFirstFile((TCHAR *)directory, &(*ctx)->ctx); } if ((*ctx)->handle == INVALID_HANDLE_VALUE) { @@ -142,9 +183,9 @@ const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory) len_0++; #ifdef LP_MULTIBYTE_AVAILABLE - if (!WideCharToMultiByte - (CP_ACP, 0, (WCHAR *)wdir, len_0, (*ctx)->entry_name, - sizeof((*ctx)->entry_name), NULL, 0)) + if (!WideCharToMultiByte(CP_DEFAULT, 0, (WCHAR *)wdir, len_0, + (*ctx)->entry_name, + sizeof((*ctx)->entry_name), NULL, 0)) #endif for (index = 0; index < len_0; index++) (*ctx)->entry_name[index] = (char)wdir[index];