Commit 4ac3cc374f2fb7f4e561137f8c42a37996845618

Authored by Stéphane Raimbault
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
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) {