This fixes a null pointer dereference in MuJS regexp.c as reported at: http://seclists.org/oss-sec/2017/q1/74 Patch lifted from upstream source repository: http://git.ghostscript.com/?p=mujs.git;h=fd003eceda531e13fbdd1aeb6e9c73156496e569 From fd003eceda531e13fbdd1aeb6e9c73156496e569 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Fri, 2 Dec 2016 14:56:20 -0500 Subject: [PATCH] Fix 697381: check allocation when compiling regular expressions. Also use allocator callback function. --- thirdparty/mujs/jsgc.c | 2 +- thirdparty/mujs/jsregexp.c | 2 +- thirdparty/mujs/jsstate.c | 6 ------ thirdparty/mujs/regexp.c | 45 +++++++++++++++++++++++++++++++++++---------- thirdparty/mujs/regexp.h | 7 +++++++ 5 files changed, 44 insertions(+), 18 deletions(-) diff --git a/thirdparty/mujs/jsgc.c b/thirdparty/mujs/jsgc.c index 4f7e7dc..f80111e 100644 --- a/thirdparty/mujs/jsgc.c +++ b/thirdparty/mujs/jsgc.c @@ -46,7 +46,7 @@ static void jsG_freeobject(js_State *J, js_Object *obj) jsG_freeproperty(J, obj->head); if (obj->type == JS_CREGEXP) { js_free(J, obj->u.r.source); - js_regfree(obj->u.r.prog); + js_regfreex(J->alloc, J->actx, obj->u.r.prog); } if (obj->type == JS_CITERATOR) jsG_freeiterator(J, obj->u.iter.head); diff --git a/thirdparty/mujs/jsregexp.c b/thirdparty/mujs/jsregexp.c index a2d5156..7b09c06 100644 --- a/thirdparty/mujs/jsregexp.c +++ b/thirdparty/mujs/jsregexp.c @@ -16,7 +16,7 @@ void js_newregexp(js_State *J, const char *pattern, int flags) if (flags & JS_REGEXP_I) opts |= REG_ICASE; if (flags & JS_REGEXP_M) opts |= REG_NEWLINE; - prog = js_regcomp(pattern, opts, &error); + prog = js_regcompx(J->alloc, J->actx, pattern, opts, &error); if (!prog) js_syntaxerror(J, "regular expression: %s", error); diff --git a/thirdparty/mujs/jsstate.c b/thirdparty/mujs/jsstate.c index 638cab3..fd5bcf6 100644 --- a/thirdparty/mujs/jsstate.c +++ b/thirdparty/mujs/jsstate.c @@ -9,12 +9,6 @@ static void *js_defaultalloc(void *actx, void *ptr, int size) { - if (size == 0) { - free(ptr); - return NULL; - } - if (!ptr) - return malloc((size_t)size); return realloc(ptr, (size_t)size); } diff --git a/thirdparty/mujs/regexp.c b/thirdparty/mujs/regexp.c index 9852be2..01c18a3 100644 --- a/thirdparty/mujs/regexp.c +++ b/thirdparty/mujs/regexp.c @@ -807,23 +807,31 @@ static void dumpprog(Reprog *prog) } #endif -Reprog *regcomp(const char *pattern, int cflags, const char **errorp) +Reprog *regcompx(void *(*alloc)(void *ctx, void *p, int n), void *ctx, + const char *pattern, int cflags, const char **errorp) { struct cstate g; Renode *node; Reinst *split, *jump; int i; - g.prog = malloc(sizeof (Reprog)); - g.pstart = g.pend = malloc(sizeof (Renode) * strlen(pattern) * 2); + g.pstart = NULL; + g.prog = NULL; if (setjmp(g.kaboom)) { if (errorp) *errorp = g.error; - free(g.pstart); - free(g.prog); + alloc(ctx, g.pstart, 0); + alloc(ctx, g.prog, 0); return NULL; } + g.prog = alloc(ctx, NULL, sizeof (Reprog)); + if (!g.prog) + die(&g, "cannot allocate regular expression"); + g.pstart = g.pend = alloc(ctx, NULL, sizeof (Renode) * strlen(pattern) * 2); + if (!g.pstart) + die(&g, "cannot allocate regular expression parse list"); + g.source = pattern; g.ncclass = 0; g.nsub = 1; @@ -840,7 +848,9 @@ Reprog *regcomp(const char *pattern, int cflags, const char **errorp) die(&g, "syntax error"); g.prog->nsub = g.nsub; - g.prog->start = g.prog->end = malloc((count(node) + 6) * sizeof (Reinst)); + g.prog->start = g.prog->end = alloc(ctx, NULL, (count(node) + 6) * sizeof (Reinst)); + if (!g.prog->start) + die(&g, "cannot allocate regular expression instruction list"); split = emit(g.prog, I_SPLIT); split->x = split + 3; @@ -859,20 +869,35 @@ Reprog *regcomp(const char *pattern, int cflags, const char **errorp) dumpprog(g.prog); #endif - free(g.pstart); + alloc(ctx, g.pstart, 0); if (errorp) *errorp = NULL; return g.prog; } -void regfree(Reprog *prog) +void regfreex(void *(*alloc)(void *ctx, void *p, int n), void *ctx, Reprog *prog) { if (prog) { - free(prog->start); - free(prog); + alloc(ctx, prog->start, 0); + alloc(ctx, prog, 0); } } +static void *default_alloc(void *ctx, void *p, int n) +{ + return realloc(p, (size_t)n); +} + +Reprog *regcomp(const char *pattern, int cflags, const char **errorp) +{ + return regcompx(default_alloc, NULL, pattern, cflags, errorp); +} + +void regfree(Reprog *prog) +{ + regfreex(default_alloc, NULL, prog); +} + /* Match */ static int isnewline(int c) diff --git a/thirdparty/mujs/regexp.h b/thirdparty/mujs/regexp.h index 4bb4615..6bb73e8 100644 --- a/thirdparty/mujs/regexp.h +++ b/thirdparty/mujs/regexp.h @@ -1,6 +1,8 @@ #ifndef regexp_h #define regexp_h +#define regcompx js_regcompx +#define regfreex js_regfreex #define regcomp js_regcomp #define regexec js_regexec #define regfree js_regfree @@ -8,6 +10,11 @@ typedef struct Reprog Reprog; typedef struct Resub Resub; +Reprog *regcompx(void *(*alloc)(void *ctx, void *p, int n), void *ctx, + const char *pattern, int cflags, const char **errorp); +void regfreex(void *(*alloc)(void *ctx, void *p, int n), void *ctx, + Reprog *prog); + Reprog *regcomp(const char *pattern, int cflags, const char **errorp); int regexec(Reprog *prog, const char *string, Resub *sub, int eflags); void regfree(Reprog *prog); -- 2.9.1