Skip to content

Fix segfault in NUT clients with empty host/device name components #2053

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Sep 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions NEWS.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ as part of https://github.com/networkupstools/nut/issues/1410 solution.
seems to have confused the MGE SHUT (Serial HID UPS Transfer) driver
support [#2022]

- An issue was identified which could cause `libupsclient` parser of device
and host names to crash upon bad inputs (e.g. poorly resolved environment
variables in scripts). Now it should fail more gracefully [#2052]

- New `configure --enable-inplace-runtime` option should set default values
for `--sysconfdir`, `--with-user` and `--with-group` options to match an
existing NUT deployment -- for users who are trying if a custom build
Expand Down
41 changes: 32 additions & 9 deletions clients/upsclient.c
Original file line number Diff line number Diff line change
Expand Up @@ -1161,7 +1161,7 @@ int upscli_tryconnect(UPSCONN_t *ups, const char *host, uint16_t port, int flags

pconf_init(&ups->pc_ctx, NULL);

ups->host = strdup(host);
ups->host = xstrdup(host);

if (!ups->host) {
ups->upserror = UPSCLI_ERR_NOMEM;
Expand Down Expand Up @@ -1618,22 +1618,45 @@ int upscli_splitname(const char *buf, char **upsname, char **hostname, uint16_t

s = strchr(tmp, '@');

if ((*upsname = strdup(strtok_r(tmp, "@", &last))) == NULL) {
fprintf(stderr, "upscli_splitname: strdup failed\n");
/* someone passed a "@hostname" string? */
if (s == tmp) {
fprintf(stderr, "upscli_splitname: got empty upsname string\n");
return -1;
}

if ((*upsname = xstrdup(strtok_r(tmp, "@", &last))) == NULL) {
fprintf(stderr, "upscli_splitname: xstrdup failed\n");
return -1;
}

/* someone passed a "@hostname" string (take two)? */
if (!**upsname) {
fprintf(stderr, "upscli_splitname: got empty upsname string\n");
return -1;
}

/*
fprintf(stderr, "upscli_splitname3: got buf='%s', tmp='%s', upsname='%s', possible hostname:port='%s'\n",
NUT_STRARG(buf), NUT_STRARG(tmp), NUT_STRARG(*upsname), NUT_STRARG((s ? s+1 : s)));
*/

/* only a upsname is specified, fill in defaults */
if (s == NULL) {
if ((*hostname = strdup("localhost")) == NULL) {
fprintf(stderr, "upscli_splitname: strdup failed\n");
if ((*hostname = xstrdup("localhost")) == NULL) {
fprintf(stderr, "upscli_splitname: xstrdup failed\n");
return -1;
}

*port = PORT;
return 0;
}

/* someone passed a "upsname@" string? */
if (!(*(s+1))) {
fprintf(stderr, "upscli_splitname: got the @ separator and then an empty hostname[:port] string\n");
return -1;
}

return upscli_splitaddr(s+1, hostname, port);
}

Expand All @@ -1659,8 +1682,8 @@ int upscli_splitaddr(const char *buf, char **hostname, uint16_t *port)
return -1;
}

if ((*hostname = strdup(strtok_r(tmp+1, "]", &last))) == NULL) {
fprintf(stderr, "upscli_splitaddr: strdup failed\n");
if ((*hostname = xstrdup(strtok_r(tmp+1, "]", &last))) == NULL) {
fprintf(stderr, "upscli_splitaddr: xstrdup failed\n");
return -1;
}

Expand All @@ -1672,8 +1695,8 @@ int upscli_splitaddr(const char *buf, char **hostname, uint16_t *port)
} else {
s = strchr(tmp, ':');

if ((*hostname = strdup(strtok_r(tmp, ":", &last))) == NULL) {
fprintf(stderr, "upscli_splitaddr: strdup failed\n");
if ((*hostname = xstrdup(strtok_r(tmp, ":", &last))) == NULL) {
fprintf(stderr, "upscli_splitaddr: xstrdup failed\n");
return -1;
}

Expand Down
9 changes: 8 additions & 1 deletion common/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -1738,7 +1738,14 @@ void *xrealloc(void *ptr, size_t size)

char *xstrdup(const char *string)
{
char *p = strdup(string);
char *p;

if (string == NULL) {
upsdebugx(1, "%s: got null input", __func__);
return NULL;
}

p = strdup(string);

if (p == NULL)
fatal_with_errno(EXIT_FAILURE, "%s", oom_msg);
Expand Down