Commit 4ac3cc374f2fb7f4e561137f8c42a37996845618
1 parent
3707d37f
Add strlcpy if not available to enhance copy of device string
- check strlcpy in configure.ac - test for empty device string - test truncated device string
Showing
5 changed files
with
67 additions
and
7 deletions
configure.ac
| ... | ... | @@ -81,7 +81,6 @@ AC_CHECK_HEADERS([ \ |
| 81 | 81 | # Checks for header files. |
| 82 | 82 | AC_HEADER_STDC |
| 83 | 83 | |
| 84 | - | |
| 85 | 84 | # Checks for typedefs, structures, and compiler characteristics. |
| 86 | 85 | AC_C_CONST |
| 87 | 86 | AC_TYPE_SIZE_T |
| ... | ... | @@ -97,7 +96,7 @@ AC_CHECK_DECLS([__CYGWIN__]) |
| 97 | 96 | |
| 98 | 97 | # Checks for library functions. |
| 99 | 98 | AC_FUNC_FORK |
| 100 | -AC_CHECK_FUNCS([gettimeofday inet_ntoa memset select socket strerror]) | |
| 99 | +AC_CHECK_FUNCS([gettimeofday inet_ntoa memset select socket strerror strlcpy]) | |
| 101 | 100 | |
| 102 | 101 | AC_CONFIG_FILES([ |
| 103 | 102 | Makefile | ... | ... |
src/modbus-private.h
| ... | ... | @@ -109,6 +109,10 @@ struct _modbus { |
| 109 | 109 | void _modbus_init_common(modbus_t *ctx); |
| 110 | 110 | void _error_print(modbus_t *ctx, const char *context); |
| 111 | 111 | |
| 112 | +#ifndef HAVE_STRLCPY | |
| 113 | +size_t strlcpy(char *dest, const char *src, size_t dest_size); | |
| 114 | +#endif | |
| 115 | + | |
| 112 | 116 | MODBUS_END_DECLS |
| 113 | 117 | |
| 114 | 118 | #endif /* _MODBUS_PRIVATE_H_ */ | ... | ... |
src/modbus-rtu.c
| ... | ... | @@ -853,6 +853,8 @@ modbus_t* modbus_new_rtu(const char *device, |
| 853 | 853 | { |
| 854 | 854 | modbus_t *ctx; |
| 855 | 855 | modbus_rtu_t *ctx_rtu; |
| 856 | + size_t dest_size; | |
| 857 | + size_t src_size; | |
| 856 | 858 | |
| 857 | 859 | ctx = (modbus_t *) malloc(sizeof(modbus_t)); |
| 858 | 860 | _modbus_init_common(ctx); |
| ... | ... | @@ -860,11 +862,23 @@ modbus_t* modbus_new_rtu(const char *device, |
| 860 | 862 | ctx->backend = &_modbus_rtu_backend; |
| 861 | 863 | ctx->backend_data = (modbus_rtu_t *) malloc(sizeof(modbus_rtu_t)); |
| 862 | 864 | ctx_rtu = (modbus_rtu_t *)ctx->backend_data; |
| 863 | -#if defined(OpenBSD) | |
| 864 | - strlcpy(ctx_rtu->device, device, sizeof(ctx_rtu->device)); | |
| 865 | -#else | |
| 866 | - strcpy(ctx_rtu->device, device); | |
| 867 | -#endif | |
| 865 | + | |
| 866 | + dest_size = sizeof(ctx_rtu->device); | |
| 867 | + src_size = strlcpy(ctx_rtu->device, device, dest_size); | |
| 868 | + if (src_size == 0) { | |
| 869 | + modbus_free(ctx); | |
| 870 | + fprintf(stderr, "The device string is empty\n"); | |
| 871 | + errno = EINVAL; | |
| 872 | + return NULL; | |
| 873 | + } | |
| 874 | + | |
| 875 | + if (src_size >= dest_size) { | |
| 876 | + modbus_free(ctx); | |
| 877 | + fprintf(stderr, "The device string has been truncated\n"); | |
| 878 | + errno = EINVAL; | |
| 879 | + return NULL; | |
| 880 | + } | |
| 881 | + | |
| 868 | 882 | ctx_rtu->baud = baud; |
| 869 | 883 | if (parity == 'N' || parity == 'E' || parity == 'O') { |
| 870 | 884 | ctx_rtu->parity = parity; | ... | ... |
src/modbus.c
| ... | ... | @@ -1425,3 +1425,42 @@ int modbus_accept(modbus_t *ctx, int *socket) |
| 1425 | 1425 | { |
| 1426 | 1426 | return ctx->backend->accept(ctx, socket); |
| 1427 | 1427 | } |
| 1428 | + | |
| 1429 | +#ifndef HAVE_STRLCPY | |
| 1430 | +/* | |
| 1431 | +/* Function strlcpy was originally developed by | |
| 1432 | + * Todd C. Miller <Todd.Miller@courtesan.com> to simplify writing secure code. | |
| 1433 | + * See ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/strlcpy.3 | |
| 1434 | + * for more information. | |
| 1435 | + * | |
| 1436 | + * Thank you Ulrich Drepper... not! | |
| 1437 | + * | |
| 1438 | + * Copy src to string dest of size dest_size. At most dest_size-1 characters | |
| 1439 | + * will be copied. Always NUL terminates (unless dest_size == 0). Returns | |
| 1440 | + * strlen(src); if retval >= dest_size, truncation occurred. | |
| 1441 | + */ | |
| 1442 | +size_t strlcpy(char *dest, const char *src, size_t dest_size) | |
| 1443 | +{ | |
| 1444 | + register char *d = dest; | |
| 1445 | + register const char *s = src; | |
| 1446 | + register size_t n = dest_size; | |
| 1447 | + | |
| 1448 | + /* Copy as many bytes as will fit */ | |
| 1449 | + if (n != 0 && --n != 0) { | |
| 1450 | + do { | |
| 1451 | + if ((*d++ = *s++) == 0) | |
| 1452 | + break; | |
| 1453 | + } while (--n != 0); | |
| 1454 | + } | |
| 1455 | + | |
| 1456 | + /* Not enough room in dest, add NUL and traverse rest of src */ | |
| 1457 | + if (n == 0) { | |
| 1458 | + if (dest_size != 0) | |
| 1459 | + *d = '\0'; /* NUL-terminate dest */ | |
| 1460 | + while (*s++) | |
| 1461 | + ; | |
| 1462 | + } | |
| 1463 | + | |
| 1464 | + return (s - src - 1); /* count does not include NUL */ | |
| 1465 | +} | |
| 1466 | +#endif | ... | ... |
tests/unit-test-client.c
| ... | ... | @@ -48,6 +48,10 @@ int main(void) |
| 48 | 48 | |
| 49 | 49 | /* TCP */ |
| 50 | 50 | ctx = modbus_new_tcp("127.0.0.1", 1502); |
| 51 | + if (ctx == NULL) { | |
| 52 | + fprintf(stderr, "Unable to initialize TCP Modbus\n"); | |
| 53 | + return -1; | |
| 54 | + } | |
| 51 | 55 | modbus_set_debug(ctx, TRUE); |
| 52 | 56 | |
| 53 | 57 | if (modbus_connect(ctx) == -1) { | ... | ... |