summaryrefslogtreecommitdiff
path: root/src/mesa/shader/program_parse.tab.c
diff options
context:
space:
mode:
authorIan Romanick <ian.d.romanick@intel.com>2009-10-27 13:40:18 -0700
committerIan Romanick <ian.d.romanick@intel.com>2009-10-27 17:06:18 -0700
commit93dae6761bc90bbd43b450d2673620ec189b2c7a (patch)
tree034b2c8d4c50ecf5e96e9b8c255421e487c90b88 /src/mesa/shader/program_parse.tab.c
parent8df9587d68752f3369cc1eda1606d3b7c1041ec6 (diff)
ARB prog parser: Fix epic memory leak in lexer / parser interface
Anything that matched IDENTIFIER was strdup'ed and returned to the parser. However, almost every case of IDENTIFIER in the parser just dropped the returned string on the floor. Every swizzle string, every option string, every use of a variable, etc. leaked memory. Create a temporary buffer in the parser state (string_dumpster and dumpster_size). Return strings from the lexer to the parser in the buffer. Grow the buffer as needed. When the parser needs to keep a string (i.e., delcaring a new variable), let it make a copy then. The only leak that valgrind now detects is /occasionally/ the copy of the program string in gl_program::String is leaked. I'm not seeing how. :(
Diffstat (limited to 'src/mesa/shader/program_parse.tab.c')
-rw-r--r--src/mesa/shader/program_parse.tab.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/src/mesa/shader/program_parse.tab.c b/src/mesa/shader/program_parse.tab.c
index c255e912ed..261b605a2d 100644
--- a/src/mesa/shader/program_parse.tab.c
+++ b/src/mesa/shader/program_parse.tab.c
@@ -4565,7 +4565,7 @@ yyreduce:
"undefined variable binding in ALIAS statement");
YYERROR;
} else {
- _mesa_symbol_table_add_symbol(state->st, 0, (yyvsp[(2) - (4)].string), target);
+ _mesa_symbol_table_add_symbol(state->st, 0, strdup((yyvsp[(2) - (4)].string)), target);
}
;}
break;
@@ -4896,10 +4896,14 @@ declare_variable(struct asm_parser_state *state, char *name, enum asm_type t,
if (exist != NULL) {
yyerror(locp, state, "redeclared identifier");
} else {
- s = calloc(1, sizeof(struct asm_symbol));
- s->name = name;
+ const size_t name_len = strlen(name);
+
+ s = calloc(1, sizeof(struct asm_symbol) + name_len + 1);
+ s->name = (char *)(s + 1);
s->type = t;
+ memcpy((char *) s->name, name, name_len + 1);
+
switch (t) {
case at_temp:
if (state->prog->NumTemporaries >= state->limits->MaxTemps) {
@@ -5147,6 +5151,11 @@ _mesa_parse_arb_program(GLcontext *ctx, GLenum target, const GLubyte *str,
_mesa_memcpy (strz, str, len);
strz[len] = '\0';
+ if (state->prog->String != NULL) {
+ _mesa_free(state->prog->String);
+ state->prog->String = NULL;
+ }
+
state->prog->String = strz;
state->st = _mesa_symbol_table_ctor();
@@ -5236,7 +5245,6 @@ error:
for (sym = state->sym; sym != NULL; sym = temp) {
temp = sym->next;
- _mesa_free((void *) sym->name);
_mesa_free(sym);
}
state->sym = NULL;
@@ -5244,6 +5252,11 @@ error:
_mesa_symbol_table_dtor(state->st);
state->st = NULL;
+ if (state->string_dumpster != NULL) {
+ _mesa_free(state->string_dumpster);
+ state->dumpster_size = 0;
+ }
+
return result;
}