* [PATCH] getcwd: Set errno to EINVAL when size == 0 @ 2013-10-07 6:08 Michael Forney 2013-10-07 6:38 ` Jens Gustedt 0 siblings, 1 reply; 7+ messages in thread From: Michael Forney @ 2013-10-07 6:08 UTC (permalink / raw) To: musl According to POSIX, The getcwd() function shall fail if: [EINVAL] The size argument is 0. [ERANGE] The size argument is greater than 0, but is smaller than the length of the string +1. --- src/unistd/getcwd.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/unistd/getcwd.c b/src/unistd/getcwd.c index 2e540cd..0238fa7 100644 --- a/src/unistd/getcwd.c +++ b/src/unistd/getcwd.c @@ -8,6 +8,10 @@ char *getcwd(char *buf, size_t size) { char tmp[PATH_MAX]; if (!buf) buf = tmp, size = PATH_MAX; + else if (size == 0) { + errno = EINVAL; + return 0; + } if (syscall(SYS_getcwd, buf, size) < 0) return 0; return buf == tmp ? strdup(buf) : buf; } -- 1.8.4 ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] getcwd: Set errno to EINVAL when size == 0 2013-10-07 6:08 [PATCH] getcwd: Set errno to EINVAL when size == 0 Michael Forney @ 2013-10-07 6:38 ` Jens Gustedt 2013-10-07 16:21 ` Rich Felker 0 siblings, 1 reply; 7+ messages in thread From: Jens Gustedt @ 2013-10-07 6:38 UTC (permalink / raw) To: musl [-- Attachment #1: Type: text/plain, Size: 1591 bytes --] Hello, Am Sonntag, den 06.10.2013, 23:08 -0700 schrieb Michael Forney: > According to POSIX, > > The getcwd() function shall fail if: > > [EINVAL] > The size argument is 0. > [ERANGE] > The size argument is greater than 0, but is smaller than the length > of the string +1. > --- > src/unistd/getcwd.c | 4 ++++ > 1 file changed, 4 insertions(+) > > diff --git a/src/unistd/getcwd.c b/src/unistd/getcwd.c > index 2e540cd..0238fa7 100644 > --- a/src/unistd/getcwd.c > +++ b/src/unistd/getcwd.c > @@ -8,6 +8,10 @@ char *getcwd(char *buf, size_t size) > { > char tmp[PATH_MAX]; > if (!buf) buf = tmp, size = PATH_MAX; > + else if (size == 0) { > + errno = EINVAL; > + return 0; > + } > if (syscall(SYS_getcwd, buf, size) < 0) return 0; Is the new error check really necessary? I would have expected the error path to have triggered before when buf is !0 and size is 0 on entry. > return buf == tmp ? strdup(buf) : buf; This in turn doesn't seem to be consistent with the extension that glibc offers. It says > In this case, the allocated buffer has the length size So I would think that strdup(buf) should be replaced by something like strcpy(malloc(size), buf) Jens -- :: INRIA Nancy Grand Est :: http://www.loria.fr/~gustedt/ :: :: AlGorille ::::::::::::::: office Nancy : +33 383593090 :: :: ICube :::::::::::::: office Strasbourg : +33 368854536 :: :: ::::::::::::::::::::::::::: gsm France : +33 651400183 :: :: :::::::::::::::::::: gsm international : +49 15737185122 :: [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] getcwd: Set errno to EINVAL when size == 0 2013-10-07 6:38 ` Jens Gustedt @ 2013-10-07 16:21 ` Rich Felker 2013-10-07 17:15 ` Justin Cormack 2013-10-07 23:29 ` Michael Forney 0 siblings, 2 replies; 7+ messages in thread From: Rich Felker @ 2013-10-07 16:21 UTC (permalink / raw) To: musl On Mon, Oct 07, 2013 at 08:38:14AM +0200, Jens Gustedt wrote: > Hello, > > Am Sonntag, den 06.10.2013, 23:08 -0700 schrieb Michael Forney: > > According to POSIX, > > > > The getcwd() function shall fail if: > > > > [EINVAL] > > The size argument is 0. > > [ERANGE] > > The size argument is greater than 0, but is smaller than the length > > of the string +1. > > --- > > src/unistd/getcwd.c | 4 ++++ > > 1 file changed, 4 insertions(+) > > > > diff --git a/src/unistd/getcwd.c b/src/unistd/getcwd.c > > index 2e540cd..0238fa7 100644 > > --- a/src/unistd/getcwd.c > > +++ b/src/unistd/getcwd.c > > @@ -8,6 +8,10 @@ char *getcwd(char *buf, size_t size) > > { > > char tmp[PATH_MAX]; > > if (!buf) buf = tmp, size = PATH_MAX; > > + else if (size == 0) { > > + errno = EINVAL; > > + return 0; > > + } > > if (syscall(SYS_getcwd, buf, size) < 0) return 0; > > Is the new error check really necessary? I would have expected the > error path to have triggered before when buf is !0 and size is 0 on > entry. In principle the kernel should be generating the EINVAL if size is 0, but maybe it does the wrong thing...? > > return buf == tmp ? strdup(buf) : buf; > > This in turn doesn't seem to be consistent with the extension that > glibc offers. It says > > > In this case, the allocated buffer has the length size You omitted the rest of that sentence: "unless size is zero, when buf is allocated as big as necessary." > So I would think that strdup(buf) should be replaced by something like > > strcpy(malloc(size), buf) This is definitely unsafe if size is less than strnel(buf)+1. I'm not convinced this aspect of the glibc behavior (using the size argument) is beneficial; the only possible case in which it would be benficial is when the caller wants the returned buffer to have space for appending a filename, which could be achieved by passing PATH_MAX. However, I thought the whole point of having getcwd accept a NULL argument was for the GNU HURD "no PATH_MAX limit" model, in which case you wouldn't even know the right length to pass in order to have space left over to append a filename. If it is deemed important to support this weird GNU behavior, I think it would be beneficial to always allocate MAX(strlen(buf)+1,size) rather than just size, to avoid spurious failure. Opinions from anyone else? Rich ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] getcwd: Set errno to EINVAL when size == 0 2013-10-07 16:21 ` Rich Felker @ 2013-10-07 17:15 ` Justin Cormack 2013-10-07 17:25 ` Rich Felker 2013-10-07 23:29 ` Michael Forney 1 sibling, 1 reply; 7+ messages in thread From: Justin Cormack @ 2013-10-07 17:15 UTC (permalink / raw) To: musl On Mon, Oct 7, 2013 at 5:21 PM, Rich Felker <dalias@aerifal.cx> wrote: > On Mon, Oct 07, 2013 at 08:38:14AM +0200, Jens Gustedt wrote: >> Hello, >> >> Am Sonntag, den 06.10.2013, 23:08 -0700 schrieb Michael Forney: >> > According to POSIX, >> > >> > The getcwd() function shall fail if: >> > >> > [EINVAL] >> > The size argument is 0. >> > [ERANGE] >> > The size argument is greater than 0, but is smaller than the length >> > of the string +1. >> > --- >> > src/unistd/getcwd.c | 4 ++++ >> > 1 file changed, 4 insertions(+) >> > >> > diff --git a/src/unistd/getcwd.c b/src/unistd/getcwd.c >> > index 2e540cd..0238fa7 100644 >> > --- a/src/unistd/getcwd.c >> > +++ b/src/unistd/getcwd.c >> > @@ -8,6 +8,10 @@ char *getcwd(char *buf, size_t size) >> > { >> > char tmp[PATH_MAX]; >> > if (!buf) buf = tmp, size = PATH_MAX; >> > + else if (size == 0) { >> > + errno = EINVAL; >> > + return 0; >> > + } >> > if (syscall(SYS_getcwd, buf, size) < 0) return 0; >> >> Is the new error check really necessary? I would have expected the >> error path to have triggered before when buf is !0 and size is 0 on >> entry. > > In principle the kernel should be generating the EINVAL if size is 0, > but maybe it does the wrong thing...? > >> > return buf == tmp ? strdup(buf) : buf; >> >> This in turn doesn't seem to be consistent with the extension that >> glibc offers. It says >> >> > In this case, the allocated buffer has the length size > > You omitted the rest of that sentence: "unless size is zero, when buf > is allocated as big as necessary." > >> So I would think that strdup(buf) should be replaced by something like >> >> strcpy(malloc(size), buf) > > This is definitely unsafe if size is less than strnel(buf)+1. I'm not > convinced this aspect of the glibc behavior (using the size argument) > is beneficial; the only possible case in which it would be benficial > is when the caller wants the returned buffer to have space for > appending a filename, which could be achieved by passing PATH_MAX. > However, I thought the whole point of having getcwd accept a NULL > argument was for the GNU HURD "no PATH_MAX limit" model, in which case > you wouldn't even know the right length to pass in order to have space > left over to append a filename. > > If it is deemed important to support this weird GNU behavior, I think > it would be beneficial to always allocate MAX(strlen(buf)+1,size) > rather than just size, to avoid spurious failure. > > Opinions from anyone else? I can't see any way in which the user could detect (in the malloc case) that you always allocated PATH_MAX not the provided size, so you may as well just do that if they insist on using this stupid interface in the first place. Justin ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] getcwd: Set errno to EINVAL when size == 0 2013-10-07 17:15 ` Justin Cormack @ 2013-10-07 17:25 ` Rich Felker 0 siblings, 0 replies; 7+ messages in thread From: Rich Felker @ 2013-10-07 17:25 UTC (permalink / raw) To: musl On Mon, Oct 07, 2013 at 06:15:24PM +0100, Justin Cormack wrote: > > If it is deemed important to support this weird GNU behavior, I think > > it would be beneficial to always allocate MAX(strlen(buf)+1,size) > > rather than just size, to avoid spurious failure. > > > > Opinions from anyone else? > > I can't see any way in which the user could detect (in the malloc > case) that you always allocated PATH_MAX not the provided size, so you > may as well just do that if they insist on using this stupid interface > in the first place. Well if the caller requested a size of 2*PATH_MAX and you only allocated PATH_MAX, this could result in the program invoking UB at a later time by trying to use the additional space (for whatever purpose). And conversely, the application _could_ detect allocation of too much space, if it expected the call to fail with an error but instead the call succeeded, or if it simply expected that, on successful return, strlen(getcwd(0, size))<size is true. Rich ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] getcwd: Set errno to EINVAL when size == 0 2013-10-07 16:21 ` Rich Felker 2013-10-07 17:15 ` Justin Cormack @ 2013-10-07 23:29 ` Michael Forney 2013-10-08 23:48 ` Rich Felker 1 sibling, 1 reply; 7+ messages in thread From: Michael Forney @ 2013-10-07 23:29 UTC (permalink / raw) To: musl On Mon, 07 Oct 2013 12:21:57 -0400, Rich Felker <dalias@aerifal.cx> wrote: > In principle the kernel should be generating the EINVAL if size is 0, > but maybe it does the wrong thing...? Yeah, from what I could tell, it returns ERANGE in all cases where it can't fit the cwd into the buffer. -- Michael Forney <mforney@mforney.org> ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] getcwd: Set errno to EINVAL when size == 0 2013-10-07 23:29 ` Michael Forney @ 2013-10-08 23:48 ` Rich Felker 0 siblings, 0 replies; 7+ messages in thread From: Rich Felker @ 2013-10-08 23:48 UTC (permalink / raw) To: musl On Mon, Oct 07, 2013 at 04:29:53PM -0700, Michael Forney wrote: > On Mon, 07 Oct 2013 12:21:57 -0400, Rich Felker <dalias@aerifal.cx> wrote: > > In principle the kernel should be generating the EINVAL if size is 0, > > but maybe it does the wrong thing...? > > Yeah, from what I could tell, it returns ERANGE in all cases where it > can't fit the cwd into the buffer. OK, I think that clears it up then. For now I'll apply your patch (and at the same time, replace the if branch with a proper block instead of the ugly comma operator hack) and we can worry about the glibc issue later. Rich ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2013-10-08 23:48 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2013-10-07 6:08 [PATCH] getcwd: Set errno to EINVAL when size == 0 Michael Forney 2013-10-07 6:38 ` Jens Gustedt 2013-10-07 16:21 ` Rich Felker 2013-10-07 17:15 ` Justin Cormack 2013-10-07 17:25 ` Rich Felker 2013-10-07 23:29 ` Michael Forney 2013-10-08 23:48 ` Rich Felker
Code repositories for project(s) associated with this public inbox https://git.vuxu.org/mirror/musl/ This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).