Skip to content

Commit 46f64c3

Browse files
authored
Merge pull request #2123 from EchterAgo/apc_modbus_fix_string_ops
apc_modbus: Use snprintf instead of strncpy
2 parents 94139cb + 0f675b4 commit 46f64c3

File tree

1 file changed

+50
-17
lines changed

1 file changed

+50
-17
lines changed

drivers/apc_modbus.c

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ static int _apc_modbus_double_to_nut(const apc_modbus_value_t *value, char *outp
271271
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
272272
#pragma GCC diagnostic pop
273273
#endif
274-
if (res < 0 || (size_t)res > output_len) {
274+
if (res < 0 || (size_t)res >= output_len) {
275275
return 0;
276276
}
277277

@@ -314,7 +314,7 @@ static int _apc_modbus_power_to_nut(const apc_modbus_value_t *value, char *outpu
314314
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_FORMAT_NONLITERAL
315315
#pragma GCC diagnostic pop
316316
#endif
317-
if (res < 0 || (size_t)res > output_len) {
317+
if (res < 0 || (size_t)res >= output_len) {
318318
return 0;
319319
}
320320

@@ -325,6 +325,8 @@ static apc_modbus_converter_t _apc_modbus_power_conversion = { _apc_modbus_power
325325

326326
static int _apc_modbus_voltage_to_nut(const apc_modbus_value_t *value, char *output, size_t output_len)
327327
{
328+
int res;
329+
328330
if (value == NULL || output == NULL || output_len == 0) {
329331
/* Invalid parameters */
330332
return 0;
@@ -336,7 +338,10 @@ static int _apc_modbus_voltage_to_nut(const apc_modbus_value_t *value, char *out
336338

337339
if (value->data.uint_value == 0xffff) {
338340
/* Not applicable */
339-
strncpy(output, "NA", output_len);
341+
res = snprintf(output, output_len, "NA");
342+
if (res < 0 || (size_t)res >= output_len) {
343+
return 0;
344+
}
340345
return 1;
341346
}
342347

@@ -348,6 +353,7 @@ static apc_modbus_converter_t _apc_modbus_voltage_conversion = { _apc_modbus_vol
348353
static int _apc_modbus_efficiency_to_nut(const apc_modbus_value_t *value, char *output, size_t output_len)
349354
{
350355
char *cause;
356+
int res;
351357

352358
if (value == NULL || output == NULL || output_len == 0) {
353359
/* Invalid parameters */
@@ -387,7 +393,10 @@ static int _apc_modbus_efficiency_to_nut(const apc_modbus_value_t *value, char *
387393
return _apc_modbus_double_to_nut(value, output, output_len);
388394
}
389395

390-
strncpy(output, cause, output_len);
396+
res = snprintf(output, output_len, "%s", cause);
397+
if (res < 0 || (size_t)res >= output_len) {
398+
return 0;
399+
}
391400

392401
return 1;
393402
}
@@ -397,6 +406,7 @@ static apc_modbus_converter_t _apc_modbus_efficiency_conversion = { _apc_modbus_
397406
static int _apc_modbus_status_change_cause_to_nut(const apc_modbus_value_t *value, char *output, size_t output_len)
398407
{
399408
char *cause;
409+
int res;
400410

401411
if (value == NULL || output == NULL || output_len == 0) {
402412
/* Invalid parameters */
@@ -506,7 +516,10 @@ static int _apc_modbus_status_change_cause_to_nut(const apc_modbus_value_t *valu
506516
break;
507517
}
508518

509-
strncpy(output, cause, output_len);
519+
res = snprintf(output, output_len, "%s", cause);
520+
if (res < 0 || (size_t)res >= output_len) {
521+
return 0;
522+
}
510523

511524
return 1;
512525
}
@@ -1014,6 +1027,7 @@ static void _apc_modbus_usb_lib_to_nut(const modbus_usb_device_t *device, USBDev
10141027
/* This makes a USBDevice_t from modbus_usb_device_t so we can use our matchers */
10151028

10161029
static char bus_buf[4], device_buf[4], bus_port_buf[4];
1030+
int res;
10171031

10181032
assert(device != NULL);
10191033
assert(out != NULL);
@@ -1027,14 +1041,23 @@ static void _apc_modbus_usb_lib_to_nut(const modbus_usb_device_t *device, USBDev
10271041
out->Serial = device->serial_str;
10281042
out->bcdDevice = device->bcd_device;
10291043

1030-
snprintf(bus_buf, sizeof(bus_buf), "%03u", device->bus);
1044+
res = snprintf(bus_buf, sizeof(bus_buf), "%03u", device->bus);
1045+
if (res < 0 || (size_t)res >= sizeof(bus_buf)) {
1046+
fatalx(EXIT_FAILURE, "failed to convert USB bus to string");
1047+
}
10311048
out->Bus = bus_buf;
10321049

1033-
snprintf(device_buf, sizeof(device_buf), "%03u", device->device_address);
1050+
res = snprintf(device_buf, sizeof(device_buf), "%03u", device->device_address);
1051+
if (res < 0 || (size_t)res >= sizeof(device_buf)) {
1052+
fatalx(EXIT_FAILURE, "failed to convert USB device address to string");
1053+
}
10341054
out->Device = device_buf;
10351055

10361056
#if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT)
1037-
snprintf(bus_port_buf, sizeof(bus_port_buf), "%03u", device->bus_port);
1057+
res = snprintf(bus_port_buf, sizeof(bus_port_buf), "%03u", device->bus_port);
1058+
if (res < 0 || (size_t)res >= sizeof(bus_port_buf)) {
1059+
fatalx(EXIT_FAILURE, "failed to convert USB bus port to string");
1060+
}
10381061
out->BusPort = bus_port_buf;
10391062
#endif
10401063
}
@@ -1118,7 +1141,7 @@ static int _apc_modbus_usb_callback(const modbus_usb_device_t *device)
11181141
static int _apc_modbus_parse_host_port(const char *input, char *host, size_t host_buf_size, char *port, size_t port_buf_size, const uint16_t default_port) {
11191142
const char *start = input;
11201143
const char *end = input;
1121-
int port_int;
1144+
int port_int, r;
11221145
size_t host_size, port_size;
11231146

11241147
if (*start == '[') {
@@ -1134,21 +1157,30 @@ static int _apc_modbus_parse_host_port(const char *input, char *host, size_t hos
11341157

11351158
if (!end) {
11361159
/* Port is missing, use the default port */
1137-
strncpy(host, start, host_buf_size);
1138-
snprintf(port, port_buf_size, "%u", default_port);
1139-
return 0;
1160+
r = snprintf(host, host_buf_size, "%s", start);
1161+
if (r < 0 || (size_t)r >= host_buf_size) {
1162+
upslogx(LOG_ERR, "%s: Buffer size too small or encoding error", __func__);
1163+
return 0;
1164+
}
1165+
r = snprintf(port, port_buf_size, "%u", default_port);
1166+
if (r < 0 || (size_t)r >= port_buf_size) {
1167+
upslogx(LOG_ERR, "%s: Buffer size too small or encoding error", __func__);
1168+
return 0;
1169+
}
1170+
return 1;
11401171
}
11411172

1142-
host_size = (size_t)(end - start);
1143-
port_size = strlen(end + 1);
1173+
/* +1 for zero termination */
1174+
host_size = (size_t)(end - start) + 1;
1175+
port_size = strlen(end + 1) + 1;
11441176

1145-
if (host_size >= host_buf_size || port_size >= port_buf_size) {
1177+
if (host_size > host_buf_size || port_size > port_buf_size) {
11461178
upslogx(LOG_ERR, "%s: Buffer size too small", __func__);
11471179
return 0;
11481180
}
11491181

1150-
strncpy(host, start, host_size);
1151-
strncpy(port, end + 1, port_size);
1182+
snprintf(host, host_size, "%s", start);
1183+
snprintf(port, port_size, "%s", end + 1);
11521184

11531185
port_int = atoi(port);
11541186
if (port_int < 0 || port_int > 65535) {
@@ -1221,6 +1253,7 @@ void upsdrv_initups(void)
12211253
for (i = 0; i < sizeof(regex_array) / sizeof(regex_array[0]); i++) {
12221254
if (regex_array[i] != NULL) {
12231255
has_nonzero_regex = 1;
1256+
break;
12241257
}
12251258
}
12261259

0 commit comments

Comments
 (0)