summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Coopersmith <alan.coopersmith@oracle.com>2022-04-17 10:19:58 -0700
committerAlan Coopersmith <alan.coopersmith@oracle.com>2022-04-17 10:19:58 -0700
commit10eecbe868b5c898ea9cd05d014fbf13c29c3a26 (patch)
treea0eee9f752a9e6761e569d0007237a353730c14c
parentd14cb47d9e9a10d04b1a7de9d2799fef9b0436e0 (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.c35
1 files changed, 30 insertions, 5 deletions
diff --git a/handle.c b/handle.c
index 429b57a..ffbfe12 100644
--- a/handle.c
+++ b/handle.c
@@ -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);
}
}