Commit 4e995b4d authored by Adam Simpkins's avatar Adam Simpkins Committed by Facebook Github Bot 6

update SocketAddress::setFromPath() to take a StringPiece

Summary:Update setFromPath() to accept a StringPiece rather than just std::string
or a plain const char*.

Also fix two other minor issues:
- Leave the old address untouched on failure.  Previously it could leave the
  SocketAddress in a partially updated state.
- Don't assume the input is nul terminated.  Previously the input code read
  one past the specified input length, and copied this into the address,
  assuming it was a nul terminator.  The new code explicitly writes a 0 byte.

Reviewed By: yfeldblum

Differential Revision: D3119882

fb-gh-sync-id: 3e2258f42034b4f470ade0a23ea085e132a3dd0f
fbshipit-source-id: 3e2258f42034b4f470ade0a23ea085e132a3dd0f
parent 98d33bb5
...@@ -180,24 +180,29 @@ void SocketAddress::setFromHostPort(const char* hostAndPort) { ...@@ -180,24 +180,29 @@ void SocketAddress::setFromHostPort(const char* hostAndPort) {
setFromAddrInfo(results.info); setFromAddrInfo(results.info);
} }
void SocketAddress::setFromPath(const char* path, size_t len) { void SocketAddress::setFromPath(StringPiece path) {
// Before we touch storage_, check to see if the length is too big.
// Note that "storage_.un.addr->sun_path" may not be safe to evaluate here,
// but sizeof() just uses its type, and does't evaluate it.
if (path.size() > sizeof(storage_.un.addr->sun_path)) {
throw std::invalid_argument(
"socket path too large to fit into sockaddr_un");
}
if (!external_) { if (!external_) {
storage_.un.init(); storage_.un.init();
external_ = true; external_ = true;
} }
size_t len = path.size();
storage_.un.len = offsetof(struct sockaddr_un, sun_path) + len; storage_.un.len = offsetof(struct sockaddr_un, sun_path) + len;
if (len > sizeof(storage_.un.addr->sun_path)) { memcpy(storage_.un.addr->sun_path, path.data(), len);
throw std::invalid_argument( // If there is room, put a terminating NUL byte in sun_path. In general the
"socket path too large to fit into sockaddr_un"); // path should be NUL terminated, although getsockname() and getpeername()
} else if (len == sizeof(storage_.un.addr->sun_path)) { // may return Unix socket addresses with paths that fit exactly in sun_path
// Note that there will be no terminating NUL in this case. // with no terminating NUL.
// We allow this since getsockname() and getpeername() may return if (len < sizeof(storage_.un.addr->sun_path)) {
// Unix socket addresses with paths that fit exactly in sun_path with no storage_.un.addr->sun_path[len] = '\0';
// terminating NUL.
memcpy(storage_.un.addr->sun_path, path, len);
} else {
memcpy(storage_.un.addr->sun_path, path, len + 1);
} }
} }
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <folly/IPAddress.h> #include <folly/IPAddress.h>
#include <folly/Portability.h> #include <folly/Portability.h>
#include <folly/Range.h>
namespace folly { namespace folly {
...@@ -278,16 +279,12 @@ class SocketAddress { ...@@ -278,16 +279,12 @@ class SocketAddress {
* *
* Raises std::invalid_argument on error. * Raises std::invalid_argument on error.
*/ */
void setFromPath(const char* path) { void setFromPath(StringPiece path);
setFromPath(path, strlen(path));
}
void setFromPath(const std::string& path) { void setFromPath(const char* path, size_t length) {
setFromPath(path.data(), path.length()); setFromPath(StringPiece{path, length});
} }
void setFromPath(const char* path, size_t length);
// a typedef that allow us to compile against both winsock & POSIX sockets: // a typedef that allow us to compile against both winsock & POSIX sockets:
using SocketDesc = decltype(socket(0,0,0)); // POSIX: int, winsock: unsigned using SocketDesc = decltype(socket(0,0,0)); // POSIX: int, winsock: unsigned
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment