diff options
authorRich Felker <>2013-04-20 11:51:58 -0400
committerRich Felker <>2013-04-20 11:51:58 -0400
commit8c203eae1e90f646a3c7c40d9700d55de2163df1 (patch)
parent7bec92e793d4b8a349796848cf43c7329b0f2ed0 (diff)
make dynamic linker accept : or \n as path separator
this allows /etc/ld-musl-$(ARCH).path to contain one path per line, which is much more convenient for users than the :-delimited format, which was a source of repeated and unnecessary confusion. for simplicity, \n is also accepted in environment variables, though it should probably not be used there. at the same time, issues with overly long paths invoking UB or getting truncated have been fixed. such issues should not have arisen with the environment (which is size-limited) but could have been generated by a path file larger than 2**31 bytes in length.
1 files changed, 8 insertions, 8 deletions
diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c
index efbec8fb..dec95111 100644
--- a/src/ldso/dynlink.c
+++ b/src/ldso/dynlink.c
@@ -403,16 +403,16 @@ error:
return 0;
-static int path_open(const char *name, const char *search, char *buf, size_t buf_size)
+static int path_open(const char *name, const char *s, char *buf, size_t buf_size)
- const char *s=search, *z;
- int l, fd;
+ size_t l;
+ int fd;
for (;;) {
- while (*s==':') s++;
- if (!*s) return -1;
- z = strchr(s, ':');
- l = z ? z-s : strlen(s);
- snprintf(buf, buf_size, "%.*s/%s", l, s, name);
+ s += strspn(s, ":\n");
+ l = strcspn(s, ":\n");
+ if (l-1 >= INT_MAX) return -1;
+ if (snprintf(buf, buf_size, "%.*s/%s", (int)l, s, name) >= buf_size)
+ continue;
if ((fd = open(buf, O_RDONLY|O_CLOEXEC))>=0) return fd;
s += l;