* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/select.h>
#include <sigchain.h>
#include "fortify_test.h"
#include "functionalext.h"
#include "test.h"
#define STABILITY_LOOP_TIMES 10
* @tc.name : fd_set_0010
* @tc.desc : test FD_SET with normal fd
* @tc.level : Level 1
*/
static void fd_set_0010(void)
{
fd_set readfds;
FD_ZERO(&readfds);
int sockfd = 0;
FD_SET(sockfd, &readfds);
EXPECT_EQ(fd_set_0010, (&readfds)->fds_bits[0], 1);
return;
}
* @tc.name : fd_set_0020
* @tc.desc : test FD_SET with fd < 0
* @tc.level : Level 2
*/
static void fd_set_0020(void)
{
struct sigaction sigabrt = {
.sa_handler = SignalHandler,
};
sigaction(SIGABRT, &sigabrt, NULL);
int status;
int pid = fork();
fd_set readfds;
int sockfd = -1;
switch (pid) {
case -1:
t_error("fork failed: %s\n", strerror(errno));
break;
case 0:
FD_ZERO(&readfds);
FD_SET(sockfd, &readfds);
exit(0);
default:
waitpid(pid, &status, WUNTRACED);
TEST(WIFEXITED(status) == 0);
TEST(WIFSTOPPED(status) == 1);
TEST(WSTOPSIG(status) == SIGSTOP);
kill(pid, SIGCONT);
break;
}
return;
}
* @tc.name : fd_set_0030
* @tc.desc : test FD_SET with fd >= 1024
* @tc.level : Level 2
*/
static void fd_set_0030(void)
{
struct sigaction sigabrt = {
.sa_handler = SignalHandler,
};
sigaction(SIGABRT, &sigabrt, NULL);
int status;
int pid = fork();
fd_set readfds;
int sockfd = 1024;
switch (pid) {
case -1:
t_error("fork failed: %s\n", strerror(errno));
break;
case 0:
FD_ZERO(&readfds);
FD_SET(sockfd, &readfds);
exit(0);
default:
waitpid(pid, &status, WUNTRACED);
TEST(WIFEXITED(status) == 0);
TEST(WIFSTOPPED(status) == 1);
TEST(WSTOPSIG(status) == SIGSTOP);
kill(pid, SIGCONT);
break;
}
return;
}
* @tc.name : fd_clr_0010
* @tc.desc : test FD_CLR with normal fd
* @tc.level : Level 1
*/
static void fd_clr_0010(void)
{
fd_set readfds;
FD_ZERO(&readfds);
int sockfd = 0;
FD_SET(sockfd, &readfds);
FD_CLR(sockfd, &readfds);
EXPECT_EQ(fd_set_0010, (&readfds)->fds_bits[0], 0);
return;
}
* @tc.name : fd_clr_0020
* @tc.desc : test FD_CLR with fd < 0
* @tc.level : Level 2
*/
static void fd_clr_0020(void)
{
struct sigaction sigabrt = {
.sa_handler = SignalHandler,
};
sigaction(SIGABRT, &sigabrt, NULL);
int status;
int pid = fork();
fd_set readfds;
int sockfd = -1;
switch (pid) {
case -1:
t_error("fork failed: %s\n", strerror(errno));
break;
case 0:
FD_ZERO(&readfds);
FD_CLR(sockfd, &readfds);
exit(0);
default:
waitpid(pid, &status, WUNTRACED);
TEST(WIFEXITED(status) == 0);
TEST(WIFSTOPPED(status) == 1);
TEST(WSTOPSIG(status) == SIGSTOP);
kill(pid, SIGCONT);
break;
}
return;
}
* @tc.name : fd_clr_0030
* @tc.desc : test FD_CLR with fd >= 1024
* @tc.level : Level 2
*/
static void fd_clr_0030(void)
{
struct sigaction sigabrt = {
.sa_handler = SignalHandler,
};
sigaction(SIGABRT, &sigabrt, NULL);
int status;
int pid = fork();
fd_set readfds;
int sockfd = 1024;
switch (pid) {
case -1:
t_error("fork failed: %s\n", strerror(errno));
break;
case 0:
FD_ZERO(&readfds);
FD_CLR(sockfd, &readfds);
exit(0);
default:
waitpid(pid, &status, WUNTRACED);
TEST(WIFEXITED(status) == 0);
TEST(WIFSTOPPED(status) == 1);
TEST(WSTOPSIG(status) == SIGSTOP);
kill(pid, SIGCONT);
break;
}
return;
}
* @tc.name : fd_isset_0010
* @tc.desc : test FD_ISSET with normal fd
* @tc.level : Level 1
*/
static void fd_isset_0010(void)
{
fd_set readfds;
FD_ZERO(&readfds);
int sockfd = 0;
FD_SET(sockfd, &readfds);
int res = FD_ISSET(sockfd, &readfds);
EXPECT_EQ(fd_set_0010, res, 1);
return;
}
* @tc.name : fd_isset_0020
* @tc.desc : test FD_ISSET with fd < 0
* @tc.level : Level 2
*/
static void fd_isset_0020(void)
{
fd_set readfds;
FD_ZERO(&readfds);
int sockfd = -1;
int res = FD_ISSET(sockfd, &readfds);
EXPECT_EQ(fd_set_0010, res, 0);
return;
}
* @tc.name : fd_isset_0030
* @tc.desc : test FD_ISSET with fd >= 1024
* @tc.level : Level 2
*/
static void fd_isset_0030(void)
{
fd_set readfds;
FD_ZERO(&readfds);
int sockfd = 1024;
int res = FD_ISSET(sockfd, &readfds);
EXPECT_EQ(fd_set_0010, res, 0);
return;
}
#ifndef MUSL_EXTERNAL_FUNCTION
* @tc.name : __fdelt_chk_0010
* @tc.desc : test __fdelt_chk stub return value and errno
* @tc.level : Level 1
*/
static void __fdelt_chk_0010(void)
{
errno = 0;
long int ret = __fdelt_chk(0);
EXPECT_LONGEQ(__fdelt_chk_0010, ret, -1);
EXPECT_EQ(__fdelt_chk_0010, errno, ENOSYS);
}
#else
* @tc.name : __fdelt_chk_0020
* @tc.desc : test __fdelt_chk with normal fd
* @tc.level : Level 1
*/
static void __fdelt_chk_0020(void)
{
EXPECT_EQ(__fdelt_chk_0020, __fdelt_chk(0), 0);
EXPECT_EQ(__fdelt_chk_0020, __fdelt_chk(NFDBITS - 1), 0);
EXPECT_EQ(__fdelt_chk_0020, __fdelt_chk(NFDBITS), 1);
EXPECT_EQ(__fdelt_chk_0020, __fdelt_chk(FD_SETSIZE - 1), (FD_SETSIZE - 1) / NFDBITS);
}
* @tc.name : __fdelt_chk_0030
* @tc.desc : test __fdelt_chk with fd < 0
* @tc.level : Level 2
*/
static void __fdelt_chk_0030(void)
{
struct sigaction sigabrt = {
.sa_handler = SignalHandler,
};
sigaction(SIGABRT, &sigabrt, NULL);
int status;
int pid = fork();
switch (pid) {
case -1:
t_error("fork failed: %s\n", strerror(errno));
break;
case 0:
__fdelt_chk(-1);
exit(0);
default:
waitpid(pid, &status, WUNTRACED);
TEST(WIFEXITED(status) == 0);
TEST(WIFSTOPPED(status) == 1);
TEST(WSTOPSIG(status) == SIGSTOP);
kill(pid, SIGCONT);
break;
}
}
* @tc.name : __fdelt_chk_0040
* @tc.desc : test __fdelt_chk with fd >= FD_SETSIZE
* @tc.level : Level 2
*/
static void __fdelt_chk_0040(void)
{
struct sigaction sigabrt = {
.sa_handler = SignalHandler,
};
sigaction(SIGABRT, &sigabrt, NULL);
int status;
int pid = fork();
switch (pid) {
case -1:
t_error("fork failed: %s\n", strerror(errno));
break;
case 0:
__fdelt_chk(FD_SETSIZE);
exit(0);
default:
waitpid(pid, &status, WUNTRACED);
TEST(WIFEXITED(status) == 0);
TEST(WIFSTOPPED(status) == 1);
TEST(WSTOPSIG(status) == SIGSTOP);
kill(pid, SIGCONT);
break;
}
}
* @tc.name : __fdelt_chk_0050
* @tc.desc : test __fdelt_chk stability with repeated boundary checks
* @tc.level : Level 1
*/
static void __fdelt_chk_0050(void)
{
for (int round = 0; round < STABILITY_LOOP_TIMES; round++) {
for (int fd = 0; fd < FD_SETSIZE; fd++) {
EXPECT_EQ(__fdelt_chk_0050, __fdelt_chk(fd), fd / NFDBITS);
}
}
}
#endif
int main(int argc, char *argv[])
{
remove_all_special_handler(SIGABRT);
fd_set_0010();
fd_set_0020();
fd_set_0030();
fd_clr_0010();
fd_clr_0020();
fd_clr_0030();
fd_isset_0010();
fd_isset_0020();
fd_isset_0030();
#ifndef MUSL_EXTERNAL_FUNCTION
__fdelt_chk_0010();
#else
__fdelt_chk_0020();
__fdelt_chk_0030();
__fdelt_chk_0040();
__fdelt_chk_0050();
#endif
return t_status;
}