Browse Source

Handle out-of-memory conditions more gracefully

Current code could dereference NULL pointer in case an inner
malloc fails. Check for this and exit gracefully.

Signed-off-by: Michael Heimpold <mhei@heimpold.de>
Michael Heimpold 8 years ago
parent
commit
c258137adc
5 changed files with 47 additions and 3 deletions
  1. 4 0
      doc/modbus_new_rtu.txt
  2. 4 0
      doc/modbus_new_tcp.txt
  3. 4 0
      doc/modbus_new_tcp_pi.txt
  4. 19 3
      src/modbus-rtu.c
  5. 16 0
      src/modbus-tcp.c

+ 4 - 0
doc/modbus_new_rtu.txt

@@ -53,6 +53,10 @@ ERRORS
 *EINVAL*::
 *EINVAL*::
 An invalid argument was given.
 An invalid argument was given.
 
 
+*ENOMEM*::
+Out of memory. Possibly, the application hits its memory limit and/or whole
+system is running out of memory.
+
 
 
 EXAMPLE
 EXAMPLE
 -------
 -------

+ 4 - 0
doc/modbus_new_tcp.txt

@@ -39,6 +39,10 @@ ERRORS
 *EINVAL*::
 *EINVAL*::
 An invalid IP address was given.
 An invalid IP address was given.
 
 
+*ENOMEM*::
+Out of memory. Possibly, the application hits its memory limit and/or whole
+system is running out of memory.
+
 
 
 EXAMPLE
 EXAMPLE
 -------
 -------

+ 4 - 0
doc/modbus_new_tcp_pi.txt

@@ -40,6 +40,10 @@ ERRORS
 The node string is empty or has been truncated. The service string is empty or
 The node string is empty or has been truncated. The service string is empty or
 has been truncated.
 has been truncated.
 
 
+*ENOMEM*::
+Out of memory. Possibly, the application hits its memory limit and/or whole
+system is running out of memory.
+
 
 
 EXAMPLE
 EXAMPLE
 -------
 -------

+ 19 - 3
src/modbus-rtu.c

@@ -1180,8 +1180,11 @@ static int _modbus_rtu_select(modbus_t *ctx, fd_set *rset,
 }
 }
 
 
 static void _modbus_rtu_free(modbus_t *ctx) {
 static void _modbus_rtu_free(modbus_t *ctx) {
-    free(((modbus_rtu_t*)ctx->backend_data)->device);
-    free(ctx->backend_data);
+    if (ctx->backend_data) {
+        free(((modbus_rtu_t *)ctx->backend_data)->device);
+        free(ctx->backend_data);
+    }
+
     free(ctx);
     free(ctx);
 }
 }
 
 
@@ -1229,14 +1232,27 @@ modbus_t* modbus_new_rtu(const char *device,
     }
     }
 
 
     ctx = (modbus_t *)malloc(sizeof(modbus_t));
     ctx = (modbus_t *)malloc(sizeof(modbus_t));
+    if (ctx == NULL) {
+        return NULL;
+    }
+
     _modbus_init_common(ctx);
     _modbus_init_common(ctx);
     ctx->backend = &_modbus_rtu_backend;
     ctx->backend = &_modbus_rtu_backend;
     ctx->backend_data = (modbus_rtu_t *)malloc(sizeof(modbus_rtu_t));
     ctx->backend_data = (modbus_rtu_t *)malloc(sizeof(modbus_rtu_t));
+    if (ctx->backend_data == NULL) {
+        modbus_free(ctx);
+        errno = ENOMEM;
+        return NULL;
+    }
     ctx_rtu = (modbus_rtu_t *)ctx->backend_data;
     ctx_rtu = (modbus_rtu_t *)ctx->backend_data;
-    ctx_rtu->device = NULL;
 
 
     /* Device name and \0 */
     /* Device name and \0 */
     ctx_rtu->device = (char *)malloc((strlen(device) + 1) * sizeof(char));
     ctx_rtu->device = (char *)malloc((strlen(device) + 1) * sizeof(char));
+    if (ctx_rtu->device == NULL) {
+        modbus_free(ctx);
+        errno = ENOMEM;
+        return NULL;
+    }
     strcpy(ctx_rtu->device, device);
     strcpy(ctx_rtu->device, device);
 
 
     ctx_rtu->baud = baud;
     ctx_rtu->baud = baud;

+ 16 - 0
src/modbus-tcp.c

@@ -799,6 +799,9 @@ modbus_t* modbus_new_tcp(const char *ip, int port)
 #endif
 #endif
 
 
     ctx = (modbus_t *)malloc(sizeof(modbus_t));
     ctx = (modbus_t *)malloc(sizeof(modbus_t));
+    if (ctx == NULL) {
+        return NULL;
+    }
     _modbus_init_common(ctx);
     _modbus_init_common(ctx);
 
 
     /* Could be changed after to reach a remote serial Modbus device */
     /* Could be changed after to reach a remote serial Modbus device */
@@ -807,6 +810,11 @@ modbus_t* modbus_new_tcp(const char *ip, int port)
     ctx->backend = &_modbus_tcp_backend;
     ctx->backend = &_modbus_tcp_backend;
 
 
     ctx->backend_data = (modbus_tcp_t *)malloc(sizeof(modbus_tcp_t));
     ctx->backend_data = (modbus_tcp_t *)malloc(sizeof(modbus_tcp_t));
+    if (ctx->backend_data == NULL) {
+        modbus_free(ctx);
+        errno = ENOMEM;
+        return NULL;
+    }
     ctx_tcp = (modbus_tcp_t *)ctx->backend_data;
     ctx_tcp = (modbus_tcp_t *)ctx->backend_data;
 
 
     if (ip != NULL) {
     if (ip != NULL) {
@@ -843,6 +851,9 @@ modbus_t* modbus_new_tcp_pi(const char *node, const char *service)
     size_t ret_size;
     size_t ret_size;
 
 
     ctx = (modbus_t *)malloc(sizeof(modbus_t));
     ctx = (modbus_t *)malloc(sizeof(modbus_t));
+    if (ctx == NULL) {
+        return NULL;
+    }
     _modbus_init_common(ctx);
     _modbus_init_common(ctx);
 
 
     /* Could be changed after to reach a remote serial Modbus device */
     /* Could be changed after to reach a remote serial Modbus device */
@@ -851,6 +862,11 @@ modbus_t* modbus_new_tcp_pi(const char *node, const char *service)
     ctx->backend = &_modbus_tcp_pi_backend;
     ctx->backend = &_modbus_tcp_pi_backend;
 
 
     ctx->backend_data = (modbus_tcp_pi_t *)malloc(sizeof(modbus_tcp_pi_t));
     ctx->backend_data = (modbus_tcp_pi_t *)malloc(sizeof(modbus_tcp_pi_t));
+    if (ctx->backend_data == NULL) {
+        modbus_free(ctx);
+        errno = ENOMEM;
+        return NULL;
+    }
     ctx_tcp_pi = (modbus_tcp_pi_t *)ctx->backend_data;
     ctx_tcp_pi = (modbus_tcp_pi_t *)ctx->backend_data;
 
 
     if (node == NULL) {
     if (node == NULL) {