|
Message-ID: <20240811025424.GJ10433@brightrain.aerifal.cx> Date: Sat, 10 Aug 2024 22:54:24 -0400 From: Rich Felker <dalias@...c.org> To: contact@...ktivis.me Cc: musl@...ts.openwall.com Subject: Re: [PATCH v3 3/3] signal: add str2sig(3) from POSIX.1-2024 On Sat, Aug 10, 2024 at 08:43:15PM -0400, Rich Felker wrote: > A few things I didn't catch before: > > On Fri, Aug 09, 2024 at 05:34:23PM +0200, contact@...ktivis.me wrote: > > From: "Haelwenn (lanodan) Monnier" <contact@...ktivis.me> > > > > --- > > include/signal.h | 1 + > > src/signal/str2sig.c | 54 ++++++++++++++++++++++++++++++++++++++++++++ > > 2 files changed, 55 insertions(+) > > create mode 100644 src/signal/str2sig.c > > > > diff --git a/include/signal.h b/include/signal.h > > index 94ac29b1..5451424d 100644 > > --- a/include/signal.h > > +++ b/include/signal.h > > @@ -237,6 +237,7 @@ void psignal(int, const char *); > > // Bumped to 13 to be safe if a case like "SIGRTMIN+nnn" happens > > #define SIG2STR_MAX 13 > > int sig2str(int signum, char *str); > > +int str2sig(const char *__restrict str, int *__restrict pnum); > > As a matter of conformance, declarations in public headers can't have > non-reserved identifiers like str or pnum in them (these might already > have been #defined'd by the application). As a matter of policy, we > just don't use argument names or other "creative" content (including > comments) in the public headers at all, mainly because the headers > have been intended to be statements of fact not subject to copyright > (so a dynamic program using them is not a derived work and doesn't > rely on license at all). > > (There might be a few places where that's not entirely followed, but > if so they should be fixed.) > > > #endif > > > > diff --git a/src/signal/str2sig.c b/src/signal/str2sig.c > > new file mode 100644 > > index 00000000..e4c17c57 > > --- /dev/null > > +++ b/src/signal/str2sig.c > > @@ -0,0 +1,54 @@ > > +#include <signal.h> > > +#include <string.h> > > +#include <errno.h> > > +#include <stdlib.h> > > +#include <ctype.h> > > + > > +int str2sig(const char *restrict str, int *restrict pnum) > > +{ > > + if (str[0] == '\0') return -1; > > + > > + errno = 0; > > + long signum = strtol(str, NULL, 10); > > + if (errno == 0 && signum < _NSIG) return (*pnum = signum, 0); > > I don't think the errno check is either necessary or sufficient. As > written, this code won't reject something like "12x". Generally, you > need to pass a pend argument, like: > > char *end; > long signum = strtol(str, &end, 10); > if (!*end && signum < _NSIG) ... > > which checks that the whole input was consumed, and thereby also that > there was no error except possible range overflow (which would be > caught by range checks). > > However there's also a missing range check for negative values. This > could probably be handled by use of an unsigned type here, but unless > the intent is to accept inputs starting with + or -, the entire strtol > path should probably only be attempted if (isdigit(str[0])), in which > case negative can't happen. > > > + if (strnlen(str, sizeof *__sys_signame) <= sizeof *__sys_signame) > > + for (int i = 0; i < sizeof __sys_signame/sizeof *__sys_signame; i++) > > + if (strncmp(str, __sys_signame[i], sizeof *__sys_signame) == 0) > > + return (*pnum = i, 0); > > I think the indexing for __sys_signame could be adjusted by 1 so > there's not an unused slot 0. The entries could also be 6-byte rather > than 7-byte. > > > + // signal aliases > > + if (strcmp(str, "IOT") == 0) > > + return (*pnum = SIGIOT, 0); > > + if (strcmp(str, "UNUSED") == 0) > > + return (*pnum = SIGUNUSED, 0); > > +#if SIGPOLL == SIGIO > > + if (strcmp(str, "POLL") == 0) > > + return (*pnum = SIGPOLL, 0); > > +#endif > > + > > + if (strcmp(str, "RTMIN") == 0) > > + return (*pnum = SIGRTMIN, 0); > > + if (strcmp(str, "RTMAX") == 0) > > + return (*pnum = SIGRTMAX, 0); > > + > > + if (strncmp(str, "RTMIN+", 6) == 0 || strncmp(str, "RTMAX-", 6) == 0) > > + { > > + if(!isdigit(str[6])) return -1; > > + > > + int sigrt = str[6]-'0'; > > + > > + if(str[7] != '\0') > > + { > > + if(!isdigit(str[7])) return -1; > > + > > + sigrt *= 10; > > + sigrt += str[7]-'0'; > > + } > > At this point you're missing a check that there's not further junk (or > more digits) after the second one. It could be something like: > > + if(!isdigit(str[7]) || str[8]) return -1; > > This isn't highly important, but the style str[8] vs str[8]!='\0' is > generally preferred in musl. OK, I've finally gone and dug up and read the specification: https://pubs.opengroup.org/onlinepubs/9799919799/functions/sig2str.html and it requires: "If str points to a string of the form "RTMIN+n", where n is a decimal representation of a number between 1 and SIGRTMAX-SIGRTMIN-1 inclusive, the stored value shall be equal to SIGRTMIN+n. "If str points to a string of the form "RTMAX-n", where n is a decimal representation of a number between 1 and SIGRTMAX-SIGRTMIN-1 inclusive, the stored value shall be equal to SIGRTMAX-n." So there is no requirement that the decimal number be in shortest form. As such this needs a loop or strtol (after checking isdigit). Rich
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.