iSulad/0015-refactor-util_getgrent_r-and-util_getpwent_r.patch

409 lines
12 KiB
Diff
Raw Normal View History

From 8da6dd20b73068e9d29fc8ed1469ade7b1dc2c12 Mon Sep 17 00:00:00 2001
From: haozi007 <liuhao27@huawei.com>
Date: Sat, 14 May 2022 09:55:18 +0100
Subject: [PATCH 15/16] refactor util_getgrent_r and util_getpwent_r
Signed-off-by: haozi007 <liuhao27@huawei.com>
---
src/utils/cutils/utils_pwgr.c | 215 +++++++++++-------------
test/cutils/utils_pwgr/passwd_sample | 8 +-
test/cutils/utils_pwgr/utils_pwgr_ut.cc | 8 +-
3 files changed, 109 insertions(+), 122 deletions(-)
diff --git a/src/utils/cutils/utils_pwgr.c b/src/utils/cutils/utils_pwgr.c
index 17cf017b..f8e4a18e 100644
--- a/src/utils/cutils/utils_pwgr.c
+++ b/src/utils/cutils/utils_pwgr.c
@@ -29,100 +29,82 @@
static int hold_int(const char delim, bool required, char **src, unsigned int *dst)
{
- long long res = 0;
- char *walker = *src;
+ unsigned long long int res = 0;
char *err_str = NULL;
+ // ensure *src not a empty string
if (**src == '\0') {
ERROR("Empty subject on given entrie is not allowed.");
return -1;
}
- while (*walker != delim) {
- if (*walker == '\0') {
- break;
- }
- ++walker;
- }
-
- if (*walker == **src) {
- if (required) { // deafult 0 while required full content but integer part is missing
- *dst = 0;
- *src = walker + 1;
- return 0;
- }
- ERROR("Integer part is missing.");
- ++(*src);
- return -1;
- }
-
- res = strtoll(*src, &err_str, 0);
- if (err_str == *src) {
- ERROR("invalid digits string.");
- return -1;
- }
+ // covert string to long long
+ res = strtoull(*src, &err_str, 0);
+ // large digit string, return error
if (errno == ERANGE) {
ERROR("Parse int from string failed.");
return -1;
}
- if (res < 0) {
- ERROR("Gid uid shall not be negative.");
- return -1;
+
+ // **src is not a digit
+ if (err_str == *src) {
+ if (!required) {
+ ERROR("Integer part is missing.");
+ return -1;
+ }
+ // if required, just set 0
+ *dst = 0;
+ } else {
+ if (sizeof(void *) > 4 && res > UINT_MAX) { // make sure 64-bit platform behave same as 32-bit
+ res = UINT_MAX;
+ }
+ res = res & UINT_MAX;
+ *dst = (uint32_t)res;
}
- if (sizeof(void *) > 4 && res > UINT_MAX) { // make sure 64-bit platform behave same as 32-bit
- res = UINT_MAX;
+ // normal case
+ if (*err_str == delim) {
+ err_str++;
+ } else if (*err_str != '\0') {
+ ERROR("Invalid digit string.");
+ return -1;
}
- res = res & UINT_MAX;
- *dst = (uint32_t)res;
- *src = err_str + 1; // update src to next valid context in line.
+ *src = err_str; // update src to next valid context in line.
return 0;
}
-static int hold_string(const char delim, char **src, char **dst)
+static void hold_string(const char delim, char **src, char **dst)
{
- if (**src == delim) { // if src point to deliminator, content parsing is skiped.
- *dst = "";
- *src = *src + 1;
- return 0;
- }
-
- if (**src == '\0') {
- return 0;
- }
-
for (*dst = *src; **src != delim; ++(*src)) {
if (**src == '\0') {
break;
}
}
+
if (**src == delim) {
**src = '\0';
++(*src);
}
-
- return 0;
}
static int parse_line_pw(const char delim, char *line, struct passwd *result)
{
int ret = 0;
bool required = false;
+ char *walker = NULL;
- ret = hold_string(delim, &line, &result->pw_name);
- if (ret != 0) {
- ERROR("Parse name error.");
- return ret;
+ walker = strpbrk(line, "\n");
+ if (walker != NULL) {
+ // clear newline char
+ *walker = '\0';
}
+ hold_string(delim, &line, &result->pw_name);
+
required = (result->pw_name[0] == '+' || result->pw_name[0] == '-') ? true : false;
- ret = hold_string(delim, &line, &result->pw_passwd);
- if (ret != 0) {
- ERROR("Parse passwd error.");
- return ret;
- }
+ hold_string(delim, &line, &result->pw_passwd);
ret = hold_int(delim, required, &line, &result->pw_uid);
if (ret != 0) {
@@ -130,31 +112,20 @@ static int parse_line_pw(const char delim, char *line, struct passwd *result)
ERROR("Parse uid error.");
return ret;
}
+
ret = hold_int(delim, required, &line, &result->pw_gid);
if (ret != 0) {
// it's ok to not provide gid
ERROR("Parse gid error.");
- }
-
- ret = hold_string(delim, &line, &result->pw_gecos);
- if (ret != 0) {
- ERROR("Parse gecos error.");
return ret;
}
- ret = hold_string(delim, &line, &result->pw_dir);
- if (ret != 0) {
- ERROR("Parse dir error.");
- return ret;
- }
+ hold_string(delim, &line, &result->pw_gecos);
- ret = hold_string(delim, &line, &result->pw_shell);
- if (ret != 0) {
- ERROR("Parse shell error.");
- return ret;
- }
+ hold_string(delim, &line, &result->pw_dir);
- return ret;
+ result->pw_shell = line;
+ return 0;
}
static char **hold_string_list(char **line, char *buf_start, char *buf_end, const char terminator)
@@ -172,42 +143,38 @@ static char **hold_string_list(char **line, char *buf_start, char *buf_end, cons
walker = result;
for (; walker < (char **)buf_end; ++walker) {
- (void)util_trim_space(*line);
- if (hold_string(',', line, walker) != 0) {
- ERROR("Parse string list error.");
+ if (**line == '\0') {
return result;
}
+ (void)util_trim_space(*line);
+ hold_string(',', line, walker);
+
if ((char *)(walker + 2) > buf_end) {
return NULL;
}
-
- if (**line == '\0') {
- return result;
- }
}
return result;
}
-static int parse_line_gr(const char delim, char *line, size_t buflen, struct group *result)
+static int parse_line_gr(const char delim, char *line, char *buffend, struct group *result)
{
int ret = 0;
bool rf = false;
char *freebuff = line + 1 + strlen(line);
- char *buffend = line + buflen;
+ char *walker = NULL;
- ret = hold_string(delim, &line, &result->gr_name);
- if (ret != 0) {
- ERROR("Parse name error.");
- return ret;
+ walker = strpbrk(line, "\n");
+ if (walker != NULL) {
+ // clear newline char
+ *walker = '\0';
}
- ret = hold_string(delim, &line, &result->gr_passwd);
- if (ret != 0) {
- ERROR("Parse gecos error.");
- return ret;
- }
+ hold_string(delim, &line, &result->gr_name);
+
+ hold_string(delim, &line, &result->gr_passwd);
+
if (result->gr_name[0] == '+' || result->gr_name[0] == '-') {
rf = true;
}
@@ -231,6 +198,7 @@ int util_getpwent_r(FILE *stream, struct passwd *resbuf, char *buffer, size_t bu
{
const char delim = ':';
char *buff_end = NULL;
+ char *walker = NULL;
bool got = false;
if (stream == NULL || resbuf == NULL || buffer == NULL || result == NULL) {
@@ -250,27 +218,36 @@ int util_getpwent_r(FILE *stream, struct passwd *resbuf, char *buffer, size_t bu
__fsetlocking(stream, FSETLOCKING_BYCALLER);
- if (feof(stream)) {
- *result = NULL;
- return ENOENT;
- }
buff_end = buffer + buflen - 1;
+ while (1) {
+ *buff_end = '\xff';
+ walker = fgets(buffer, buflen, stream);
+ // if get NULL string
+ if (walker == NULL) {
+ *result = NULL;
+ // reach end of file, return error
+ if (feof(stream)) {
+ return ENOENT;
+ }
+ // overflow buffer
+ return ERANGE;
+ }
+ // just overflow last char in buffer
+ if (*buff_end != '\xff') {
+ *result = NULL;
+ return ERANGE;
+ }
- while ((*buff_end = '\xff') && fgets(buffer, buflen, stream) != NULL) {
(void)util_trim_space(buffer);
- if (buffer[0] == '\0' || buffer[0] == '#' || strlen(buffer) < 1) {
+ // skip comment line and empty line
+ if (walker[0] == '#' || walker[0] == '\0') {
continue;
}
- if (parse_line_pw(delim, buffer, resbuf) == 0) {
+ if (parse_line_pw(delim, walker, resbuf) == 0) {
got = true;
break;
}
-
- if (*buff_end != '\xff') {
- *result = NULL;
- return ERANGE;
- }
}
if (!got) {
*result = NULL;
@@ -286,6 +263,7 @@ int util_getgrent_r(FILE *stream, struct group *resbuf, char *buffer, size_t buf
{
const char delim = ':';
char *buff_end = NULL;
+ char *walker = NULL;
bool got = false;
if (stream == NULL || resbuf == NULL || buffer == NULL || result == NULL) {
@@ -305,27 +283,36 @@ int util_getgrent_r(FILE *stream, struct group *resbuf, char *buffer, size_t buf
__fsetlocking(stream, FSETLOCKING_BYCALLER);
- if (feof(stream)) {
- *result = NULL;
- return ENOENT;
- }
buff_end = buffer + buflen - 1;
+ while (1) {
+ *buff_end = '\xff';
+ walker = fgets(buffer, buflen, stream);
+ // if get NULL string
+ if (walker == NULL) {
+ *result = NULL;
+ // reach end of file, return error
+ if (feof(stream)) {
+ return ENOENT;
+ }
+ // overflow buffer
+ return ERANGE;
+ }
+ // just overflow last char in buffer
+ if (*buff_end != '\xff') {
+ *result = NULL;
+ return ERANGE;
+ }
- while ((*buff_end = '\xff') && fgets(buffer, buflen, stream) != NULL) {
- (void)util_trim_space(buffer);
- if (buffer[0] == '\0' || buffer[0] == '#' || strlen(buffer) < 1) {
+ (void)util_trim_space(walker);
+ // skip comment line and empty line
+ if (walker[0] == '#' || walker[0] == '\0') {
continue;
}
- if (parse_line_gr(delim, buffer, buflen, resbuf) == 0) {
+ if (parse_line_gr(delim, walker, buff_end, resbuf) == 0) {
got = true;
break;
}
-
- if (*buff_end != '\xff') {
- *result = NULL;
- return ERANGE;
- }
}
if (!got) {
diff --git a/test/cutils/utils_pwgr/passwd_sample b/test/cutils/utils_pwgr/passwd_sample
index 995dea3a..cdb1890d 100644
--- a/test/cutils/utils_pwgr/passwd_sample
+++ b/test/cutils/utils_pwgr/passwd_sample
@@ -1,13 +1,13 @@
root:x:b:0:
root:x:0:0:root:/root:/bin/bash
-bin:x:1:1:bin:/bin:/sbin/nologin
-bin:x:-1:1:bin:/bin:/sbin/nologin
+abin:x:1:1:bin:/bin:/sbin/nologin
+bbin:x:-1:1:bin:/bin:/sbin/nologin
uidonly:x:1::bin:/bin:/sbin/nologin
::::1:1:bin:/bin:/sbin/nologin
root:x:
#npt:*:66:77::/etc/ntp:/sbin/nologin
-npt:*:66:77::/etc/ntp:/sbin/nologin
-npt:*:66:77::/etc/ntp:/sbin/nologin:some:extra:context:added
+anpt:*:66:77::/etc/ntp:/sbin/nologin
+bnpt:*:66:77::/etc/ntp:/sbin/nologin:some:extra:context:added
+npt:*::::/etc/ntp:/sbin/nologin
-npt:*::::/etc/ntp:/sbin/nologin
\ No newline at end of file
diff --git a/test/cutils/utils_pwgr/utils_pwgr_ut.cc b/test/cutils/utils_pwgr/utils_pwgr_ut.cc
index d856270d..1f3dab9e 100644
--- a/test/cutils/utils_pwgr/utils_pwgr_ut.cc
+++ b/test/cutils/utils_pwgr/utils_pwgr_ut.cc
@@ -32,10 +32,10 @@ TEST(utils_pwgr, test_getpwent_r)
std::vector<std::tuple<std::string, std::string, int, int, std::string, std::string, std::string>> testcase = {
std::make_tuple("root", "x", 0, 0, "root", "/root", "/bin/bash"),
- std::make_tuple("bin", "x", 1, 1, "bin", "/bin", "/sbin/nologin"),
- std::make_tuple("uidonly", "x", 1, 0, "bin", "/bin", "/sbin/nologin"),
- std::make_tuple("npt", "*", 66, 77, "", "/etc/ntp", "/sbin/nologin"),
- std::make_tuple("npt", "*", 66, 77, "", "/etc/ntp", "/sbin/nologin"),
+ std::make_tuple("abin", "x", 1, 1, "bin", "/bin", "/sbin/nologin"),
+ std::make_tuple("bbin", "x", 4294967295, 1, "bin", "/bin", "/sbin/nologin"),
+ std::make_tuple("anpt", "*", 66, 77, "", "/etc/ntp", "/sbin/nologin"),
+ std::make_tuple("bnpt", "*", 66, 77, "", "/etc/ntp", "/sbin/nologin:some:extra:context:added"),
std::make_tuple("+npt", "*", 0, 0, "", "/etc/ntp", "/sbin/nologin"),
std::make_tuple("-npt", "*", 0, 0, "", "/etc/ntp", "/sbin/nologin")
};
--
2.20.1