From d7d471b7c7d628a28221a71f09ef505fdc48bf44 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 22 Jul 2024 19:47:25 +0200 Subject: [PATCH] server/netget.c: sanity-check NUMBER values that they actually resolve as float or long int [#266] If we assume a value without flags is by default a NUMBER but is not, re-default it to STRING. If it is also flagged explicitly as a NUMBER but is not, yell a warning for upstream to fix the code. Eventually this should be a reason to report protocol error, but not now. Signed-off-by: Jim Klimov --- server/netget.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/server/netget.c b/server/netget.c index 5ff11d8b0b..6110233a3b 100644 --- a/server/netget.c +++ b/server/netget.c @@ -24,6 +24,7 @@ #include "state.h" #include "desc.h" #include "neterr.h" +#include "nut_stdint.h" #include "netget.h" @@ -175,6 +176,55 @@ static void get_type(nut_ctype_t *client, const char *upsname, const char *var) __func__, upsname, var); } + /* Sanity-check current contents */ + if (node->val && *(node->val)) { + char *s; + float f; + long l; + int i, ok = 1; + size_t len = strlen(node->val); + + errno = 0; + i = sscanf(node->val, "%f", &f); + if (i < 1 || (uintmax_t)i > (uintmax_t)(len + 1) || errno || *(s = node->val + i) != '\0') { + upsdebugx(3, "%s: UPS[%s] variable %s is a NUMBER but not a float: %s", + __func__, upsname, var, node->val); + ok = 0; + } + + if (!ok) { + /* did not parse as a float... range issues or NaN? */ + errno = 0; + ok = 1; + i = sscanf(node->val, "%ld", &l); + if (i < 1 || (uintmax_t)i > (uintmax_t)(len + 1) || errno || *(s = node->val + i) != '\0') { + upsdebugx(3, "%s: UPS[%s] variable %s is a NUMBER but not a long int: %s", + __func__, upsname, var, node->val); + ok = 0; + } + } + + if (!ok && !(node->flags & ST_FLAG_NUMBER)) { + upsdebugx(3, "%s: assuming UPS[%s] variable %s is a STRING after all, by contents; " + "value='%s' len='%" PRIuSIZE "' aux='%ld'", + __func__, upsname, var, node->val, len, node->aux); + + sendback(client, "%s STRING:%ld\n", buf, node->aux); + return; + } + + if (!ok) { + /* FIXME: Should this return an error? + * Value was explicitly flagged as a NUMBER but is not by content. + * Note that state_addinfo() does not sanity-check; but + * netset.c::set_var() does though (for protocol clients). + */ + upslogx(LOG_WARNING, "%s: UPS[%s] variable %s is flagged as a NUMBER but is not " + "by contents (please report as a bug to NUT project)): %s", + __func__, upsname, var, node->val); + } + } + sendback(client, "%s NUMBER\n", buf); }