Commit c258137adcc6182a50effb2dd1d77c54ac0798a0

Authored by Michael Heimpold
Committed by Stéphane Raimbault
1 parent a002b389

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>
doc/modbus_new_rtu.txt
@@ -53,6 +53,10 @@ ERRORS @@ -53,6 +53,10 @@ ERRORS
53 *EINVAL*:: 53 *EINVAL*::
54 An invalid argument was given. 54 An invalid argument was given.
55 55
  56 +*ENOMEM*::
  57 +Out of memory. Possibly, the application hits its memory limit and/or whole
  58 +system is running out of memory.
  59 +
56 60
57 EXAMPLE 61 EXAMPLE
58 ------- 62 -------
doc/modbus_new_tcp.txt
@@ -39,6 +39,10 @@ ERRORS @@ -39,6 +39,10 @@ ERRORS
39 *EINVAL*:: 39 *EINVAL*::
40 An invalid IP address was given. 40 An invalid IP address was given.
41 41
  42 +*ENOMEM*::
  43 +Out of memory. Possibly, the application hits its memory limit and/or whole
  44 +system is running out of memory.
  45 +
42 46
43 EXAMPLE 47 EXAMPLE
44 ------- 48 -------
doc/modbus_new_tcp_pi.txt
@@ -40,6 +40,10 @@ ERRORS @@ -40,6 +40,10 @@ ERRORS
40 The node string is empty or has been truncated. The service string is empty or 40 The node string is empty or has been truncated. The service string is empty or
41 has been truncated. 41 has been truncated.
42 42
  43 +*ENOMEM*::
  44 +Out of memory. Possibly, the application hits its memory limit and/or whole
  45 +system is running out of memory.
  46 +
43 47
44 EXAMPLE 48 EXAMPLE
45 ------- 49 -------
src/modbus-rtu.c
@@ -1180,8 +1180,11 @@ static int _modbus_rtu_select(modbus_t *ctx, fd_set *rset, @@ -1180,8 +1180,11 @@ static int _modbus_rtu_select(modbus_t *ctx, fd_set *rset,
1180 } 1180 }
1181 1181
1182 static void _modbus_rtu_free(modbus_t *ctx) { 1182 static void _modbus_rtu_free(modbus_t *ctx) {
1183 - free(((modbus_rtu_t*)ctx->backend_data)->device);  
1184 - free(ctx->backend_data); 1183 + if (ctx->backend_data) {
  1184 + free(((modbus_rtu_t *)ctx->backend_data)->device);
  1185 + free(ctx->backend_data);
  1186 + }
  1187 +
1185 free(ctx); 1188 free(ctx);
1186 } 1189 }
1187 1190
@@ -1229,14 +1232,27 @@ modbus_t* modbus_new_rtu(const char *device, @@ -1229,14 +1232,27 @@ modbus_t* modbus_new_rtu(const char *device,
1229 } 1232 }
1230 1233
1231 ctx = (modbus_t *)malloc(sizeof(modbus_t)); 1234 ctx = (modbus_t *)malloc(sizeof(modbus_t));
  1235 + if (ctx == NULL) {
  1236 + return NULL;
  1237 + }
  1238 +
1232 _modbus_init_common(ctx); 1239 _modbus_init_common(ctx);
1233 ctx->backend = &_modbus_rtu_backend; 1240 ctx->backend = &_modbus_rtu_backend;
1234 ctx->backend_data = (modbus_rtu_t *)malloc(sizeof(modbus_rtu_t)); 1241 ctx->backend_data = (modbus_rtu_t *)malloc(sizeof(modbus_rtu_t));
  1242 + if (ctx->backend_data == NULL) {
  1243 + modbus_free(ctx);
  1244 + errno = ENOMEM;
  1245 + return NULL;
  1246 + }
1235 ctx_rtu = (modbus_rtu_t *)ctx->backend_data; 1247 ctx_rtu = (modbus_rtu_t *)ctx->backend_data;
1236 - ctx_rtu->device = NULL;  
1237 1248
1238 /* Device name and \0 */ 1249 /* Device name and \0 */
1239 ctx_rtu->device = (char *)malloc((strlen(device) + 1) * sizeof(char)); 1250 ctx_rtu->device = (char *)malloc((strlen(device) + 1) * sizeof(char));
  1251 + if (ctx_rtu->device == NULL) {
  1252 + modbus_free(ctx);
  1253 + errno = ENOMEM;
  1254 + return NULL;
  1255 + }
1240 strcpy(ctx_rtu->device, device); 1256 strcpy(ctx_rtu->device, device);
1241 1257
1242 ctx_rtu->baud = baud; 1258 ctx_rtu->baud = baud;
src/modbus-tcp.c
@@ -799,6 +799,9 @@ modbus_t* modbus_new_tcp(const char *ip, int port) @@ -799,6 +799,9 @@ modbus_t* modbus_new_tcp(const char *ip, int port)
799 #endif 799 #endif
800 800
801 ctx = (modbus_t *)malloc(sizeof(modbus_t)); 801 ctx = (modbus_t *)malloc(sizeof(modbus_t));
  802 + if (ctx == NULL) {
  803 + return NULL;
  804 + }
802 _modbus_init_common(ctx); 805 _modbus_init_common(ctx);
803 806
804 /* Could be changed after to reach a remote serial Modbus device */ 807 /* 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) @@ -807,6 +810,11 @@ modbus_t* modbus_new_tcp(const char *ip, int port)
807 ctx->backend = &_modbus_tcp_backend; 810 ctx->backend = &_modbus_tcp_backend;
808 811
809 ctx->backend_data = (modbus_tcp_t *)malloc(sizeof(modbus_tcp_t)); 812 ctx->backend_data = (modbus_tcp_t *)malloc(sizeof(modbus_tcp_t));
  813 + if (ctx->backend_data == NULL) {
  814 + modbus_free(ctx);
  815 + errno = ENOMEM;
  816 + return NULL;
  817 + }
810 ctx_tcp = (modbus_tcp_t *)ctx->backend_data; 818 ctx_tcp = (modbus_tcp_t *)ctx->backend_data;
811 819
812 if (ip != NULL) { 820 if (ip != NULL) {
@@ -843,6 +851,9 @@ modbus_t* modbus_new_tcp_pi(const char *node, const char *service) @@ -843,6 +851,9 @@ modbus_t* modbus_new_tcp_pi(const char *node, const char *service)
843 size_t ret_size; 851 size_t ret_size;
844 852
845 ctx = (modbus_t *)malloc(sizeof(modbus_t)); 853 ctx = (modbus_t *)malloc(sizeof(modbus_t));
  854 + if (ctx == NULL) {
  855 + return NULL;
  856 + }
846 _modbus_init_common(ctx); 857 _modbus_init_common(ctx);
847 858
848 /* Could be changed after to reach a remote serial Modbus device */ 859 /* 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) @@ -851,6 +862,11 @@ modbus_t* modbus_new_tcp_pi(const char *node, const char *service)
851 ctx->backend = &_modbus_tcp_pi_backend; 862 ctx->backend = &_modbus_tcp_pi_backend;
852 863
853 ctx->backend_data = (modbus_tcp_pi_t *)malloc(sizeof(modbus_tcp_pi_t)); 864 ctx->backend_data = (modbus_tcp_pi_t *)malloc(sizeof(modbus_tcp_pi_t));
  865 + if (ctx->backend_data == NULL) {
  866 + modbus_free(ctx);
  867 + errno = ENOMEM;
  868 + return NULL;
  869 + }
854 ctx_tcp_pi = (modbus_tcp_pi_t *)ctx->backend_data; 870 ctx_tcp_pi = (modbus_tcp_pi_t *)ctx->backend_data;
855 871
856 if (node == NULL) { 872 if (node == NULL) {