提交 9a65a375 编写于 作者: W wangjiahui

add test case about rm011

Signed-off-by: Nwangjiahui <wangjiahui27@huawei.com>
上级 e6587537
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "functionalext.h" #include "functionalext.h"
#define PIPE_FD 2
#define NUM_OF_BYTE 8 #define NUM_OF_BYTE 8
#define BASE_NUM 11 #define BASE_NUM 11
#define TEST_COUNTS 32 #define TEST_COUNTS 32
...@@ -312,6 +313,55 @@ static void dlopen_ext_randomization_0800(void) ...@@ -312,6 +313,55 @@ static void dlopen_ext_randomization_0800(void)
dlclose(handle); dlclose(handle);
} }
/**
* @tc.name : dlopen_ext_randomization_0900
* @tc.desc : Different processes call the dlopen_ext interface to load a dynamic library,
* the flag of dl_extinfo is set to DL_EXT_RESERVED_ADDRESS_RECURSIVE,
* and then call the dlsym interface to get symbol address
* @tc.level : Level1
*/
static void dlopen_ext_randomization_0900(void)
{
void *parent_handle = 0;
void *child_handle = 0;
void *parent_sym = 0;
void *child_sym = 0;
void *get_child_sym = 0;
int fd[PIPE_FD];
if (pipe(fd) < 0) {
EXPECT_FALSE(__FUNCTION__, true);
return;
}
dl_extinfo extinfo = {
.flag = DL_EXT_RESERVED_ADDRESS_RECURSIVE,
};
pid_t pid = fork();
if (pid == 0) {
child_handle = dlopen_ext(LIB_NAME_A, RTLD_NOW, &extinfo);
EXPECT_PTRNE(__FUNCTION__, child_handle, 0);
if (!child_handle) {
exit(-1);
}
child_sym = dlsym(child_handle, "test");
write(fd[1], &child_sym, sizeof(void *));
dlclose(child_handle);
exit(0);
}
parent_handle = dlopen_ext(LIB_NAME_A, RTLD_NOW, &extinfo);
EXPECT_PTRNE(__FUNCTION__, parent_handle, 0);
if (!parent_handle) {
return;
};
parent_sym = dlsym(parent_handle, "test");
dlclose(parent_handle);
int status;
waitpid(pid, &status, 0);
read(fd[0], &get_child_sym, sizeof(void *));
EXPECT_PTREQ(__FUNCTION__, parent_sym, get_child_sym);
close(fd[0]);
close(fd[1]);
}
/** /**
* @tc.name : dlopen_ns_randomization_0100 * @tc.name : dlopen_ns_randomization_0100
* @tc.desc : Call the dlopen_ns interface to load a valid dynamic library * @tc.desc : Call the dlopen_ns interface to load a valid dynamic library
...@@ -479,6 +529,7 @@ TEST_FUNC test_cases[] = { ...@@ -479,6 +529,7 @@ TEST_FUNC test_cases[] = {
dlopen_ext_randomization_0400, dlopen_ext_randomization_0400,
dlopen_ext_randomization_0600, dlopen_ext_randomization_0600,
dlopen_ext_randomization_0800, dlopen_ext_randomization_0800,
dlopen_ext_randomization_0900,
dlopen_ns_randomization_0100, dlopen_ns_randomization_0100,
dlopen_ns_randomization_0200, dlopen_ns_randomization_0200,
dlopen_ns_randomization_0300, dlopen_ns_randomization_0300,
......
...@@ -63,12 +63,12 @@ static void clear_handle(void *handle) ...@@ -63,12 +63,12 @@ static void clear_handle(void *handle)
} }
} }
static void test_wirte_relro_file(const char* lib, const int relro_fd) static void test_write_relro_file(const char* lib, const int relro_fd)
{ {
pid_t pid = fork(); pid_t pid = fork();
if (pid == 0) { if (pid == 0) {
dl_extinfo extinfo = { dl_extinfo extinfo = {
.flag = DL_EXT_WIRTE_INFO, .flag = DL_EXT_WRITE_RELRO,
.relro_fd = relro_fd, .relro_fd = relro_fd,
}; };
void* handle = dlopen_ext(lib, RTLD_NOW, &extinfo); void* handle = dlopen_ext(lib, RTLD_NOW, &extinfo);
...@@ -126,7 +126,7 @@ static void dlopen_ext_relro_0300(void) ...@@ -126,7 +126,7 @@ static void dlopen_ext_relro_0300(void)
/** /**
* @tc.name : dlopen_ext_relro_0400 * @tc.name : dlopen_ext_relro_0400
* @tc.desc : extinfo flag is DL_EXT_WIRTE_INFO, relro_fd is valid, call dlopen_ext, return handle is not NULL. * @tc.desc : extinfo flag is DL_EXT_WRITE_RELRO, relro_fd is valid, call dlopen_ext, return handle is not NULL.
* @tc.level : Level 1 * @tc.level : Level 1
*/ */
static void dlopen_ext_relro_0400(void) static void dlopen_ext_relro_0400(void)
...@@ -141,7 +141,7 @@ static void dlopen_ext_relro_0400(void) ...@@ -141,7 +141,7 @@ static void dlopen_ext_relro_0400(void)
return; return;
} }
dl_extinfo extinfo = { dl_extinfo extinfo = {
.flag = DL_EXT_WIRTE_INFO, .flag = DL_EXT_WRITE_RELRO,
.relro_fd = relro_fd, .relro_fd = relro_fd,
}; };
void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo); void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
...@@ -152,13 +152,13 @@ static void dlopen_ext_relro_0400(void) ...@@ -152,13 +152,13 @@ static void dlopen_ext_relro_0400(void)
/** /**
* @tc.name : dlopen_ext_relro_0500 * @tc.name : dlopen_ext_relro_0500
* @tc.desc : extinfo flag is DL_EXT_WIRTE_INFO, relro_fd is not valid, call dlopen_ext, return handle is NULL. * @tc.desc : extinfo flag is DL_EXT_WRITE_RELRO, relro_fd is not valid, call dlopen_ext, return handle is NULL.
* @tc.level : Level 2 * @tc.level : Level 2
*/ */
static void dlopen_ext_relro_0500(void) static void dlopen_ext_relro_0500(void)
{ {
dl_extinfo extinfo = { dl_extinfo extinfo = {
.flag = DL_EXT_WIRTE_INFO, .flag = DL_EXT_WRITE_RELRO,
.relro_fd = -1, .relro_fd = -1,
}; };
void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo); void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
...@@ -168,7 +168,7 @@ static void dlopen_ext_relro_0500(void) ...@@ -168,7 +168,7 @@ static void dlopen_ext_relro_0500(void)
/** /**
* @tc.name : dlopen_ext_relro_0600 * @tc.name : dlopen_ext_relro_0600
* @tc.desc : extinfo flag is DL_EXT_USE_INFO, relro_fd is valid, call dlopen_ext, return handle is not NULL. * @tc.desc : extinfo flag is DL_EXT_USE_RELRO, relro_fd is valid, call dlopen_ext, return handle is not NULL.
* @tc.level : Level 1 * @tc.level : Level 1
*/ */
static void dlopen_ext_relro_0600(void) static void dlopen_ext_relro_0600(void)
...@@ -182,9 +182,9 @@ static void dlopen_ext_relro_0600(void) ...@@ -182,9 +182,9 @@ static void dlopen_ext_relro_0600(void)
t_error("%s relro file %s open failed error is : %s \n", __FUNCTION__, relro_file, dlerror()); t_error("%s relro file %s open failed error is : %s \n", __FUNCTION__, relro_file, dlerror());
return; return;
} }
test_wirte_relro_file(LIB_NAME, relro_fd); test_write_relro_file(LIB_NAME, relro_fd);
dl_extinfo extinfo = { dl_extinfo extinfo = {
.flag = DL_EXT_USE_INFO, .flag = DL_EXT_USE_RELRO,
.relro_fd = relro_fd, .relro_fd = relro_fd,
}; };
void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo); void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
...@@ -195,7 +195,7 @@ static void dlopen_ext_relro_0600(void) ...@@ -195,7 +195,7 @@ static void dlopen_ext_relro_0600(void)
/** /**
* @tc.name : dlopen_ext_relro_0700 * @tc.name : dlopen_ext_relro_0700
* @tc.desc : extinfo flag is DL_EXT_USE_INFO, relro_fd is not valid, call dlopen_ext, return handle is NULL. * @tc.desc : extinfo flag is DL_EXT_USE_RELRO, relro_fd is not valid, call dlopen_ext, return handle is NULL.
* @tc.level : Level 2 * @tc.level : Level 2
*/ */
static void dlopen_ext_relro_0700(void) static void dlopen_ext_relro_0700(void)
...@@ -209,9 +209,9 @@ static void dlopen_ext_relro_0700(void) ...@@ -209,9 +209,9 @@ static void dlopen_ext_relro_0700(void)
t_error("%s relro file %s open failed error is : %s \n", __FUNCTION__, relro_file, dlerror()); t_error("%s relro file %s open failed error is : %s \n", __FUNCTION__, relro_file, dlerror());
return; return;
} }
test_wirte_relro_file(LIB_NAME, relro_fd); test_write_relro_file(LIB_NAME, relro_fd);
dl_extinfo extinfo = { dl_extinfo extinfo = {
.flag = DL_EXT_USE_INFO, .flag = DL_EXT_USE_RELRO,
.relro_fd = -1, .relro_fd = -1,
}; };
void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo); void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
...@@ -222,7 +222,7 @@ static void dlopen_ext_relro_0700(void) ...@@ -222,7 +222,7 @@ static void dlopen_ext_relro_0700(void)
/** /**
* @tc.name : dlopen_ext_relro_0800 * @tc.name : dlopen_ext_relro_0800
* @tc.desc : extinfo flag is DL_EXT_WIRTE_INFO | DL_EXT_RESERVED_ADDRESS_RECURSIVE, relro_fd is valid, * @tc.desc : extinfo flag is DL_EXT_WRITE_RELRO | DL_EXT_RESERVED_ADDRESS_RECURSIVE, relro_fd is valid,
* call dlopen_ext, return handle is not NULL. * call dlopen_ext, return handle is not NULL.
* @tc.level : Level 1 * @tc.level : Level 1
*/ */
...@@ -238,7 +238,7 @@ static void dlopen_ext_relro_0800(void) ...@@ -238,7 +238,7 @@ static void dlopen_ext_relro_0800(void)
return; return;
} }
dl_extinfo extinfo = { dl_extinfo extinfo = {
.flag = DL_EXT_WIRTE_INFO | DL_EXT_RESERVED_ADDRESS_RECURSIVE, .flag = DL_EXT_WRITE_RELRO | DL_EXT_RESERVED_ADDRESS_RECURSIVE,
.relro_fd = relro_fd, .relro_fd = relro_fd,
}; };
void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo); void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
...@@ -249,13 +249,13 @@ static void dlopen_ext_relro_0800(void) ...@@ -249,13 +249,13 @@ static void dlopen_ext_relro_0800(void)
/** /**
* @tc.name : dlopen_ext_relro_0900 * @tc.name : dlopen_ext_relro_0900
* @tc.desc : extinfo flag is DL_EXT_WIRTE_INFO, relro_fd is not valid, call dlopen_ext, return handle is NULL. * @tc.desc : extinfo flag is DL_EXT_WRITE_RELRO, relro_fd is not valid, call dlopen_ext, return handle is NULL.
* @tc.level : Level 2 * @tc.level : Level 2
*/ */
static void dlopen_ext_relro_0900(void) static void dlopen_ext_relro_0900(void)
{ {
dl_extinfo extinfo = { dl_extinfo extinfo = {
.flag = DL_EXT_WIRTE_INFO | DL_EXT_RESERVED_ADDRESS_RECURSIVE, .flag = DL_EXT_WRITE_RELRO | DL_EXT_RESERVED_ADDRESS_RECURSIVE,
.relro_fd = -1, .relro_fd = -1,
}; };
void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo); void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
...@@ -266,7 +266,7 @@ static void dlopen_ext_relro_0900(void) ...@@ -266,7 +266,7 @@ static void dlopen_ext_relro_0900(void)
/** /**
* @tc.name : dlopen_ext_relro_1000 * @tc.name : dlopen_ext_relro_1000
* @tc.desc : extinfo flag is DL_EXT_USE_INFO | DL_EXT_RESERVED_ADDRESS_RECURSIVE, relro_fd is valid, * @tc.desc : extinfo flag is DL_EXT_USE_RELRO | DL_EXT_RESERVED_ADDRESS_RECURSIVE, relro_fd is valid,
* call dlopen_ext, return handle is not NULL. * call dlopen_ext, return handle is not NULL.
* @tc.level : Level 1 * @tc.level : Level 1
*/ */
...@@ -281,9 +281,9 @@ static void dlopen_ext_relro_1000(void) ...@@ -281,9 +281,9 @@ static void dlopen_ext_relro_1000(void)
t_error("%s relro file %s open failed error is : %s \n", __FUNCTION__, relro_file, dlerror()); t_error("%s relro file %s open failed error is : %s \n", __FUNCTION__, relro_file, dlerror());
return; return;
} }
test_wirte_relro_file(LIB_NAME, relro_fd); test_write_relro_file(LIB_NAME, relro_fd);
dl_extinfo extinfo = { dl_extinfo extinfo = {
.flag = DL_EXT_USE_INFO | DL_EXT_RESERVED_ADDRESS_RECURSIVE, .flag = DL_EXT_USE_RELRO | DL_EXT_RESERVED_ADDRESS_RECURSIVE,
.relro_fd = relro_fd, .relro_fd = relro_fd,
}; };
void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo); void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
...@@ -294,7 +294,7 @@ static void dlopen_ext_relro_1000(void) ...@@ -294,7 +294,7 @@ static void dlopen_ext_relro_1000(void)
/** /**
* @tc.name : dlopen_ext_relro_1100 * @tc.name : dlopen_ext_relro_1100
* @tc.desc : extinfo flag is DL_EXT_USE_INFO | DL_EXT_RESERVED_ADDRESS_RECURSIVE, relro_fd is not valid, * @tc.desc : extinfo flag is DL_EXT_USE_RELRO | DL_EXT_RESERVED_ADDRESS_RECURSIVE, relro_fd is not valid,
* call dlopen_ext, return handle is NULL. * call dlopen_ext, return handle is NULL.
* @tc.level : Level 2 * @tc.level : Level 2
*/ */
...@@ -309,9 +309,9 @@ static void dlopen_ext_relro_1100(void) ...@@ -309,9 +309,9 @@ static void dlopen_ext_relro_1100(void)
t_error("%s relro file %s open failed error is : %s \n", __FUNCTION__, relro_file, dlerror()); t_error("%s relro file %s open failed error is : %s \n", __FUNCTION__, relro_file, dlerror());
return; return;
} }
test_wirte_relro_file(LIB_NAME, relro_fd); test_write_relro_file(LIB_NAME, relro_fd);
dl_extinfo extinfo = { dl_extinfo extinfo = {
.flag = DL_EXT_USE_INFO | DL_EXT_RESERVED_ADDRESS_RECURSIVE, .flag = DL_EXT_USE_RELRO | DL_EXT_RESERVED_ADDRESS_RECURSIVE,
.relro_fd = -1, .relro_fd = -1,
}; };
void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo); void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
...@@ -322,7 +322,7 @@ static void dlopen_ext_relro_1100(void) ...@@ -322,7 +322,7 @@ static void dlopen_ext_relro_1100(void)
/** /**
* @tc.name : dlopen_ext_relro_1200 * @tc.name : dlopen_ext_relro_1200
* @tc.desc : extinfo flag is DL_EXT_USE_INFO when relro file do not wirte, * @tc.desc : extinfo flag is DL_EXT_USE_RELRO when relro file do not write,
* when call dlopen_ext, return handle is NULL. * when call dlopen_ext, return handle is NULL.
* @tc.level : Level 2 * @tc.level : Level 2
*/ */
...@@ -338,7 +338,7 @@ static void dlopen_ext_relro_1200(void) ...@@ -338,7 +338,7 @@ static void dlopen_ext_relro_1200(void)
return; return;
} }
dl_extinfo extinfo = { dl_extinfo extinfo = {
.flag = DL_EXT_USE_INFO, .flag = DL_EXT_USE_RELRO,
.relro_fd = relro_fd, .relro_fd = relro_fd,
}; };
void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo); void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
...@@ -349,7 +349,7 @@ static void dlopen_ext_relro_1200(void) ...@@ -349,7 +349,7 @@ static void dlopen_ext_relro_1200(void)
/** /**
* @tc.name : dlopen_ext_relro_1500 * @tc.name : dlopen_ext_relro_1500
* @tc.desc : extinfo flag is DL_EXT_USE_INFO | DL_EXT_WIRTE_INFO, relro_fd is valid, * @tc.desc : extinfo flag is DL_EXT_USE_RELRO | DL_EXT_WRITE_RELRO, relro_fd is valid,
* call dlopen_ext, return handle is not NULL. * call dlopen_ext, return handle is not NULL.
* @tc.level : Level 1 * @tc.level : Level 1
*/ */
...@@ -364,9 +364,9 @@ static void dlopen_ext_relro_1500(void) ...@@ -364,9 +364,9 @@ static void dlopen_ext_relro_1500(void)
t_error("%s relro file %s open failed error is : %s \n", __FUNCTION__, relro_file, dlerror()); t_error("%s relro file %s open failed error is : %s \n", __FUNCTION__, relro_file, dlerror());
return; return;
} }
test_wirte_relro_file(LIB_NAME, relro_fd); test_write_relro_file(LIB_NAME, relro_fd);
dl_extinfo extinfo = { dl_extinfo extinfo = {
.flag = DL_EXT_WIRTE_INFO | DL_EXT_USE_INFO, .flag = DL_EXT_WRITE_RELRO | DL_EXT_USE_RELRO,
.relro_fd = relro_fd, .relro_fd = relro_fd,
}; };
void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo); void* handle = dlopen_ext(LIB_NAME, RTLD_NOW, &extinfo);
......
...@@ -23,12 +23,12 @@ extern "C" { ...@@ -23,12 +23,12 @@ extern "C" {
#endif #endif
/* for dl_extinfo flag */ /* for dl_extinfo flag */
#define DL_EXT_WIRTE_INFO 0x1 #define DL_EXT_WRITE_RELRO 0x1
#define DL_EXT_USE_INFO 0x2 #define DL_EXT_USE_RELRO 0x2
#define DL_EXT_RESERVED_ADDRESS_RECURSIVE 0x4 #define DL_EXT_RESERVED_ADDRESS_RECURSIVE 0x4
/** Mask of valid bits. */ /** Mask of valid bits. */
#define DL_EXT_VALID_FLAG_BITS (DL_EXT_WIRTE_INFO | DL_EXT_USE_INFO | DL_EXT_RESERVED_ADDRESS_RECURSIVE) #define DL_EXT_VALID_FLAG_BITS (DL_EXT_WRITE_RELRO | DL_EXT_USE_RELRO | DL_EXT_RESERVED_ADDRESS_RECURSIVE)
typedef struct { typedef struct {
int flag; int flag;
...@@ -38,9 +38,9 @@ typedef struct { ...@@ -38,9 +38,9 @@ typedef struct {
/** /**
* @brief Loads the dynamic shared object (shared library) file with the extended feature. * @brief Loads the dynamic shared object (shared library) file with the extended feature.
* If extinfo is NULL, it is equivalent to dlopen. * If extinfo is NULL, it is equivalent to dlopen.
* If DL_EXT_WIRTE_INFO is set in extinfo, the GNU RELRO section will be written to relro_fd and allowed to * If DL_EXT_WRITE_RELRO is set in extinfo, the GNU RELRO section will be written to relro_fd and allowed to
* reused by other process loading the same library at the same address. * reused by other process loading the same library at the same address.
* IF DL_EXT_USE_INFO is set in extinfo, the GNU RELRO section written in relro_fd will be reused. * IF DL_EXT_USE_RELRO is set in extinfo, the GNU RELRO section written in relro_fd will be reused.
* @param file Equivalent to the argument of dlopen. * @param file Equivalent to the argument of dlopen.
* @param mode Equivalent to the argument of dlopen. * @param mode Equivalent to the argument of dlopen.
* @param extinfo Indicates the dl_extinfo struct. * @param extinfo Indicates the dl_extinfo struct.
......
...@@ -3940,14 +3940,14 @@ static void handle_relro_sharing(struct dso *p, const dl_extinfo *extinfo, ssize ...@@ -3940,14 +3940,14 @@ static void handle_relro_sharing(struct dso *p, const dl_extinfo *extinfo, ssize
if (extinfo == NULL) { if (extinfo == NULL) {
return; return;
} }
if (extinfo->flag & DL_EXT_WIRTE_INFO) { if (extinfo->flag & DL_EXT_WRITE_RELRO) {
LD_LOGD("Serializing GNU_RELRO %s", p->name); LD_LOGD("Serializing GNU_RELRO %s", p->name);
if (serialize_gnu_relro(extinfo->relro_fd, p, relro_fd_offset) < 0) { if (serialize_gnu_relro(extinfo->relro_fd, p, relro_fd_offset) < 0) {
LD_LOGE("Error serializing GNU_RELRO %s", p->name); LD_LOGE("Error serializing GNU_RELRO %s", p->name);
error("Error serializing GNU_RELRO"); error("Error serializing GNU_RELRO");
if (runtime) longjmp(*rtld_fail, 1); if (runtime) longjmp(*rtld_fail, 1);
} }
} else if (extinfo->flag & DL_EXT_USE_INFO) { } else if (extinfo->flag & DL_EXT_USE_RELRO) {
LD_LOGD("Mapping GNU_RELRO %s", p->name); LD_LOGD("Mapping GNU_RELRO %s", p->name);
if (map_gnu_relro(extinfo->relro_fd, p, relro_fd_offset) < 0) { if (map_gnu_relro(extinfo->relro_fd, p, relro_fd_offset) < 0) {
LD_LOGE("Error mapping GNU_RELRO %s", p->name); LD_LOGE("Error mapping GNU_RELRO %s", p->name);
......
...@@ -162,6 +162,10 @@ void free_task(struct loadtask *task) ...@@ -162,6 +162,10 @@ void free_task(struct loadtask *task)
if (task == NULL) { if (task == NULL) {
return; return;
} }
if (task->name) {
free(task->name);
task->name = NULL;
}
if (task->allocated_buf) { if (task->allocated_buf) {
free(task->allocated_buf); free(task->allocated_buf);
task->allocated_buf = NULL; task->allocated_buf = NULL;
...@@ -228,11 +232,17 @@ void shuffle_loadtasks(struct loadtasks *tasks) ...@@ -228,11 +232,17 @@ void shuffle_loadtasks(struct loadtasks *tasks)
struct loadtask *create_loadtask(const char *name, struct dso *needed_by, ns_t *ns, bool check_inherited) struct loadtask *create_loadtask(const char *name, struct dso *needed_by, ns_t *ns, bool check_inherited)
{ {
size_t name_len = strlen(name);
char *name_buf = (char *)malloc(name_len + 1);
if (!name_buf) {
return NULL;
}
struct loadtask *task = calloc(1, sizeof(struct loadtask)); struct loadtask *task = calloc(1, sizeof(struct loadtask));
if (!task) { if (!task) {
return NULL; return NULL;
} }
task->name = name; strcpy(name_buf, name);
task->name = name_buf;
task->needed_by = needed_by; task->needed_by = needed_by;
task->namespace = ns; task->namespace = ns;
task->check_inherited = check_inherited; task->check_inherited = check_inherited;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册