Skip to content

Commit

Permalink
Use wordexp to resolve variables like $HOME in path like settings
Browse files Browse the repository at this point in the history
It seems like the wordexp implementation in musl leaks memory and thus a
new suppression is required to pass CI. It also doesn't fully implement
all POSIX features and thus at least one test has to be deactivated in
that case.
  • Loading branch information
zappolowski committed Oct 26, 2023
1 parent 7608b97 commit 7ec7005
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 13 deletions.
13 changes: 13 additions & 0 deletions .valgrind.suppressions
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@
obj:/lib/ld-musl-x86_64.so.1
}

# Ignore another musls' weird error
{
musl_alpine_libc
Memcheck:Leak
match-leak-kinds: definite
fun:malloc
fun:realloc
fun:getdelim
obj:*
fun:vgMemCheck_new_block
obj:*
}

# rsvg_error_handle_close got fixed in
# - GNOME/librsvg@7bf1014
# (2018-11-12, first tags: v2.45.0, v2.44.9)
Expand Down
13 changes: 8 additions & 5 deletions docs/dunst.5.pod
Original file line number Diff line number Diff line change
Expand Up @@ -890,7 +890,8 @@ If B<icon_position> is set to off, this setting is ignored.

Updates the icon of the notification, it should be a path or a name for a valid
image. This overrides the icon that was sent with dunstify or another notification
tool.
tool. Expansion of the argument is carried out using wordexp(3)
with command substitution disabled.

=item C<icon_position> (values: [left/right/top/off], default: left)

Expand All @@ -901,7 +902,8 @@ disables icons.

Sets the default icon of the notification, it should be a path or a name for a
valid image. This does B<not> override the icon that was sent with dunstify or
another notification tool.
another notification tool. Expansion of the argument is carried out using
wordexp(3) with command substitution disabled.

=item C<set_stack_tag>

Expand Down Expand Up @@ -1066,9 +1068,10 @@ Note that some variables may be empty.
If the notification is suppressed, the script will not be run unless
B<always_run_script> is set to true.

If '~/' occurs at the beginning of the script parameter, it will get replaced by the
users' home directory. If the value is not an absolute path, the directories in the
PATH variable will be searched for an executable of the same name.
The script parameter is expanded according to wordexp(3) with command
substitution disabled. If the expanded value is not an absolute path, the
directories in the PATH variable will be searched for an executable of the same
name.

=head1 COLORS

Expand Down
35 changes: 27 additions & 8 deletions src/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include <wordexp.h>

#include "log.h"
#include "settings_data.h"
Expand Down Expand Up @@ -179,16 +180,34 @@ int string_array_length(char **s)
/* see utils.h */
char *string_to_path(char *string)
{

if (string && STRN_EQ(string, "~/", 2)) {
char *home = g_strconcat(user_get_home(), "/", NULL);

string = string_replace_at(string, 0, 2, home);

g_free(home);
ASSERT_OR_RET(string, string);

wordexp_t we;
switch (wordexp(string, &we, WRDE_NOCMD | WRDE_UNDEF)) {
case 0:
break;
case WRDE_BADCHAR:
LOG_W("Expansion of \"%s\" failed. It contains invalid characters.", string);
return string;
case WRDE_BADVAL:
LOG_W("Expansion of \"%s\" failed. It contains an undefined variable.", string);
return string;
case WRDE_CMDSUB:
LOG_W("Expansion of \"%s\" failed. The requested command substitution is currently not supported.", string);
return string;
case WRDE_NOSPACE:
LOG_W("Expansion of \"%s\" failed. We ran out of memory.", string);
return string;
case WRDE_SYNTAX:
LOG_W("Expansion of \"%s\" failed. It contains invalid syntax.", string);
return string;
}
g_free(string);

char *res = g_strjoinv(" ", we.we_wordv);
wordfree(&we);

return string;
return res;
}

/* see utils.h */
Expand Down
10 changes: 10 additions & 0 deletions test/option_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -521,16 +521,23 @@ TEST test_string_to_path(void)
"/path/p argument",
"p with multiple arguments",
"~/p/p",
"$HOME/p/p",
"$TEST_ENV/p/p",
};

setenv("TEST_ENV", "foobar", 1);

char *expanded_home = g_strconcat(user_get_home(), "/", "p/p", NULL);
char *expanded_env = g_strconcat("foobar", "/p/p", NULL);
const char* results[] = {
"/bin/something",
"something",
"/path/path/path/",
"/path/p argument",
"p with multiple arguments",
expanded_home,
expanded_home,
expanded_env,
};

const char* results2[][5] = {
Expand All @@ -540,6 +547,8 @@ TEST test_string_to_path(void)
{"/path/p", "argument", NULL},
{"p", "with", "multiple", "arguments", NULL},
{expanded_home},
{expanded_home},
{expanded_env},
};

ARRAY_SAME_LENGTH(inputs, results);
Expand All @@ -557,6 +566,7 @@ TEST test_string_to_path(void)
}

g_free(val);
g_free(expanded_env);
g_free(expanded_home);
g_strfreev(val2);
PASS();
Expand Down
15 changes: 15 additions & 0 deletions test/utils.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include <features.h>

#include "../src/utils.c"
#include "greatest.h"

Expand Down Expand Up @@ -152,6 +154,7 @@ TEST test_string_to_path(void)
ASSERT_STR_EQ(exp, (ptr = string_to_path(g_strdup(exp))));
free(ptr);

// This might fail, when a user named path exists on the host running the tests.
exp = "~path/with/wrong/tilde";
ASSERT_STR_EQ(exp, (ptr = string_to_path(g_strdup(exp))));
free(ptr);
Expand All @@ -166,6 +169,18 @@ TEST test_string_to_path(void)
free(exp);
free(ptr);

ASSERT_STR_EQ((exp = g_strconcat(home, "/.path/with/HOME environment variable", NULL)),
(ptr = string_to_path(g_strdup("$HOME/.path/with/HOME environment variable"))));
free(exp);
free(ptr);

// At least musl doesn't properly support wordexp.
#ifdef __GLIBC__
exp = "/some/$UNDEFINED/variable";
ASSERT_STR_EQ(exp, (ptr = string_to_path(g_strdup(exp))));
free(ptr);
#endif

PASS();
}

Expand Down

0 comments on commit 7ec7005

Please sign in to comment.