X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2FLPdir_win.c;h=1dc1ef122c0c460d53b898fe7fa7c21028cbc758;hp=37cca97c40276db387147184b640c5ce454c5929;hb=ba476aa32c2de4c652f2fdb148981f7d1ea6cae1;hpb=42306f9a93489e1f789468c1220b68903424556d diff --git a/crypto/LPdir_win.c b/crypto/LPdir_win.c index 37cca97c40..1dc1ef122c 100644 --- a/crypto/LPdir_win.c +++ b/crypto/LPdir_win.c @@ -8,6 +8,9 @@ */ /* + * This file is dual-licensed and is also available under the following + * terms: + * * Copyright (c) 2004, Richard Levitte * All rights reserved. * @@ -35,6 +38,7 @@ #include #include +#include "internal/numbers.h" #ifndef LPDIR_H # include "LPdir.h" #endif @@ -55,6 +59,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; @@ -70,11 +80,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; } @@ -86,50 +94,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) { @@ -152,9 +186,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];