瀏覽代碼

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 年之前
父節點
當前提交
c258137adc
共有 5 個文件被更改,包括 47 次插入3 次删除
  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) {