diff options
author | Alan Coopersmith <alan.coopersmith@oracle.com> | 2022-04-17 10:19:58 -0700 |
---|---|---|
committer | Alan Coopersmith <alan.coopersmith@oracle.com> | 2022-04-17 10:19:58 -0700 |
commit | 10eecbe868b5c898ea9cd05d014fbf13c29c3a26 (patch) | |
tree | a0eee9f752a9e6761e569d0007237a353730c14c | |
parent | d14cb47d9e9a10d04b1a7de9d2799fef9b0436e0 (diff) |
handle.c: avoid leaks when realloc() fails
Resolves issues reported by Oracle Parfait static analyzer:
Error: Memory leak
Memory leak [memory-leak] (CWE 401):
Memory leak of pointer kclist allocated with malloc((n * 1))
at line 698 of app/xmodmap/handle.c in function 'do_remove'.
kclist allocated at line 662 with malloc((n * 1))
kclist leaks when num_kcs != 0 at line 676
and (j + 1) >= num_kcs at line 687
and (nc + num_kcs) > tot at line 691
and (num_kcs - 1) < 0 at line 701.
Memory leak [memory-leak] (CWE 401):
Memory leak of pointer kclist allocated with malloc((n * 1))
at line 711 of app/xmodmap/handle.c in function 'do_remove'.
kclist allocated at line 662 with malloc((n * 1))
kclist leaks when (i + 1) >= n at line 672.
Error: Memory leak
Memory leak [memory-leak] (CWE 401):
Memory leak of pointer kclist allocated with realloc(kclist, (tot * 1))
at line 711 of app/xmodmap/handle.c in function 'do_remove'.
kclist allocated at line 693 with realloc(kclist, (tot * 1))
kclist leaks when (num_kcs - 1) < 0 at line 701
and (i + 1) >= n at line 672.
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
-rw-r--r-- | handle.c | 35 |
1 files changed, 30 insertions, 5 deletions
@@ -37,6 +37,7 @@ from The Open Group. #include "xmodmap.h" #include "wq.h" #include <stdlib.h> +#include <stdint.h> #ifdef HAVE_STRNCASECMP #include <strings.h> @@ -59,6 +60,26 @@ struct wq work_queue = {NULL, NULL}; * common utility routines */ +/* + * This is a combination of reallocf() and reallocarray(). + * If the realloc fails, it frees the old pointer so it doesn't leak. + */ +static void * +reallocfarray(void *old, size_t num, size_t size) +{ + static void *new; + + if (size > 0 && num > (SIZE_MAX / size)) /* overflow would happen */ + new = NULL; + else + new = realloc(old, num * size); + + if (new == NULL) + free(old); + + return new; +} + static KeyCode * KeysymToKeycodes(Display *dpy, KeySym keysym, int *pnum_kcs) { @@ -72,7 +93,12 @@ KeysymToKeycodes(Display *dpy, KeySym keysym, int *pnum_kcs) if (!kcs) kcs = malloc(sizeof(KeyCode)); else - kcs = realloc(kcs, sizeof(KeyCode) * (*pnum_kcs + 1)); + kcs = reallocfarray(kcs, (*pnum_kcs + 1), sizeof(KeyCode)); + if (!kcs) { + fprintf(stderr, "attempt to allocate %ld byte keycode set", + (long) ((*pnum_kcs + 1) * sizeof (KeyCode))); + return NULL; + } kcs[*pnum_kcs] = i; *pnum_kcs += 1; break; @@ -690,7 +716,7 @@ do_remove(char *line, int len) } if (nc + num_kcs > tot) { tot = nc + num_kcs; - kclist = realloc(kclist, tot * sizeof(KeyCode)); + kclist = reallocfarray(kclist, tot, sizeof(KeyCode)); if (!kclist) { badmsg ("attempt to allocate %ld byte keycode list", (long) (tot * sizeof (KeyCode))); @@ -708,6 +734,7 @@ do_remove(char *line, int len) if (!uop) { badmsg ("attempt to allocate %ld byte removemodifier opcode", (long) sizeof (struct op_removemodifier)); + free(kclist); return; } oprm = &uop->removemodifier; @@ -982,13 +1009,11 @@ get_keysym_list(const char *line, int len, int *np, KeySym **kslistp) /* grow the list bigger if necessary */ if (havesofar >= maxcanhave) { - KeySym *origkeysymlist = keysymlist; maxcanhave *= 2; - keysymlist = realloc (keysymlist, maxcanhave * sizeof (KeySym)); + keysymlist = reallocfarray(keysymlist, maxcanhave, sizeof(KeySym)); if (!keysymlist) { badmsg ("attempt to grow keysym list to %ld bytes", (long) (maxcanhave * sizeof (KeySym))); - free(origkeysymlist); return (-1); } } |