Skip to content

Commit bf6eb20

Browse files
committed
Feature: fencer: Improve validation of pcmk_host_map
Previously, if we hit a parsing error in pcmk_host_map, we logged a debug message and continued trying to parse the rest of the value. It's hard to be confident about the resulting behavior. Now, we stop parsing if we encounter an error. Also as part of this commit, we use g_strsplit_set() twice. At the first level, we use it to split the list of node-name-to-port mappings in pcmk_host_map, using ';', ' ', and '\t' as delimiters. At the second level, we use it to split each mapping, using '=' and ':' as delimiters. Support for '=' is likely to be removed in a future release. I greatly struggled to reason about the existing code based on "last = i + 1". It felt as if there were lots of potential edge cases. The behavior may not be identical as of this commit, but it should be more robust and predictable, and the code should be easier to maintain. Signed-off-by: Reid Wahl <[email protected]>
1 parent 544e530 commit bf6eb20

File tree

1 file changed

+25
-45
lines changed

1 file changed

+25
-45
lines changed

daemons/fenced/fenced_commands.c

Lines changed: 25 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -901,63 +901,43 @@ fenced_free_device_table(void)
901901
}
902902

903903
static GHashTable *
904-
build_port_aliases(const char *hostmap, GList ** targets)
904+
build_port_aliases(const char *hostmap, GList **targets)
905905
{
906-
char *name = NULL;
907-
int last = 0;
908-
size_t len = 0;
909906
GHashTable *aliases = pcmk__strikey_table(free, free);
907+
gchar *stripped = NULL;
908+
gchar **mappings = NULL;
910909

911-
if (hostmap == NULL) {
912-
return aliases;
910+
if (pcmk__str_empty(hostmap)) {
911+
goto done;
913912
}
914913

915-
len = strlen(hostmap);
916-
for (int i = 0; i <= len; i++) {
917-
switch (hostmap[i]) {
918-
/* Assignment chars */
919-
case '=':
920-
case ':':
921-
if (i > last) {
922-
free(name);
923-
name = pcmk__assert_alloc(1 + i - last, sizeof(char));
924-
memcpy(name, hostmap + last, i - last);
925-
}
926-
last = i + 1;
927-
break;
914+
stripped = g_strstrip(g_strdup(hostmap));
915+
mappings = g_strsplit_set(stripped, "; \t", 0);
928916

929-
/* Delimeter chars */
930-
/* case ',': Potentially used to specify multiple ports */
931-
case 0:
932-
case ';':
933-
case ' ':
934-
case '\t':
935-
if (name) {
936-
char *value = pcmk__assert_alloc(1 + i - last,
937-
sizeof(char));
938-
939-
memcpy(value, hostmap + last, i - last);
940-
941-
crm_debug("Adding alias '%s'='%s'", name, value);
942-
g_hash_table_replace(aliases, name, value);
943-
*targets = g_list_append(*targets, pcmk__str_copy(value));
944-
name = NULL;
945-
946-
} else if (i > last) {
947-
crm_debug("Parse error at offset %d near '%s'", i - last,
948-
hostmap + last);
949-
}
917+
for (gchar **mapping = mappings; *mapping != NULL; mapping++) {
918+
gchar **nvpair = NULL;
950919

951-
last = i + 1;
952-
break;
920+
if (pcmk__str_empty(*mapping)) {
921+
continue;
953922
}
954923

955-
if (hostmap[i] == 0) {
956-
break;
924+
// @COMPAT Drop support for '=' as delimiter
925+
nvpair = g_strsplit_set(*mapping, ":=", 2);
926+
927+
if (pcmk__str_empty(nvpair[0]) || pcmk__str_empty(nvpair[1])) {
928+
crm_err(PCMK_FENCING_HOST_MAP ": Malformed mapping '%s'", *mapping);
929+
930+
} else {
931+
crm_debug("Adding alias '%s'='%s'", nvpair[0], nvpair[1]);
932+
pcmk__insert_dup(aliases, nvpair[0], nvpair[1]);
933+
*targets = g_list_append(*targets, pcmk__str_copy(nvpair[1]));
957934
}
935+
g_strfreev(nvpair);
958936
}
959937

960-
free(name);
938+
done:
939+
g_free(stripped);
940+
g_strfreev(mappings);
961941
return aliases;
962942
}
963943

0 commit comments

Comments
 (0)