diff mbox

[1/1] mcstrans: fix memory leaks reported by clang's static analyzer

Message ID 20180701145739.23309-1-nicolas.iooss@m4x.org (mailing list archive)
State Not Applicable
Headers show

Commit Message

Nicolas Iooss July 1, 2018, 2:57 p.m. UTC
There are many memory leaks in mcstrans. Clean them up in order to
reduce the noise in clang's static analyzer report. Some are remaining,
because they are more complex to fix.

Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
 mcstrans/src/mcstrans.c | 68 +++++++++++++++++++++++++++++++++--------
 1 file changed, 56 insertions(+), 12 deletions(-)

Comments

William Roberts July 1, 2018, 8:51 p.m. UTC | #1
I see lots of repeating blocks, would it make more sense to goto an
error label and free them then return -1?

On Sun, Jul 1, 2018 at 7:57 AM, Nicolas Iooss <nicolas.iooss@m4x.org> wrote:
> There are many memory leaks in mcstrans. Clean them up in order to
> reduce the noise in clang's static analyzer report. Some are remaining,
> because they are more complex to fix.
>
> Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
> ---
>  mcstrans/src/mcstrans.c | 68 +++++++++++++++++++++++++++++++++--------
>  1 file changed, 56 insertions(+), 12 deletions(-)
>
> diff --git a/mcstrans/src/mcstrans.c b/mcstrans/src/mcstrans.c
> index 00fb80856da7..96bdbdff7d8b 100644
> --- a/mcstrans/src/mcstrans.c
> +++ b/mcstrans/src/mcstrans.c
> @@ -708,6 +708,7 @@ append(affix_t **affixes, const char *val) {
>
>  err:
>         log_error("allocation error %s", strerror(errno));
> +       free(affix);
>         return -1;
>  }
>
> @@ -1517,8 +1518,10 @@ trans_context(const security_context_t incon, security_context_t *rcon) {
>                 } else {
>                         trans = compute_trans_from_raw(range, domain);
>                         if (trans)
> -                               if (add_cache(domain, range, trans) < 0)
> +                               if (add_cache(domain, range, trans) < 0) {
> +                                       free(range);
>                                         return -1;
> +                               }
>                 }
>
>                 if (lrange && urange) {
> @@ -1526,12 +1529,15 @@ trans_context(const security_context_t incon, security_context_t *rcon) {
>                         if (! ltrans) {
>                                 ltrans = compute_trans_from_raw(lrange, domain);
>                                 if (ltrans) {
> -                                       if (add_cache(domain, lrange, ltrans) < 0)
> +                                       if (add_cache(domain, lrange, ltrans) < 0) {
> +                                               free(range);
>                                                 return -1;
> +                                       }
>                                 } else {
>                                         ltrans = strdup(lrange);
>                                         if (! ltrans) {
>                                                 log_error("strdup failed %s", strerror(errno));
> +                                               free(range);
>                                                 return -1;
>                                         }
>                                 }
> @@ -1541,25 +1547,36 @@ trans_context(const security_context_t incon, security_context_t *rcon) {
>                         if (! utrans) {
>                                 utrans = compute_trans_from_raw(urange, domain);
>                                 if (utrans) {
> -                                       if (add_cache(domain, urange, utrans) < 0)
> +                                       if (add_cache(domain, urange, utrans) < 0) {
> +                                               free(ltrans);
> +                                               free(range);
>                                                 return -1;
> +                                       }
>                                 } else {
>                                         utrans = strdup(urange);
>                                         if (! utrans) {
>                                                 log_error("strdup failed %s", strerror(errno));
> -                                               return -1;
> -                                       }
> -                               }
> +                                               free(ltrans);
> +                                               free(range);
> +                                               return -1;
> +                                       }
> +                               }
>                         }
>
>                         if (strcmp(ltrans, utrans) == 0) {
>                                 if (asprintf(&trans, "%s", ltrans) < 0) {
>                                         log_error("asprintf failed %s", strerror(errno));
> +                                       free(utrans);
> +                                       free(ltrans);
> +                                       free(range);
>                                         return -1;
>                                 }
>                         } else {
>                                 if (asprintf(&trans, "%s-%s", ltrans, utrans) < 0) {
>                                         log_error("asprintf failed %s", strerror(errno));
> +                                       free(utrans);
> +                                       free(ltrans);
> +                                       free(range);
>                                         return -1;
>                                 }
>                         }
> @@ -1629,13 +1646,17 @@ untrans_context(const security_context_t incon, security_context_t *rcon) {
>                                 if (!canonical) {
>                                         canonical = compute_trans_from_raw(raw, domain);
>                                         if (canonical && strcmp(canonical, range))
> -                                               if (add_cache(domain, raw, canonical) < 0)
> +                                               if (add_cache(domain, raw, canonical) < 0) {
> +                                                       free(range);
>                                                         return -1;
> +                                               }
>                                 }
>                                 if (canonical)
>                                         free(canonical);
> -                               if (add_cache(domain, raw, range) < 0)
> +                               if (add_cache(domain, raw, range) < 0) {
> +                                       free(range);
>                                         return -1;
> +                               }
>                         } else {
>                                 log_debug("untrans_context unable to compute raw context %s\n", range);
>                         }
> @@ -1650,17 +1671,24 @@ untrans_context(const security_context_t incon, security_context_t *rcon) {
>                                         if (!canonical) {
>                                                 canonical = compute_trans_from_raw(lraw, domain);
>                                                 if (canonical)
> -                                                       if (add_cache(domain, lraw, canonical) < 0)
> +                                                       if (add_cache(domain, lraw, canonical) < 0) {
> +                                                               free(lraw);
> +                                                               free(range);
>                                                                 return -1;
> +                                                       }
>                                         }
>                                         if (canonical)
>                                                 free(canonical);
> -                                       if (add_cache(domain, lraw, lrange) < 0)
> +                                       if (add_cache(domain, lraw, lrange) < 0) {
> +                                               free(lraw);
> +                                               free(range);
>                                                 return -1;
> +                                       }
>                                 } else {
>                                         lraw = strdup(lrange);
>                                         if (! lraw) {
>                                                 log_error("strdup failed %s", strerror(errno));
> +                                               free(range);
>                                                 return -1;
>                                         }
>                                 }
> @@ -1674,17 +1702,27 @@ untrans_context(const security_context_t incon, security_context_t *rcon) {
>                                         if (!canonical) {
>                                                 canonical = compute_trans_from_raw(uraw, domain);
>                                                 if (canonical)
> -                                                       if (add_cache(domain, uraw, canonical) < 0)
> +                                                       if (add_cache(domain, uraw, canonical) < 0) {
> +                                                               free(uraw);
> +                                                               free(lraw);
> +                                                               free(range);
>                                                                 return -1;
>                                                         }
> +                                       }
>                                         if (canonical)
>                                                 free(canonical);
> -                                       if (add_cache(domain, uraw, urange) < 0)
> +                                       if (add_cache(domain, uraw, urange) < 0) {
> +                                               free(uraw);
> +                                               free(lraw);
> +                                               free(range);
>                                                 return -1;
> +                                       }
>                                 } else {
>                                         uraw = strdup(urange);
>                                         if (! uraw) {
>                                                 log_error("strdup failed %s", strerror(errno));
> +                                               free(lraw);
> +                                               free(range);
>                                                 return -1;
>                                         }
>                                 }
> @@ -1694,11 +1732,17 @@ untrans_context(const security_context_t incon, security_context_t *rcon) {
>                         if (strcmp(lraw, uraw) == 0) {
>                                 if (asprintf(&raw, "%s", lraw) < 0) {
>                                         log_error("asprintf failed %s", strerror(errno));
> +                                       free(uraw);
> +                                       free(lraw);
> +                                       free(range);
>                                         return -1;
>                                 }
>                         } else {
>                                 if (asprintf(&raw, "%s-%s", lraw, uraw) < 0) {
>                                         log_error("asprintf failed %s", strerror(errno));
> +                                       free(uraw);
> +                                       free(lraw);
> +                                       free(range);
>                                         return -1;
>                                 }
>                         }
> --
> 2.17.1
>
> _______________________________________________
> Selinux mailing list
> Selinux@tycho.nsa.gov
> To unsubscribe, send email to Selinux-leave@tycho.nsa.gov.
> To get help, send an email containing "help" to Selinux-request@tycho.nsa.gov.
Nicolas Iooss July 2, 2018, 6:38 p.m. UTC | #2
On Sun, Jul 1, 2018 at 10:51 PM, William Roberts
<bill.c.roberts@gmail.com> wrote:
> I see lots of repeating blocks, would it make more sense to goto an
> error label and free them then return -1?

Both trans_context() and untrans_context() currently define "char
*ltrans = NULL, *utrans = NULL;" and "char *lrange = NULL, *urange =
NULL;" in the body of a for loop. Introducing an error label at the
end of these functions requires moving these definition outside of the
loop (which could introduce side effects) and introducing the label at
the end of the loop makes the code less readable, IMHO. I guess this
could explain why the current code does not use a "goto error" or
"goto clean" approach and leaks memory where an error occurs.

Anyway, if you are fine with moving the definitions of some variables
(ltrans and utrans for trans_context(), lrange and urange for
untrans_context()), I can write, test and send a new patch with a
"goto error" instead of several free().

Thanks for your review,
Nicolas
William Roberts July 2, 2018, 10:49 p.m. UTC | #3
On Mon, Jul 2, 2018 at 11:38 AM, Nicolas Iooss <nicolas.iooss@m4x.org> wrote:
> On Sun, Jul 1, 2018 at 10:51 PM, William Roberts
> <bill.c.roberts@gmail.com> wrote:
>> I see lots of repeating blocks, would it make more sense to goto an
>> error label and free them then return -1?
>
> Both trans_context() and untrans_context() currently define "char
> *ltrans = NULL, *utrans = NULL;" and "char *lrange = NULL, *urange =
> NULL;" in the body of a for loop. Introducing an error label at the
> end of these functions requires moving these definition outside of the
> loop (which could introduce side effects) and introducing the label at
> the end of the loop makes the code less readable, IMHO. I guess this
> could explain why the current code does not use a "goto error" or
> "goto clean" approach and leaks memory where an error occurs.
>
> Anyway, if you are fine with moving the definitions of some variables
> (ltrans and utrans for trans_context(), lrange and urange for
> untrans_context()), I can write, test and send a new patch with a
> "goto error" instead of several free().

This seems fine. I just applied and tested this (finally). Ack.

>
> Thanks for your review,
> Nicolas
>
Nicolas Iooss July 4, 2018, 8:12 p.m. UTC | #4
On Tue, Jul 3, 2018 at 12:49 AM, William Roberts
<bill.c.roberts@gmail.com> wrote:
> On Mon, Jul 2, 2018 at 11:38 AM, Nicolas Iooss <nicolas.iooss@m4x.org> wrote:
>> On Sun, Jul 1, 2018 at 10:51 PM, William Roberts
>> <bill.c.roberts@gmail.com> wrote:
>>> I see lots of repeating blocks, would it make more sense to goto an
>>> error label and free them then return -1?
>>
>> Both trans_context() and untrans_context() currently define "char
>> *ltrans = NULL, *utrans = NULL;" and "char *lrange = NULL, *urange =
>> NULL;" in the body of a for loop. Introducing an error label at the
>> end of these functions requires moving these definition outside of the
>> loop (which could introduce side effects) and introducing the label at
>> the end of the loop makes the code less readable, IMHO. I guess this
>> could explain why the current code does not use a "goto error" or
>> "goto clean" approach and leaks memory where an error occurs.
>>
>> Anyway, if you are fine with moving the definitions of some variables
>> (ltrans and utrans for trans_context(), lrange and urange for
>> untrans_context()), I can write, test and send a new patch with a
>> "goto error" instead of several free().
>
> This seems fine. I just applied and tested this (finally). Ack.

Thanks. I applied the 3 patches that I sent.

Nicolas
diff mbox

Patch

diff --git a/mcstrans/src/mcstrans.c b/mcstrans/src/mcstrans.c
index 00fb80856da7..96bdbdff7d8b 100644
--- a/mcstrans/src/mcstrans.c
+++ b/mcstrans/src/mcstrans.c
@@ -708,6 +708,7 @@  append(affix_t **affixes, const char *val) {
 
 err:
 	log_error("allocation error %s", strerror(errno));
+	free(affix);
 	return -1;
 }
 
@@ -1517,8 +1518,10 @@  trans_context(const security_context_t incon, security_context_t *rcon) {
 		} else {
 			trans = compute_trans_from_raw(range, domain);
 			if (trans)
-				if (add_cache(domain, range, trans) < 0)
+				if (add_cache(domain, range, trans) < 0) {
+					free(range);
 					return -1;
+				}
 		}
 
 		if (lrange && urange) {
@@ -1526,12 +1529,15 @@  trans_context(const security_context_t incon, security_context_t *rcon) {
 			if (! ltrans) {
 				ltrans = compute_trans_from_raw(lrange, domain);
 				if (ltrans) {
-					if (add_cache(domain, lrange, ltrans) < 0)
+					if (add_cache(domain, lrange, ltrans) < 0) {
+						free(range);
 						return -1;
+					}
 				} else {
 					ltrans = strdup(lrange);
 					if (! ltrans) {
 						log_error("strdup failed %s", strerror(errno));
+						free(range);
 						return -1;
 					}
 				}
@@ -1541,25 +1547,36 @@  trans_context(const security_context_t incon, security_context_t *rcon) {
 			if (! utrans) {
 				utrans = compute_trans_from_raw(urange, domain);
 				if (utrans) {
-					if (add_cache(domain, urange, utrans) < 0)
+					if (add_cache(domain, urange, utrans) < 0) {
+						free(ltrans);
+						free(range);
 						return -1;
+					}
 				} else {
 					utrans = strdup(urange);
 					if (! utrans) {
 						log_error("strdup failed %s", strerror(errno));
- 						return -1;
- 					}
- 				}
+						free(ltrans);
+						free(range);
+						return -1;
+					}
+				}
 			}
 
 			if (strcmp(ltrans, utrans) == 0) {
 				if (asprintf(&trans, "%s", ltrans) < 0) {
 					log_error("asprintf failed %s", strerror(errno));
+					free(utrans);
+					free(ltrans);
+					free(range);
 					return -1;
 				}
 			} else {
 				if (asprintf(&trans, "%s-%s", ltrans, utrans) < 0) {
 					log_error("asprintf failed %s", strerror(errno));
+					free(utrans);
+					free(ltrans);
+					free(range);
 					return -1;
 				}
 			}
@@ -1629,13 +1646,17 @@  untrans_context(const security_context_t incon, security_context_t *rcon) {
 				if (!canonical) {
 					canonical = compute_trans_from_raw(raw, domain);
 					if (canonical && strcmp(canonical, range))
-						if (add_cache(domain, raw, canonical) < 0)
+						if (add_cache(domain, raw, canonical) < 0) {
+							free(range);
 							return -1;
+						}
 				}
 				if (canonical)
 					free(canonical);
-				if (add_cache(domain, raw, range) < 0)
+				if (add_cache(domain, raw, range) < 0) {
+					free(range);
 					return -1;
+				}
 			} else {
 				log_debug("untrans_context unable to compute raw context %s\n", range);
 			}
@@ -1650,17 +1671,24 @@  untrans_context(const security_context_t incon, security_context_t *rcon) {
 					if (!canonical) {
 						canonical = compute_trans_from_raw(lraw, domain);
 						if (canonical)
-							if (add_cache(domain, lraw, canonical) < 0)
+							if (add_cache(domain, lraw, canonical) < 0) {
+								free(lraw);
+								free(range);
 								return -1;
+							}
 					}
 					if (canonical)
 						free(canonical);
-					if (add_cache(domain, lraw, lrange) < 0)
+					if (add_cache(domain, lraw, lrange) < 0) {
+						free(lraw);
+						free(range);
 						return -1;
+					}
 				} else {
 					lraw = strdup(lrange);
 					if (! lraw) {
 						log_error("strdup failed %s", strerror(errno));
+						free(range);
 						return -1;
 					}
 				}
@@ -1674,17 +1702,27 @@  untrans_context(const security_context_t incon, security_context_t *rcon) {
 					if (!canonical) {
 						canonical = compute_trans_from_raw(uraw, domain);
 						if (canonical)
-							if (add_cache(domain, uraw, canonical) < 0)
+							if (add_cache(domain, uraw, canonical) < 0) {
+								free(uraw);
+								free(lraw);
+								free(range);
 								return -1;
 							}
+					}
 					if (canonical)
 						free(canonical);
-					if (add_cache(domain, uraw, urange) < 0)
+					if (add_cache(domain, uraw, urange) < 0) {
+						free(uraw);
+						free(lraw);
+						free(range);
 						return -1;
+					}
 				} else {
 					uraw = strdup(urange);
 					if (! uraw) {
 						log_error("strdup failed %s", strerror(errno));
+						free(lraw);
+						free(range);
 						return -1;
 					}
 				}
@@ -1694,11 +1732,17 @@  untrans_context(const security_context_t incon, security_context_t *rcon) {
 			if (strcmp(lraw, uraw) == 0) {
 				if (asprintf(&raw, "%s", lraw) < 0) {
 					log_error("asprintf failed %s", strerror(errno));
+					free(uraw);
+					free(lraw);
+					free(range);
 					return -1;
 				}
 			} else {
 				if (asprintf(&raw, "%s-%s", lraw, uraw) < 0) {
 					log_error("asprintf failed %s", strerror(errno));
+					free(uraw);
+					free(lraw);
+					free(range);
 					return -1;
 				}
 			}