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,7 +81,6 @@ AC_CHECK_HEADERS([ \ | ||
| 81 | # Checks for header files. | 81 | # Checks for header files. |
| 82 | AC_HEADER_STDC | 82 | AC_HEADER_STDC |
| 83 | 83 | ||
| 84 | - | ||
| 85 | # Checks for typedefs, structures, and compiler characteristics. | 84 | # Checks for typedefs, structures, and compiler characteristics. |
| 86 | AC_C_CONST | 85 | AC_C_CONST |
| 87 | AC_TYPE_SIZE_T | 86 | AC_TYPE_SIZE_T |
| @@ -97,7 +96,7 @@ AC_CHECK_DECLS([__CYGWIN__]) | @@ -97,7 +96,7 @@ AC_CHECK_DECLS([__CYGWIN__]) | ||
| 97 | 96 | ||
| 98 | # Checks for library functions. | 97 | # Checks for library functions. |
| 99 | AC_FUNC_FORK | 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 | AC_CONFIG_FILES([ | 101 | AC_CONFIG_FILES([ |
| 103 | Makefile | 102 | Makefile |
src/modbus-private.h
| @@ -109,6 +109,10 @@ struct _modbus { | @@ -109,6 +109,10 @@ struct _modbus { | ||
| 109 | void _modbus_init_common(modbus_t *ctx); | 109 | void _modbus_init_common(modbus_t *ctx); |
| 110 | void _error_print(modbus_t *ctx, const char *context); | 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 | MODBUS_END_DECLS | 116 | MODBUS_END_DECLS |
| 113 | 117 | ||
| 114 | #endif /* _MODBUS_PRIVATE_H_ */ | 118 | #endif /* _MODBUS_PRIVATE_H_ */ |
src/modbus-rtu.c
| @@ -853,6 +853,8 @@ modbus_t* modbus_new_rtu(const char *device, | @@ -853,6 +853,8 @@ modbus_t* modbus_new_rtu(const char *device, | ||
| 853 | { | 853 | { |
| 854 | modbus_t *ctx; | 854 | modbus_t *ctx; |
| 855 | modbus_rtu_t *ctx_rtu; | 855 | modbus_rtu_t *ctx_rtu; |
| 856 | + size_t dest_size; | ||
| 857 | + size_t src_size; | ||
| 856 | 858 | ||
| 857 | ctx = (modbus_t *) malloc(sizeof(modbus_t)); | 859 | ctx = (modbus_t *) malloc(sizeof(modbus_t)); |
| 858 | _modbus_init_common(ctx); | 860 | _modbus_init_common(ctx); |
| @@ -860,11 +862,23 @@ modbus_t* modbus_new_rtu(const char *device, | @@ -860,11 +862,23 @@ modbus_t* modbus_new_rtu(const char *device, | ||
| 860 | ctx->backend = &_modbus_rtu_backend; | 862 | ctx->backend = &_modbus_rtu_backend; |
| 861 | ctx->backend_data = (modbus_rtu_t *) malloc(sizeof(modbus_rtu_t)); | 863 | ctx->backend_data = (modbus_rtu_t *) malloc(sizeof(modbus_rtu_t)); |
| 862 | ctx_rtu = (modbus_rtu_t *)ctx->backend_data; | 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 | ctx_rtu->baud = baud; | 882 | ctx_rtu->baud = baud; |
| 869 | if (parity == 'N' || parity == 'E' || parity == 'O') { | 883 | if (parity == 'N' || parity == 'E' || parity == 'O') { |
| 870 | ctx_rtu->parity = parity; | 884 | ctx_rtu->parity = parity; |
src/modbus.c
| @@ -1425,3 +1425,42 @@ int modbus_accept(modbus_t *ctx, int *socket) | @@ -1425,3 +1425,42 @@ int modbus_accept(modbus_t *ctx, int *socket) | ||
| 1425 | { | 1425 | { |
| 1426 | return ctx->backend->accept(ctx, socket); | 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,6 +48,10 @@ int main(void) | ||
| 48 | 48 | ||
| 49 | /* TCP */ | 49 | /* TCP */ |
| 50 | ctx = modbus_new_tcp("127.0.0.1", 1502); | 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 | modbus_set_debug(ctx, TRUE); | 55 | modbus_set_debug(ctx, TRUE); |
| 52 | 56 | ||
| 53 | if (modbus_connect(ctx) == -1) { | 57 | if (modbus_connect(ctx) == -1) { |