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*::
 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
 -------

+ 4 - 0
doc/modbus_new_tcp.txt

@@ -39,6 +39,10 @@ ERRORS
 *EINVAL*::
 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
 -------

+ 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
 has been truncated.
 
+*ENOMEM*::
+Out of memory. Possibly, the application hits its memory limit and/or whole
+system is running out of memory.
+
 
 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) {
-    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);
 }
 
@@ -1229,14 +1232,27 @@ modbus_t* modbus_new_rtu(const char *device,
     }
 
     ctx = (modbus_t *)malloc(sizeof(modbus_t));
+    if (ctx == NULL) {
+        return NULL;
+    }
+
     _modbus_init_common(ctx);
     ctx->backend = &_modbus_rtu_backend;
     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->device = NULL;
 
     /* Device name and \0 */
     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);
 
     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
 
     ctx = (modbus_t *)malloc(sizeof(modbus_t));
+    if (ctx == NULL) {
+        return NULL;
+    }
     _modbus_init_common(ctx);
 
     /* 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_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;
 
     if (ip != NULL) {
@@ -843,6 +851,9 @@ modbus_t* modbus_new_tcp_pi(const char *node, const char *service)
     size_t ret_size;
 
     ctx = (modbus_t *)malloc(sizeof(modbus_t));
+    if (ctx == NULL) {
+        return NULL;
+    }
     _modbus_init_common(ctx);
 
     /* 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_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;
 
     if (node == NULL) {