diff options
author | Ian Romanick <[email protected]> | 2010-08-02 12:49:20 -0700 |
---|---|---|
committer | Ian Romanick <[email protected]> | 2010-08-02 13:53:32 -0700 |
commit | 955ceef47f2bb8b5005abf11d4a8580c71f19e1b (patch) | |
tree | 339e3ab1b2207fafd13f51fb4847f161f1061a49 | |
parent | 7ffe40532f6b22d9b80caeac0fc3b9495619186a (diff) |
Keep a local copy of the symbol name in the symbol table
The symbol_header structure that tracks symbols with a particular name
may have a different (longer) life time than the symbols it tracks.
Not keeping a local copy of the name can lead to use-after-free
errors. For example, the following sequence would trigger such an
error:
char *copy = strdup(name);
_mesa_symbol_table_push_scope(st);
_mesa_symbol_table_add_symbol(st, 0, name, NULL);
_mesa_symbol_table_pop_scope(st);
free(name);
_mesa_symbol_table_find_symbol(st, 0, copy);
With this change, the symbol table keeps a local copy of the name that
has the same life time as the symbol_header for that name. This
resolves some use-after-free errors with built-in functions in the
GLSL compiler.
-rw-r--r-- | src/mesa/program/symbol_table.c | 7 |
1 files changed, 4 insertions, 3 deletions
diff --git a/src/mesa/program/symbol_table.c b/src/mesa/program/symbol_table.c index 3fea5ee1f1f..09e7cb44ef3 100644 --- a/src/mesa/program/symbol_table.c +++ b/src/mesa/program/symbol_table.c @@ -75,7 +75,7 @@ struct symbol_header { struct symbol_header *next; /** Symbol name. */ - const char *name; + char *name; /** Linked list of symbols with the same name. */ struct symbol *symbols; @@ -337,9 +337,9 @@ _mesa_symbol_table_add_symbol(struct _mesa_symbol_table *table, if (hdr == NULL) { hdr = calloc(1, sizeof(*hdr)); - hdr->name = name; + hdr->name = strdup(name); - hash_table_insert(table->ht, hdr, name); + hash_table_insert(table->ht, hdr, hdr->name); hdr->next = table->hdr; table->hdr = hdr; } @@ -404,6 +404,7 @@ _mesa_symbol_table_dtor(struct _mesa_symbol_table *table) for (hdr = table->hdr; hdr != NULL; hdr = next) { next = hdr->next; + free(hdr->name); free(hdr); } |