From 2d50b7f2ccf6faeaa22d735066d915956f3117a0 Mon Sep 17 00:00:00 2001 From: espie Date: Sun, 21 Dec 2014 09:33:12 +0000 Subject: [PATCH] fix test-redef2: - introduce explicit STORAGE classes for the shadow stack entries - delay freeing definitions if they're in-use, keep them in a simple array. okay millert@ --- usr.bin/m4/look.c | 68 +++++++++++++++++++++++++++++++++++++++++++++-- usr.bin/m4/main.c | 4 +-- usr.bin/m4/mdef.h | 21 ++++++++++++--- usr.bin/m4/misc.c | 4 +-- 4 files changed, 87 insertions(+), 10 deletions(-) diff --git a/usr.bin/m4/look.c b/usr.bin/m4/look.c index eeec6569430..ac504570a9f 100644 --- a/usr.bin/m4/look.c +++ b/usr.bin/m4/look.c @@ -1,4 +1,4 @@ -/* $OpenBSD: look.c,v 1.23 2014/05/12 19:11:19 espie Exp $ */ +/* $OpenBSD: look.c,v 1.24 2014/12/21 09:33:12 espie Exp $ */ /* * Copyright (c) 1989, 1993 @@ -53,6 +53,9 @@ static void hash_free(void *, void *); static void *element_alloc(size_t, void *); static void setup_definition(struct macro_definition *, const char *, const char *); +static void free_definition(char *); +static void keep(char *); +static int string_in_use(const char *); static struct ohash_info macro_info = { offsetof(struct ndblock, name), @@ -152,7 +155,7 @@ macro_define(const char *name, const char *defn) ndptr n = create_entry(name); if (n->d != NULL) { if (n->d->defn != null) - free(n->d->defn); + free_definition(n->d->defn); } else { n->d = xalloc(sizeof(struct macro_definition), NULL); n->d->next = NULL; @@ -270,3 +273,64 @@ macro_getbuiltin(const char *name) else return p; } + +/* XXX things are slightly more complicated than they seem. + * a macro may actually be "live" (in the middle of an expansion + * on the stack. + * So we actually may need to place it in an array for later... + */ + +static int kept_capacity = 0; +static int kept_size = 0; +static char **kept = NULL; + +static void +keep(char *ptr) +{ + if (kept_capacity <= kept_size) { + if (kept_capacity) + kept_capacity *= 2; + else + kept_capacity = 50; + kept = xreallocarray(kept, kept_capacity, + sizeof(char *), "Out of memory while saving %d strings\n", + kept_capacity); + } + kept[kept_size++] = ptr; +} + +static int +string_in_use(const char *ptr) +{ + int i; + for (i = 0; i <= sp; i++) { + if (sstack[i] == STORAGE_MACRO && mstack[i].sstr == ptr) + return 1; + } + return 0; +} + + +static void +free_definition(char *ptr) +{ + int i; + + /* first try to free old strings */ + for (i = 0; i < kept_size; i++) { + if (!string_in_use(kept[i])) { + kept_size--; + free(kept[i]); + if (i != kept_size) + kept[i] = kept[kept_size]; + i--; + } + } + + /* then deal with us */ + if (string_in_use(ptr)) + keep(ptr); + else + free(ptr); +} + diff --git a/usr.bin/m4/main.c b/usr.bin/m4/main.c index 1dce48e50e0..b75877fbf9a 100644 --- a/usr.bin/m4/main.c +++ b/usr.bin/m4/main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: main.c,v 1.83 2014/05/12 19:11:19 espie Exp $ */ +/* $OpenBSD: main.c,v 1.84 2014/12/21 09:33:12 espie Exp $ */ /* $NetBSD: main.c,v 1.12 1997/02/08 23:54:49 cgd Exp $ */ /*- @@ -397,7 +397,7 @@ macro(void) /* * now push the string arguments: */ - pushs1(macro_getdef(p)->defn); /* defn string */ + pushdef(p); /* defn string */ pushs1((char *)macro_name(p)); /* macro name */ pushs(ep); /* start next..*/ diff --git a/usr.bin/m4/mdef.h b/usr.bin/m4/mdef.h index a4a2bbdc1e6..3185dcb38fa 100644 --- a/usr.bin/m4/mdef.h +++ b/usr.bin/m4/mdef.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mdef.h,v 1.31 2011/09/27 07:24:02 espie Exp $ */ +/* $OpenBSD: mdef.h,v 1.32 2014/12/21 09:33:12 espie Exp $ */ /* $NetBSD: mdef.h,v 1.7 1996/01/13 23:25:27 pk Exp $ */ /* @@ -163,6 +163,10 @@ struct input_file { int c; }; +#define STORAGE_STRSPACE 0 +#define STORAGE_MACRO 1 +#define STORAGE_OTHER 2 + #define CURRENT_NAME (infile[ilevel].name) #define CURRENT_LINE (infile[ilevel].lineno) /* @@ -178,7 +182,7 @@ struct input_file { if (++sp == STACKMAX) \ enlarge_stack();\ mstack[sp].sfra = (x); \ - sstack[sp] = 0; \ + sstack[sp] = STORAGE_OTHER; \ } while (0) #define pushs(x) \ @@ -186,7 +190,7 @@ struct input_file { if (++sp == STACKMAX) \ enlarge_stack();\ mstack[sp].sstr = (x); \ - sstack[sp] = 1; \ + sstack[sp] = STORAGE_STRSPACE; \ } while (0) #define pushs1(x) \ @@ -194,8 +198,17 @@ struct input_file { if (++sp == STACKMAX) \ enlarge_stack();\ mstack[sp].sstr = (x); \ - sstack[sp] = 0; \ + sstack[sp] = STORAGE_OTHER; \ + } while (0) + +#define pushdef(p) \ + do { \ + if (++sp == STACKMAX) \ + enlarge_stack();\ + mstack[sp].sstr = macro_getdef(p)->defn;\ + sstack[sp] = STORAGE_MACRO; \ } while (0) + /* * . . diff --git a/usr.bin/m4/misc.c b/usr.bin/m4/misc.c index 556ecd637b9..122cf0b3dc5 100644 --- a/usr.bin/m4/misc.c +++ b/usr.bin/m4/misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.c,v 1.44 2014/05/12 19:11:19 espie Exp $ */ +/* $OpenBSD: misc.c,v 1.45 2014/12/21 09:33:12 espie Exp $ */ /* $NetBSD: misc.c,v 1.6 1995/09/28 05:37:41 tls Exp $ */ /* @@ -184,7 +184,7 @@ enlarge_strspace() errx(1, "string space overflow"); memcpy(newstrspace, strspace, strsize/2); for (i = 0; i <= sp; i++) - if (sstack[i]) + if (sstack[i] == STORAGE_STRSPACE) mstack[i].sstr = (mstack[i].sstr - strspace) + newstrspace; ep = (ep-strspace) + newstrspace; -- 2.20.1