Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2008-12-02 14:40:13 +0300
committerCorinna Vinschen <corinna@vinschen.de>2008-12-02 14:40:13 +0300
commit651d8393c8083a255f2a36f45f2f813146cf98c4 (patch)
tree597470c78aa7a426dd923235b8ed87b413d9d141 /winsup/cygwin/fhandler_registry.cc
parentc4f3555ecb7aa109e01f33cb9147211c5bb0662c (diff)
* fhandler_registry.cc (must_encode): New function.
(encode_regname): Ditto. (decode_regname): Ditto. (fhandler_registry::exists): Encode name before path compare. (fhandler_registry::fstat): Pass decoded name to win32 registry call. (fhandler_registry::readdir): Return encoded name to user. (fhandler_registry::open): Store decoded name into value_name. (open_key): Pass decoded name to win32 registry call.
Diffstat (limited to 'winsup/cygwin/fhandler_registry.cc')
-rw-r--r--winsup/cygwin/fhandler_registry.cc101
1 files changed, 91 insertions, 10 deletions
diff --git a/winsup/cygwin/fhandler_registry.cc b/winsup/cygwin/fhandler_registry.cc
index dcf46de27..f77e85c4d 100644
--- a/winsup/cygwin/fhandler_registry.cc
+++ b/winsup/cygwin/fhandler_registry.cc
@@ -11,6 +11,7 @@ details. */
/* FIXME: Access permissions are ignored at the moment. */
#include "winsup.h"
+#include <stdlib.h>
#include "cygerrno.h"
#include "security.h"
#include "path.h"
@@ -79,6 +80,69 @@ static const char *DEFAULT_VALUE_NAME = "@";
static HKEY open_key (const char *name, REGSAM access, DWORD wow64, bool isValue);
+/* Return true if char must be encoded.
+ */
+static inline bool
+must_encode (char c)
+{
+ return (isdirsep (c) || c == '%');
+}
+
+/* Encode special chars in registry key or value name.
+ */
+static int
+encode_regname (char * dst, const char * src)
+{
+ int di = 0;
+ for (int si = 0; src[si]; si++)
+ {
+ char c = src[si];
+ if (must_encode (c) ||
+ (c == '.' && si == 0 && (!src[1] || (src[1] == '.' && !src[2]))))
+ {
+ if (di + 3 >= NAME_MAX + 1)
+ return ENAMETOOLONG;
+ __small_sprintf (dst + di, "%%%02x", c);
+ di += 3;
+ }
+ else
+ dst[di++] = c;
+ }
+ dst[di] = 0;
+ return 0;
+}
+
+/* Decode special chars in registry key or value name.
+ */
+static int
+decode_regname (char * dst, const char * src, int len = -1)
+{
+ if (len < 0)
+ len = strlen (src);
+ int di = 0;
+ for (int si = 0; si < len; si++)
+ {
+ char c = src[si];
+ if (c == '%')
+ {
+ if (si + 2 >= len)
+ return EINVAL;
+ char s[] = {src[si+1], src[si+2], '\0'};
+ char *p;
+ c = strtoul (s, &p, 16);
+ if (!(must_encode (c) ||
+ (c == '.' && si == 0 && (len == 3 || (src[3] == '.' && len == 4)))))
+ return EINVAL;
+ dst[di++] = c;
+ si += 2;
+ }
+ else
+ dst[di++] = c;
+ }
+ dst[di] = 0;
+ return 0;
+}
+
/* Returns 0 if path doesn't exist, >0 if path is a directory,
* <0 if path is a file.
*
@@ -159,8 +223,9 @@ fhandler_registry::exists ()
NULL, NULL))
|| (error == ERROR_MORE_DATA))
{
- if (strcasematch (buf, file)
- || (buf[0] == '\0' && strcasematch (file, DEFAULT_VALUE_NAME)))
+ char enc_buf[NAME_MAX + 1];
+ if ( (buf[0] == '\0' && strcasematch (file, DEFAULT_VALUE_NAME))
+ || (!encode_regname (enc_buf, buf) && strcasematch (enc_buf, file)))
{
file_type = -1;
goto out;
@@ -257,9 +322,11 @@ fhandler_registry::fstat (struct __stat64 *buf)
while (!isdirsep (*value_name))
value_name--;
value_name++;
+ char dec_value_name[NAME_MAX + 1];
DWORD dwSize;
- if (ERROR_SUCCESS ==
- RegQueryValueEx (hKey, value_name, NULL, NULL, NULL,
+ if (!decode_regname (dec_value_name, value_name) &&
+ ERROR_SUCCESS ==
+ RegQueryValueEx (hKey, dec_value_name, NULL, NULL, NULL,
&dwSize))
buf->st_size = dwSize;
}
@@ -360,8 +427,8 @@ retry:
/* We get here if `buf' contains valid data. */
if (*buf == 0)
strcpy (de->d_name, DEFAULT_VALUE_NAME);
- else
- strcpy (de->d_name, buf);
+ else if (encode_regname (de->d_name, buf))
+ goto retry;
dir->__d_position++;
if (dir->__d_position & REG_ENUM_VALUES_MASK)
@@ -505,6 +572,14 @@ fhandler_registry::open (int flags, mode_t mode)
goto out;
}
+ char dec_file[NAME_MAX + 1];
+ if (decode_regname (dec_file, file))
+ {
+ set_errno (EINVAL);
+ res = 0;
+ goto out;
+ }
+
handle = open_key (path, KEY_READ, wow64, false);
if (handle == (HKEY) INVALID_HANDLE_VALUE)
{
@@ -520,10 +595,10 @@ fhandler_registry::open (int flags, mode_t mode)
set_io_handle (handle);
- if (strcasematch (file, DEFAULT_VALUE_NAME))
+ if (strcasematch (dec_file, DEFAULT_VALUE_NAME))
value_name = cstrdup ("");
else
- value_name = cstrdup (file);
+ value_name = cstrdup (dec_file);
if (!(flags & O_DIROPEN) && !fill_filebuf ())
{
@@ -661,8 +736,14 @@ open_key (const char *name, REGSAM access, DWORD wow64, bool isValue)
const char *anchor = name;
while (*name && !isdirsep (*name))
name++;
- strncpy (component, anchor, name - anchor);
- component[name - anchor] = '\0';
+ if (decode_regname (component, anchor, name - anchor))
+ {
+ set_errno (EINVAL);
+ if (parentOpened)
+ RegCloseKey (hParentKey);
+ hKey = (HKEY) INVALID_HANDLE_VALUE;
+ break;
+ }
if (*name)
name++;
if (*name == 0 && isValue == true)