Skip to content

Commit

Permalink
fix bug in keyname validation
Browse files Browse the repository at this point in the history
  • Loading branch information
kodebach committed Oct 2, 2020
1 parent 0616290 commit 495410c
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 14 deletions.
38 changes: 26 additions & 12 deletions src/libs/elektra/keyname.c
Original file line number Diff line number Diff line change
Expand Up @@ -515,23 +515,22 @@ int elektraKeyNameValidate (const char * name, const char * prefix, size_t * siz
}
}

// validate path in reverse because of ..
// need to validate path in reverse because of /../ parts
name = pathStart + pathLen - 1;

// check backslashes at end of name
// this ONLY checks for dangling escapes, size adjustments are done in the main loop
size_t backslashes = 0;
while (name >= pathStart && *name == '\\')
while (name - backslashes >= pathStart && *(name - backslashes) == '\\')
{
++backslashes;
--name;
}

if (backslashes % 2 != 0)
{
// dangling escape
return 0;
}
usize -= backslashes / 2;

enum
{
Expand All @@ -548,17 +547,38 @@ int elektraKeyNameValidate (const char * name, const char * prefix, size_t * siz
size_t skip = 0;
while (name >= pathStart)
{
char cur = *name;
size_t trailingSlashes = 0;
if (state == PART_END)
{
// count trailing slashes (the last one might be escaped)
while (name - trailingSlashes >= pathStart && *(name - trailingSlashes) == '/')
{
++trailingSlashes;
}
}

// count upcomming backslashes
backslashes = 0;
while (name - 1 - backslashes >= pathStart && *(name - 1 - backslashes) == '\\')
size_t backslashOffset = trailingSlashes == 0 ? 1 : trailingSlashes;
while (name - backslashOffset - backslashes >= pathStart && *(name - backslashOffset - backslashes) == '\\')
{
++backslashes;
}

int escaped = backslashes % 2 != 0;

// the last trailing slash is actually escaped
if (trailingSlashes > 0 && escaped)
{
--trailingSlashes;
}

name -= trailingSlashes;
size -= trailingSlashes;
usize -= trailingSlashes;

char cur = *name;

switch (state)
{
case PART_END:
Expand All @@ -568,11 +588,6 @@ int elektraKeyNameValidate (const char * name, const char * prefix, size_t * siz
partLen = 1;
state = DIGITS;
}
else if (cur == '/' && !escaped)
{
--size;
--usize;
}
else
{
partLen = 1;
Expand Down Expand Up @@ -764,7 +779,6 @@ int elektraKeyNameValidate (const char * name, const char * prefix, size_t * siz
++skip;
}


digits = 0;
underscores = 0;

Expand Down
1 change: 1 addition & 0 deletions src/tools/kdb/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ void TestCommand::doBinaryTest ()
void TestCommand::doNamingTest ()
{
vector<string> teststrings;
teststrings.push_back ("\\");
teststrings.push_back ("keyname");
teststrings.push_back ("deep/below/keyname");
teststrings.push_back ("keyname with spaces");
Expand Down
111 changes: 109 additions & 2 deletions tests/ctest/test_keyname.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,60 @@ static void test_validate (void)
TEST_VALIDATE_OK ("/\\\\\\\\/", NULL, 0, 6, 5);
TEST_VALIDATE_OK ("/\\\\\\\\\\/", NULL, 0, 8, 6);

TEST_VALIDATE_OK ("/\\/", NULL, 0, 4, 4);
TEST_VALIDATE_OK ("/\\\\", NULL, 0, 4, 4);
TEST_VALIDATE_OK ("/\\\\\\/", NULL, 0, 6, 5);
TEST_VALIDATE_OK ("/\\\\\\\\", NULL, 0, 6, 5);
TEST_VALIDATE_OK ("/\\\\\\\\\\/", NULL, 0, 8, 6);

TEST_VALIDATE_OK ("/\\//", NULL, 0, 4, 4);
TEST_VALIDATE_OK ("/\\\\/", NULL, 0, 4, 4);
TEST_VALIDATE_OK ("/\\\\\\//", NULL, 0, 6, 5);
TEST_VALIDATE_OK ("/\\\\\\\\/", NULL, 0, 6, 5);
TEST_VALIDATE_OK ("/\\\\\\\\\\//", NULL, 0, 8, 6);

TEST_VALIDATE_OK ("user:/\\/", NULL, 0, 9, 4);
TEST_VALIDATE_OK ("user:/\\\\", NULL, 0, 9, 4);
TEST_VALIDATE_OK ("user:/\\\\\\/", NULL, 0, 11, 5);
TEST_VALIDATE_OK ("user:/\\\\\\\\", NULL, 0, 11, 5);
TEST_VALIDATE_OK ("user:/\\\\\\\\\\/", NULL, 0, 13, 6);

TEST_VALIDATE_OK ("user:/\\//", NULL, 0, 9, 4);
TEST_VALIDATE_OK ("user:/\\\\/", NULL, 0, 9, 4);
TEST_VALIDATE_OK ("user:/\\\\\\//", NULL, 0, 11, 5);
TEST_VALIDATE_OK ("user:/\\\\\\\\/", NULL, 0, 11, 5);
TEST_VALIDATE_OK ("user:/\\\\\\\\\\//", NULL, 0, 13, 6);

TEST_VALIDATE_OK ("user:/tests/plugin/\\/", NULL, 0, 22, 17);
TEST_VALIDATE_OK ("user:/tests/plugin/\\\\", NULL, 0, 22, 17);
TEST_VALIDATE_OK ("user:/tests/plugin/\\\\\\/", NULL, 0, 24, 18);
TEST_VALIDATE_OK ("user:/tests/plugin/\\\\\\\\", NULL, 0, 24, 18);
TEST_VALIDATE_OK ("user:/tests/plugin/\\\\\\\\\\/", NULL, 0, 26, 19);

TEST_VALIDATE_OK ("user:/tests/plugin/\\//", NULL, 0, 22, 17);
TEST_VALIDATE_OK ("user:/tests/plugin/\\\\/", NULL, 0, 22, 17);
TEST_VALIDATE_OK ("user:/tests/plugin/\\\\\\//", NULL, 0, 24, 18);
TEST_VALIDATE_OK ("user:/tests/plugin/\\\\\\\\/", NULL, 0, 24, 18);
TEST_VALIDATE_OK ("user:/tests/plugin/\\\\\\\\\\//", NULL, 0, 26, 19);

TEST_VALIDATE_OK ("/\\//abc", NULL, 0, 8, 8);
TEST_VALIDATE_OK ("/\\\\/abc", NULL, 0, 8, 8);
TEST_VALIDATE_OK ("/\\\\\\//abc", NULL, 0, 10, 9);
TEST_VALIDATE_OK ("/\\\\\\\\/abc", NULL, 0, 10, 9);
TEST_VALIDATE_OK ("/\\\\\\\\\\//abc", NULL, 0, 12, 10);

TEST_VALIDATE_OK ("user:/\\//abc", NULL, 0, 13, 8);
TEST_VALIDATE_OK ("user:/\\\\/abc", NULL, 0, 13, 8);
TEST_VALIDATE_OK ("user:/\\\\\\//abc", NULL, 0, 15, 9);
TEST_VALIDATE_OK ("user:/\\\\\\\\/abc", NULL, 0, 15, 9);
TEST_VALIDATE_OK ("user:/\\\\\\\\\\//abc", NULL, 0, 17, 10);

TEST_VALIDATE_OK ("user:/tests/plugin/\\//abc", NULL, 0, 26, 21);
TEST_VALIDATE_OK ("user:/tests/plugin/\\\\/abc", NULL, 0, 26, 21);
TEST_VALIDATE_OK ("user:/tests/plugin/\\\\\\//abc", NULL, 0, 28, 22);
TEST_VALIDATE_OK ("user:/tests/plugin/\\\\\\\\/abc", NULL, 0, 28, 22);
TEST_VALIDATE_OK ("user:/tests/plugin/\\\\\\\\\\//abc", NULL, 0, 30, 23);

TEST_VALIDATE_OK ("/\\///", NULL, 0, 4, 4);
TEST_VALIDATE_OK ("/\\/\\/", NULL, 0, 6, 5);

Expand All @@ -81,6 +135,9 @@ static void test_validate (void)
TEST_VALIDATE_OK ("/////////", NULL, 0, 2, 3);
TEST_VALIDATE_OK ("user://///////", NULL, 0, 7, 3);

TEST_VALIDATE_OK ("/a////////", NULL, 0, 3, 4);
TEST_VALIDATE_OK ("user:/a////////", NULL, 0, 8, 4);

TEST_VALIDATE_OK ("/abc/%/def", NULL, 0, 11, 11);
TEST_VALIDATE_OK ("user:/abc/%/def", NULL, 0, 16, 11);

Expand Down Expand Up @@ -354,6 +411,9 @@ static void test_validate (void)
TEST_VALIDATE_ERROR ("/\\\\\\\\\\%", NULL, 0);
}

#undef TEST_VALIDATE_OK
#undef TEST_VALIDATE_ERROR

#define TEST_CANONICALIZE_OK(name, prefix, cname) \
do \
{ \
Expand Down Expand Up @@ -524,17 +584,49 @@ static void test_canonicalize (void)
TEST_CANONICALIZE_OK ("/\\\\\\\\%", "", "/\\\\\\\\%");

TEST_CANONICALIZE_OK ("/\\/", "", "/\\/");
TEST_CANONICALIZE_OK ("/\\\\/", "", "/\\\\");
TEST_CANONICALIZE_OK ("/\\\\", "", "/\\\\");
TEST_CANONICALIZE_OK ("/\\\\\\/", "", "/\\\\\\/");
TEST_CANONICALIZE_OK ("/\\\\\\\\/", "", "/\\\\\\\\");
TEST_CANONICALIZE_OK ("/\\\\\\\\", "", "/\\\\\\\\");
TEST_CANONICALIZE_OK ("/\\\\\\\\\\/", "", "/\\\\\\\\\\/");

TEST_CANONICALIZE_OK ("/\\//", "", "/\\/");
TEST_CANONICALIZE_OK ("/\\\\/", "", "/\\\\");
TEST_CANONICALIZE_OK ("/\\\\\\//", "", "/\\\\\\/");
TEST_CANONICALIZE_OK ("/\\\\\\\\/", "", "/\\\\\\\\");
TEST_CANONICALIZE_OK ("/\\\\\\\\\\//", "", "/\\\\\\\\\\/");

TEST_CANONICALIZE_OK ("user:/\\/", "", "user:/\\/");
TEST_CANONICALIZE_OK ("user:/\\\\", "", "user:/\\\\");
TEST_CANONICALIZE_OK ("user:/\\\\\\/", "", "user:/\\\\\\/");
TEST_CANONICALIZE_OK ("user:/\\\\\\\\", "", "user:/\\\\\\\\");
TEST_CANONICALIZE_OK ("user:/\\\\\\\\\\/", "", "user:/\\\\\\\\\\/");

TEST_CANONICALIZE_OK ("user:/\\//", "", "user:/\\/");
TEST_CANONICALIZE_OK ("user:/\\\\/", "", "user:/\\\\");
TEST_CANONICALIZE_OK ("user:/\\\\\\//", "", "user:/\\\\\\/");
TEST_CANONICALIZE_OK ("user:/\\\\\\\\/", "", "user:/\\\\\\\\");
TEST_CANONICALIZE_OK ("user:/\\\\\\\\\\//", "", "user:/\\\\\\\\\\/");

TEST_CANONICALIZE_OK ("user:/tests/plugin/\\/", "", "user:/tests/plugin/\\/");
TEST_CANONICALIZE_OK ("user:/tests/plugin/\\\\", "", "user:/tests/plugin/\\\\");
TEST_CANONICALIZE_OK ("user:/tests/plugin/\\\\\\/", "", "user:/tests/plugin/\\\\\\/");
TEST_CANONICALIZE_OK ("user:/tests/plugin/\\\\\\\\", "", "user:/tests/plugin/\\\\\\\\");
TEST_CANONICALIZE_OK ("user:/tests/plugin/\\\\\\\\\\/", "", "user:/tests/plugin/\\\\\\\\\\/");

TEST_CANONICALIZE_OK ("user:/tests/plugin/\\//", "", "user:/tests/plugin/\\/");
TEST_CANONICALIZE_OK ("user:/tests/plugin/\\\\/", "", "user:/tests/plugin/\\\\");
TEST_CANONICALIZE_OK ("user:/tests/plugin/\\\\\\//", "", "user:/tests/plugin/\\\\\\/");
TEST_CANONICALIZE_OK ("user:/tests/plugin/\\\\\\\\/", "", "user:/tests/plugin/\\\\\\\\");
TEST_CANONICALIZE_OK ("user:/tests/plugin/\\\\\\\\\\//", "", "user:/tests/plugin/\\\\\\\\\\/");

TEST_CANONICALIZE_OK ("/abc/%def/ghi", "", "/abc/%def/ghi");
TEST_CANONICALIZE_OK ("/abc/%d%ef%/ghi", "", "/abc/%d%ef%/ghi");
TEST_CANONICALIZE_OK ("/abc/%def%/ghi", "", "/abc/%def%/ghi");
TEST_CANONICALIZE_OK ("/abc/d%ef/ghi", "", "/abc/d%ef/ghi");
}

#undef TEST_CANONICALIZE_OK

static const char * keyNsNames[] = { "KEY_NS_NONE", "KEY_NS_CASCADING", "KEY_NS_META", "KEY_NS_SPEC", "KEY_NS_PROC",
"KEY_NS_DIR", "KEY_NS_USER", "KEY_NS_SYSTEM", "KEY_NS_DEFAULT" };

Expand Down Expand Up @@ -675,12 +767,26 @@ static void test_unescape (void)
TEST_UNESCAPE_OK ("/\\\\\\\\", KEY_NS_CASCADING, "\0\\\\");
TEST_UNESCAPE_OK ("/\\\\\\\\\\/", KEY_NS_CASCADING, "\0\\\\/");

TEST_UNESCAPE_OK ("user:/\\/", KEY_NS_USER, "\0/");
TEST_UNESCAPE_OK ("user:/\\\\", KEY_NS_USER, "\0\\");
TEST_UNESCAPE_OK ("user:/\\\\\\/", KEY_NS_USER, "\0\\/");
TEST_UNESCAPE_OK ("user:/\\\\\\\\", KEY_NS_USER, "\0\\\\");
TEST_UNESCAPE_OK ("user:/\\\\\\\\\\/", KEY_NS_USER, "\0\\\\/");

TEST_UNESCAPE_OK ("user:/tests/plugin/\\/", KEY_NS_USER, "\0tests\0plugin\0/");
TEST_UNESCAPE_OK ("user:/tests/plugin/\\\\", KEY_NS_USER, "\0tests\0plugin\0\\");
TEST_UNESCAPE_OK ("user:/tests/plugin/\\\\\\/", KEY_NS_USER, "\0tests\0plugin\0\\/");
TEST_UNESCAPE_OK ("user:/tests/plugin/\\\\\\\\", KEY_NS_USER, "\0tests\0plugin\0\\\\");
TEST_UNESCAPE_OK ("user:/tests/plugin/\\\\\\\\\\/", KEY_NS_USER, "\0tests\0plugin\0\\\\/");

TEST_UNESCAPE_OK ("/abc/%def/ghi", KEY_NS_CASCADING, "\0abc\0%def\0ghi");
TEST_UNESCAPE_OK ("/abc/%d%ef%/ghi", KEY_NS_CASCADING, "\0abc\0%d%ef%\0ghi");
TEST_UNESCAPE_OK ("/abc/%def%/ghi", KEY_NS_CASCADING, "\0abc\0%def%\0ghi");
TEST_UNESCAPE_OK ("/abc/d%ef/ghi", KEY_NS_CASCADING, "\0abc\0d%ef\0ghi");
}

#undef TEST_UNESCAPE_OK

#define TEST_ESCAPE_PART_OK(upart, part) \
do \
{ \
Expand Down Expand Up @@ -726,6 +832,7 @@ static void test_escapePart (void)
TEST_ESCAPE_PART_OK ("d\\a", "d\\\\a");
}

#undef TEST_ESCAPE_PART_OK

int main (int argc, char ** argv)
{
Expand Down

0 comments on commit 495410c

Please sign in to comment.