• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <errno.h>
2 #include <gtest/gtest.h>
3 #include <netdb.h>
4 #include <string.h>
5 #include <sys/un.h>
6 #include <vector>
7 using namespace testing::ext;
8 
9 class FortifyRecvchkTest : public testing::Test {
SetUp()10     void SetUp() override {}
TearDown()11     void TearDown() override {}
12 };
13 
14 struct DataLink {
15     std::function<bool(int)> callbackFn;
16     const char* sockPath;
17 };
18 
ConnectFunc(void * data)19 static void* ConnectFunc(void* data)
20 {
21     DataLink* p = reinterpret_cast<DataLink*>(data);
22     std::function<bool(int)> callbackFn = p->callbackFn;
23     void* returnValue = nullptr;
24 
25     int fd = socket(PF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
26     if (fd < 0) {
27         return reinterpret_cast<void*>(-1);
28     }
29 
30     struct sockaddr_un addr;
31     memset(&addr, 0, sizeof(addr));
32     addr.sun_family = AF_UNIX;
33     addr.sun_path[0] = '\0';
34     strcpy(addr.sun_path + 1, p->sockPath);
35 
36     if (connect(fd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) < 0) {
37         returnValue = reinterpret_cast<void*>(-1);
38     } else if (callbackFn && !callbackFn(fd)) {
39         returnValue = reinterpret_cast<void*>(-1);
40     }
41 
42     close(fd);
43     return returnValue;
44 }
45 
46 struct ReturnVal {
47     int fd;
48     struct sockaddr_un addr;
49 };
50 
SockInit(const char * sockPath,struct ReturnVal & returnVal)51 static void SockInit(const char* sockPath, struct ReturnVal& returnVal)
52 {
53     int fd = socket(PF_UNIX, SOCK_SEQPACKET, 0);
54     EXPECT_NE(fd, -1);
55 
56     struct sockaddr_un addr;
57     memset(&addr, 0, sizeof(addr));
58     addr.sun_family = AF_UNIX;
59     addr.sun_path[0] = '\0';
60     strcpy(addr.sun_path + 1, sockPath);
61     EXPECT_NE(-1, bind(fd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)));
62     EXPECT_NE(-1, listen(fd, 1));
63 
64     returnVal.fd = fd;
65     returnVal.addr = addr;
66 }
67 
CallSelectFunc(struct ReturnVal returnVal)68 static void CallSelectFunc(struct ReturnVal returnVal)
69 {
70     fd_set readSet;
71     FD_ZERO(&readSet);
72     FD_SET(returnVal.fd, &readSet);
73     timeval tv = { .tv_sec = 5, .tv_usec = 0 };
74     EXPECT_GT(select(returnVal.fd + 1, &readSet, nullptr, nullptr, &tv), 0);
75 }
76 
77 const char* g_testRecv = "hello";
Send(int fd)78 static bool Send(int fd)
79 {
80     if (send(fd, g_testRecv, strlen(g_testRecv) + 1, 0) < 0) {
81         return false;
82     }
83     return true;
84 }
85 
86 /**
87  * @tc.name: __recv_chk_001
88  * @tc.desc: This test case helps ensure that the recv_chk function can successfully receive data from a connected
89  *           socket and that the received data matches the expected content.
90  * @tc.type: FUNC
91  **/
92 HWTEST_F(FortifyRecvchkTest, __recv_chk_001, TestSize.Level1)
93 {
94     const char* sockPath = "test_recv_chk";
95     struct ReturnVal returnVal;
96     SockInit(sockPath, returnVal);
97     DataLink ConnectData;
98     ConnectData.callbackFn = Send;
99     ConnectData.sockPath = sockPath;
100 
101     struct sockaddr_un* addr = &returnVal.addr;
102     pthread_t thread;
103     int ret = pthread_create(&thread, nullptr, ConnectFunc, &ConnectData);
104     EXPECT_EQ(0, ret);
105     CallSelectFunc(returnVal);
106 
107     socklen_t len = sizeof(*addr);
108     int acceptFd = accept(returnVal.fd, reinterpret_cast<struct sockaddr*>(addr), &len);
109     EXPECT_NE(acceptFd, -1) << strerror(errno);
110     char buf[BUFSIZ];
111     memset(buf, 0, sizeof(buf));
112     size_t len1 = sizeof(buf);
113     size_t result = static_cast<size_t>(__recv_chk(acceptFd, buf, len1, len1, 0));
114     EXPECT_EQ(strlen(g_testRecv) + 1, result);
115     EXPECT_STREQ(g_testRecv, buf);
116     close(acceptFd);
117 
118     void* retVal;
119     EXPECT_EQ(0, pthread_join(thread, &retVal));
120     EXPECT_EQ(nullptr, retVal);
121     close(returnVal.fd);
122 }
123