Skip to content

Commit

Permalink
Merge pull request #870 from likema/linux-unix-addr-abstract-path
Browse files Browse the repository at this point in the history
ACE_UNIX_Addr supports abstract path in Linux.
  • Loading branch information
jwillemsen authored Feb 11, 2025
2 parents 4d9cfe6 + b3e4e45 commit 279244f
Show file tree
Hide file tree
Showing 3 changed files with 204 additions and 14 deletions.
55 changes: 50 additions & 5 deletions ACE/ace/UNIX_Addr.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "ace/UNIX_Addr.h"
#include <algorithm>

#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)

Expand Down Expand Up @@ -40,9 +41,17 @@ ACE_UNIX_Addr::string_to_addr (const char addr[])
ACE_OS::strsncpy (this->unix_addr_.sun_path, addr,
sizeof this->unix_addr_.sun_path);

size_t const len = ACE_OS::strlen (this->unix_addr_.sun_path);
#if defined (ACE_LINUX)
if (*this->unix_addr_.sun_path == '@') // abstract path
{
*this->unix_addr_.sun_path = 0;
}
#endif /* ACE_LINUX */

this->set_size (sizeof this->unix_addr_ -
sizeof (this->unix_addr_.sun_path) +
ACE_OS::strlen (this->unix_addr_.sun_path));
len);
return 0;
}

Expand All @@ -51,9 +60,27 @@ ACE_UNIX_Addr::string_to_addr (const char addr[])
int
ACE_UNIX_Addr::addr_to_string (ACE_TCHAR s[], size_t len) const
{
ACE_OS::strsncpy (s,
ACE_TEXT_CHAR_TO_TCHAR (this->unix_addr_.sun_path),
len);
if (!s || len == 0)
{
return -1;
}

size_t i = 0;
#if defined (ACE_LINUX)
if (!*this->unix_addr_.sun_path && this->unix_addr_.sun_path[1])
{
if (len == 1)
{
return -1;
}

s[0] = '@';
i = 1;
}
#endif /* ACE_LINUX */
ACE_OS::strsncpy (s + i,
ACE_TEXT_CHAR_TO_TCHAR (this->unix_addr_.sun_path + i),
len - i);
return 0;
}

Expand Down Expand Up @@ -114,7 +141,17 @@ ACE_UNIX_Addr::set (const sockaddr_un *un, int len)
(void) ACE_OS::memset ((void *) &this->unix_addr_, 0,
sizeof this->unix_addr_);
this->unix_addr_.sun_family = AF_UNIX;
#if defined (ACE_LINUX)
int const n = (std::min) (len - int (sizeof this->unix_addr_ -
sizeof (this->unix_addr_.sun_path)),
int (sizeof (this->unix_addr_.sun_path)));
if (n > 0)
{
memcpy (this->unix_addr_.sun_path, un->sun_path, n);
}
#else
ACE_OS::strcpy (this->unix_addr_.sun_path, un->sun_path);
#endif /* ACE_LINUX */
this->base_set (AF_UNIX, len);
return 0;
}
Expand All @@ -135,10 +172,18 @@ ACE_UNIX_Addr::set (const char rendezvous_point[])
rendezvous_point,
sizeof this->unix_addr_.sun_path);

size_t const len = ACE_OS::strlen (this->unix_addr_.sun_path);
#if defined (ACE_LINUX)
if (*this->unix_addr_.sun_path == '@') // abstract path
{
*this->unix_addr_.sun_path = 0;
}
#endif /* ACE_LINUX */

this->ACE_Addr::base_set (AF_UNIX,
sizeof this->unix_addr_ -
sizeof (this->unix_addr_.sun_path) +
ACE_OS::strlen (this->unix_addr_.sun_path));
len);
return 0;
}

Expand Down
13 changes: 10 additions & 3 deletions ACE/ace/UNIX_Addr.inl
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,16 @@ ACE_UNIX_Addr::set (const wchar_t rendezvous_point[])
ACE_INLINE bool
ACE_UNIX_Addr::operator == (const ACE_UNIX_Addr &sap) const
{
return ACE_OS::strncmp (this->unix_addr_.sun_path,
sap.unix_addr_.sun_path,
sizeof this->unix_addr_.sun_path) == 0;
size_t i = 0;
#if defined (ACE_LINUX)
if (!*this->unix_addr_.sun_path && !*sap.unix_addr_.sun_path)
{
i = 1;
}
#endif /* ACE_LINUX */
return ACE_OS::strncmp (this->unix_addr_.sun_path + i,
sap.unix_addr_.sun_path + i,
sizeof (this->unix_addr_.sun_path) - 1) == 0;
}

// Compare two addresses for inequality.
Expand Down
150 changes: 144 additions & 6 deletions ACE/tests/UNIX_Addr_Test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,26 +34,164 @@ int run_main (int, ACE_TCHAR *[])
addr.set (path);
ACE_TEST_ASSERT (addr.get_size () > origin);
ACE_TEST_ASSERT (addr.addr_to_string (buf, sizeof (buf)) == 0);
ACE_TEST_ASSERT (strcmp(path, ACE_TEXT_ALWAYS_CHAR(buf)) == 0);
ACE_TEST_ASSERT (strcmp(path, addr.get_path_name ()) == 0);
ACE_TEST_ASSERT (strcmp (path, ACE_TEXT_ALWAYS_CHAR(buf)) == 0);
ACE_TEST_ASSERT (strcmp (path, addr.get_path_name ()) == 0);

// Set longer path by ACE_UNIX_Addr::string_to_addr
origin = addr.get_size ();
path = "/tmp/unix_addr_test";
addr.string_to_addr (path);
ACE_TEST_ASSERT (addr.get_size () > origin);
ACE_TEST_ASSERT (addr.addr_to_string (buf, sizeof (buf)) == 0);
ACE_TEST_ASSERT (strcmp(path, ACE_TEXT_ALWAYS_CHAR(buf)) == 0);
ACE_TEST_ASSERT (strcmp(path, addr.get_path_name ()) == 0);
ACE_TEST_ASSERT (strcmp (path, ACE_TEXT_ALWAYS_CHAR(buf)) == 0);
ACE_TEST_ASSERT (strcmp (path, addr.get_path_name ()) == 0);

// Set shorter path by ACE_UNIX_Addr::string_to_addr
origin = addr.get_size ();
path = "/tmp/test";
addr.string_to_addr (path);
ACE_TEST_ASSERT (addr.get_size () < origin);
ACE_TEST_ASSERT (addr.addr_to_string (buf, sizeof (buf)) == 0);
ACE_TEST_ASSERT (strcmp(path, ACE_TEXT_ALWAYS_CHAR(buf)) == 0);
ACE_TEST_ASSERT (strcmp(path, addr.get_path_name ()) == 0);
ACE_TEST_ASSERT (strcmp (path, ACE_TEXT_ALWAYS_CHAR(buf)) == 0);
ACE_TEST_ASSERT (strcmp (path, addr.get_path_name ()) == 0);

// Bounds checking
path = "/tmp/bounds.test";
addr.set (path);
ACE_TEST_ASSERT (addr.addr_to_string (nullptr, sizeof (buf)) == -1);
ACE_TEST_ASSERT (addr.addr_to_string (buf, 0) == -1);

ACE_UNIX_Addr a1 ("/tmp/testA");
ACE_UNIX_Addr a2 ("/tmp/testB");
ACE_TEST_ASSERT (a1 != a2);

// Test 1: Regular paths with difference at the end
{
char path1[108] = "/test/path/";
char path2[108] = "/test/path/";
// Fill paths with 'a' up to index 106 (leaving room for null terminator)
ACE_OS::memset(path1 + 11, 'a', 95);
ACE_OS::memset(path2 + 11, 'a', 95);
path1[106] = '1';
path2[106] = '2';
path1[107] = '\0';
path2[107] = '\0';

ACE_UNIX_Addr addr1(path1);
ACE_UNIX_Addr addr2(path2);

// Should detect difference at the last valid character
ACE_TEST_ASSERT(!(addr1 == addr2));
}

// Regular paths comparison
{
ACE_UNIX_Addr addr1 ("/tmp/test1");
ACE_UNIX_Addr addr2 ("/tmp/test1");
ACE_UNIX_Addr addr3 ("/tmp/test2");

ACE_TEST_ASSERT (addr1 == addr2);
ACE_TEST_ASSERT (!(addr1 == addr3));
}

{
ACE_UNIX_Addr addr1 ("/tmp/test1");
ACE_UNIX_Addr addr2 ("/tmp/test2");

ACE_TEST_ASSERT (!(addr1 == addr2));
}

#if defined(ACE_LINUX)
// Abstract paths comparison
{
ACE_UNIX_Addr addr1 ("@test1");
ACE_UNIX_Addr addr2 ("@test1");
ACE_UNIX_Addr addr3 ("@test2");

ACE_TEST_ASSERT (addr1 == addr2);
ACE_TEST_ASSERT (!(addr1 == addr3));
}

// Mixed comparison (abstract vs regular)
{
ACE_UNIX_Addr addr1 ("@test1");
ACE_UNIX_Addr addr2 ("/test1");

ACE_TEST_ASSERT (!(addr1 == addr2));
}

// Bounds checking for abstract path
path = "@/tmp/bounds.test";
addr.set (path);
ACE_TEST_ASSERT (addr.addr_to_string (buf, 1) == -1);

a1.set ("@/tmp/boundA");
a2.set ("@/tmp/boundB");
ACE_TEST_ASSERT (a1 != a2);
a2.set ("/tmp/boundA");
ACE_TEST_ASSERT (a1 != a2);
a1.set ("@/tmp/bound");
ACE_TEST_ASSERT (a1 != a2);

// Set abstract path by set.
path = "@/tmp/ace.test";
addr.set (path);
ACE_TEST_ASSERT (addr.addr_to_string (buf, sizeof (buf)) == 0);
ACE_TEST_ASSERT (strcmp (path, ACE_TEXT_ALWAYS_CHAR(buf)) == 0);
ACE_TEST_ASSERT (*addr.get_path_name () == '\0');
ACE_TEST_ASSERT (strcmp (path + 1, addr.get_path_name () + 1) == 0);

// Set abstract path by string_to_addr.
path = "@/tmp/unix_addr_test";
addr.string_to_addr (path);
ACE_TEST_ASSERT (addr.addr_to_string (buf, sizeof (buf)) == 0);
ACE_TEST_ASSERT (strcmp (path, ACE_TEXT_ALWAYS_CHAR(buf)) == 0);
ACE_TEST_ASSERT (*addr.get_path_name () == '\0');
ACE_TEST_ASSERT (strcmp (path + 1, addr.get_path_name () + 1) == 0);

// Test maximum length abstract path
char max_path[108] = "@"; // sizeof(sun_path) is typically 108
ACE_OS::memset(max_path + 1, 'a', sizeof(max_path) - 2);
max_path[sizeof(max_path) - 1] = '\0';
addr.set(max_path);
ACE_TEST_ASSERT(addr.addr_to_string(buf, sizeof(buf)) == 0);
ACE_TEST_ASSERT(strcmp(max_path, ACE_TEXT_ALWAYS_CHAR(buf)) == 0);

// Test comparison of abstract paths
ACE_UNIX_Addr addr2("@/tmp/ace.test");
ACE_TEST_ASSERT(addr2 == addr2);
ACE_TEST_ASSERT(!(addr2 != addr2));

// Test invalid abstract paths
ACE_TEST_ASSERT(addr.set("@") == 0); // Empty abstract path
ACE_TEST_ASSERT(addr.set("@@/tmp/test") == 0); // Multiple @ prefixes


// Test path with embedded null
char null_path[] = "@/tmp/te\0st";
ACE_TEST_ASSERT(addr.set(null_path) == 0);
ACE_TEST_ASSERT(ACE_OS::strcmp(addr.get_path_name() + 1, "/tmp/te") == 0);

// Abstract paths with difference at the end
{
char path1[108] = "@/test/";
char path2[108] = "@/test/";
// Fill paths with 'a' up to index 106
ACE_OS::memset(path1 + 7, 'a', 99);
ACE_OS::memset(path2 + 7, 'a', 99);
path1[106] = '1';
path2[106] = '2';
path1[107] = '\0';
path2[107] = '\0';

ACE_UNIX_Addr addr1(path1);
ACE_UNIX_Addr addr2(path2);

// Should detect difference at the last valid character
ACE_TEST_ASSERT(!(addr1 == addr2));
}
#endif // ACE_LINUX

#endif // ! ACE_LACKS_UNIX_DOMAIN_SOCKETS

ACE_END_TEST;
Expand Down

0 comments on commit 279244f

Please sign in to comment.