summaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorMichal Zidek <mzidek@redhat.com>2012-10-15 12:21:00 +0200
committerJakub Hrozek <jhrozek@redhat.com>2013-01-02 17:44:09 +0100
commit04759b59e71c78ab23b84d13dd29d9c6dd680adb (patch)
treede8f6137712f7fc8ade86a7a89bb96905db3a240 /src/util
parentfc647b8eb5bca901658dedf3dbda2f35c63a86f2 (diff)
downloadsssd-04759b59e71c78ab23b84d13dd29d9c6dd680adb.tar.gz
sssd-04759b59e71c78ab23b84d13dd29d9c6dd680adb.tar.bz2
sssd-04759b59e71c78ab23b84d13dd29d9c6dd680adb.zip
failover: Protect against empty host names
Added new parameter to split_on_separator that allows to skip empty values. The whole function was rewritten. Unit test case was added to check the new implementation. https://fedorahosted.org/sssd/ticket/1484
Diffstat (limited to 'src/util')
-rw-r--r--src/util/util.c161
-rw-r--r--src/util/util.h3
2 files changed, 72 insertions, 92 deletions
diff --git a/src/util/util.c b/src/util/util.c
index ab980775..b035e231 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -27,118 +27,97 @@
#include "util/sss_utf8.h"
#include "dhash.h"
-/* split a string into an allocated array of strings.
- * the separator is a string, and is case-sensitive.
- * optionally single values can be trimmed of of spaces and tabs */
int split_on_separator(TALLOC_CTX *mem_ctx, const char *str,
- const char sep, bool trim, char ***_list, int *size)
+ const char sep, bool trim, bool skip_empty,
+ char ***_list, int *size)
{
- const char *t, *p, *n;
- size_t l, len;
- char **list, **r;
- const char sep_str[2] = { sep, '\0'};
-
- if (!str || !*str || !_list) return EINVAL;
-
- t = str;
+ int ret;
+ const char *substr_end = str;
+ const char *substr_begin = str;
+ const char *sep_pos = NULL;
+ size_t substr_len;
+ char **list = NULL;
+ int num_strings = 0;
+ TALLOC_CTX *tmp_ctx = NULL;
+
+ if (str == NULL || *str == '\0' || _list == NULL) {
+ return EINVAL;
+ }
- list = NULL;
- l = 0;
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ return ENOMEM;
+ }
- /* trim leading whitespace */
- if (trim)
- while (isspace(*t)) t++;
+ do {
+ substr_len = 0;
- /* find substrings separated by the separator */
- while (t && (p = strpbrk(t, sep_str))) {
- len = p - t;
- n = p + 1; /* save next string starting point */
- if (trim) {
- /* strip whitespace after the separator
- * so it's not in the next token */
- while (isspace(*t)) {
- t++;
- len--;
- if (len == 0) break;
- }
- p--;
- /* strip whitespace before the separator
- * so it's not in the current token */
- while (len > 0 && (isspace(*p))) {
- len--;
- p--;
- }
+ /* If this is not the first substring, then move from the separator. */
+ if (sep_pos != NULL) {
+ substr_end = sep_pos + 1;
+ substr_begin = sep_pos + 1;
}
- /* Add the token to the array, +2 b/c of the trailing NULL */
- r = talloc_realloc(mem_ctx, list, char *, l + 2);
- if (!r) {
- talloc_free(list);
- return ENOMEM;
- } else {
- list = r;
+ /* Find end of the first substring */
+ while (*substr_end != sep && *substr_end != '\0') {
+ substr_end++;
+ substr_len++;
}
- if (len == 0) {
- list[l] = talloc_strdup(list, "");
- } else {
- list[l] = talloc_strndup(list, t, len);
- }
- if (!list[l]) {
- talloc_free(list);
- return ENOMEM;
- }
- l++;
+ sep_pos = substr_end;
- t = n; /* move to next string */
- }
+ if (trim) {
+ /* Trim leading whitespace */
+ while (isspace(*substr_begin) && substr_begin < substr_end) {
+ substr_begin++;
+ substr_len--;
+ }
- /* Handle the last remaining token */
- if (t) {
- r = talloc_realloc(mem_ctx, list, char *, l + 2);
- if (!r) {
- talloc_free(list);
- return ENOMEM;
- } else {
- list = r;
+ /* Trim trailing whitespace */
+ while (substr_end - 1 > substr_begin && isspace(*(substr_end-1))) {
+ substr_end--;
+ substr_len--;
+ }
}
- if (trim) {
- /* trim leading whitespace */
- len = strlen(t);
- while (isspace(*t)) {
- t++;
- len--;
- if (len == 0) break;
- }
- /* trim trailing whitespace */
- p = t + len - 1;
- while (len > 0 && (isspace(*p))) {
- len--;
- p--;
+ /* Copy the substring to the output list of strings */
+ if (skip_empty == false || substr_len > 0) {
+ list = talloc_realloc(tmp_ctx, list, char*, num_strings + 2);
+ if (list == NULL) {
+ ret = ENOMEM;
+ goto done;
}
- if (len == 0) {
- list[l] = talloc_strdup(list, "");
- } else {
- list[l] = talloc_strndup(list, t, len);
+ /* empty string is stored for substr_len == 0 */
+ list[num_strings] = talloc_strndup(list, substr_begin, substr_len);
+ if (list[num_strings] == NULL) {
+ ret = ENOMEM;
+ goto done;
}
- } else {
- list[l] = talloc_strdup(list, t);
+ num_strings++;
}
- if (!list[l]) {
- talloc_free(list);
- return ENOMEM;
+
+ } while (*sep_pos != '\0');
+
+ if (list == NULL) {
+ /* No allocations were done, make space for the NULL */
+ list = talloc(tmp_ctx, char *);
+ if (list == NULL) {
+ ret = ENOMEM;
+ goto done;
}
- l++;
}
+ list[num_strings] = NULL;
- list[l] = NULL; /* terminate list */
-
- if (size) *size = l;
- *_list = list;
+ if (size) {
+ *size = num_strings;
+ }
- return EOK;
+ *_list = talloc_steal(mem_ctx, list);
+ ret = EOK;
+done:
+ talloc_free(tmp_ctx);
+ return ret;
}
static void free_args(char **args)
diff --git a/src/util/util.h b/src/util/util.h
index c15ca668..e4cb1a86 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -476,7 +476,8 @@ errno_t check_and_open_readonly(const char *filename, int *fd, const uid_t uid,
/* from util.c */
int split_on_separator(TALLOC_CTX *mem_ctx, const char *str,
- const char sep, bool trim, char ***_list, int *size);
+ const char sep, bool trim, bool skip_empty,
+ char ***_list, int *size);
char **parse_args(const char *str);