Skip to content

Commit 2f69645

Browse files
committed
Fix broken list-munging in ecpg's remove_variables().
The loops over cursor argument variables neglected to ever advance "prevvar". The code would accidentally do the right thing anyway when removing the first or second list entry, but if it had to remove the third or later entry then it would also remove all entries between there and the first entry. AFAICS this would only matter for cursors that reference out-of-scope variables, which is a weird Informix compatibility hack; between that and the lack of impact for short lists, it's not so surprising that nobody has complained. Nonetheless it's a pretty obvious bug. It would have been more obvious if these loops used a more standard coding style for chasing the linked lists --- this business with the "prev" pointer sometimes pointing at the current list entry is confusing and overcomplicated. So rather than just add a minimal band-aid, I chose to rewrite the loops in the same style we use elsewhere, where the "prev" pointer is NULL until we are dealing with a non-first entry and we save the "next" pointer at the top of the loop. (Two of the four loops touched here are not actually buggy, but it seems better to make them all look alike.) Coverity discovered this problem, but not until 2b41de4 added code to free no-longer-needed arguments structs. With that, the incorrect link updates are possibly touching freed memory, and it complained about that. Nonetheless the list corruption hazard is ancient, so back-patch to all supported branches.
1 parent e032e4c commit 2f69645

File tree

1 file changed

+29
-33
lines changed

1 file changed

+29
-33
lines changed

src/interfaces/ecpg/preproc/variable.c

+29-33
Original file line numberDiff line numberDiff line change
@@ -264,17 +264,19 @@ void
264264
remove_typedefs(int brace_level)
265265
{
266266
struct typedefs *p,
267-
*prev;
267+
*prev,
268+
*next;
268269

269-
for (p = prev = types; p;)
270+
for (p = types, prev = NULL; p; p = next)
270271
{
272+
next = p->next;
271273
if (p->brace_level >= brace_level)
272274
{
273275
/* remove it */
274-
if (p == types)
275-
prev = types = p->next;
276+
if (prev)
277+
prev->next = next;
276278
else
277-
prev->next = p->next;
279+
types = next;
278280

279281
if (p->type->type_enum == ECPGt_struct || p->type->type_enum == ECPGt_union)
280282
ECPGfree_struct_member(p->struct_member_list);
@@ -286,30 +288,25 @@ remove_typedefs(int brace_level)
286288
free(p->type);
287289
free(p->name);
288290
free(p);
289-
if (prev == types)
290-
p = types;
291-
else
292-
p = prev ? prev->next : NULL;
293291
}
294292
else
295-
{
296293
prev = p;
297-
p = prev->next;
298-
}
299294
}
300295
}
301296

302297
void
303298
remove_variables(int brace_level)
304299
{
305300
struct variable *p,
306-
*prev;
301+
*prev,
302+
*next;
307303

308-
for (p = prev = allvariables; p;)
304+
for (p = allvariables, prev = NULL; p; p = next)
309305
{
306+
next = p->next;
310307
if (p->brace_level >= brace_level)
311308
{
312-
/* is it still referenced by a cursor? */
309+
/* remove it, but first remove any references from cursors */
313310
struct cursor *ptr;
314311

315312
for (ptr = cur; ptr != NULL; ptr = ptr->next)
@@ -318,53 +315,52 @@ remove_variables(int brace_level)
318315
*prevvar,
319316
*nextvar;
320317

321-
for (varptr = prevvar = ptr->argsinsert; varptr != NULL; varptr = nextvar)
318+
for (varptr = ptr->argsinsert, prevvar = NULL;
319+
varptr != NULL; varptr = nextvar)
322320
{
323321
nextvar = varptr->next;
324322
if (p == varptr->variable)
325323
{
326324
/* remove from list */
327-
if (varptr == ptr->argsinsert)
328-
ptr->argsinsert = varptr->next;
325+
if (prevvar)
326+
prevvar->next = nextvar;
329327
else
330-
prevvar->next = varptr->next;
328+
ptr->argsinsert = nextvar;
331329
free(varptr);
332330
}
331+
else
332+
prevvar = varptr;
333333
}
334-
for (varptr = prevvar = ptr->argsresult; varptr != NULL; varptr = nextvar)
334+
for (varptr = ptr->argsresult, prevvar = NULL;
335+
varptr != NULL; varptr = nextvar)
335336
{
336337
nextvar = varptr->next;
337338
if (p == varptr->variable)
338339
{
339340
/* remove from list */
340-
if (varptr == ptr->argsresult)
341-
ptr->argsresult = varptr->next;
341+
if (prevvar)
342+
prevvar->next = nextvar;
342343
else
343-
prevvar->next = varptr->next;
344+
ptr->argsresult = nextvar;
344345
free(varptr);
345346
}
347+
else
348+
prevvar = varptr;
346349
}
347350
}
348351

349352
/* remove it */
350-
if (p == allvariables)
351-
prev = allvariables = p->next;
353+
if (prev)
354+
prev->next = next;
352355
else
353-
prev->next = p->next;
356+
allvariables = next;
354357

355358
ECPGfree_type(p->type);
356359
free(p->name);
357360
free(p);
358-
if (prev == allvariables)
359-
p = allvariables;
360-
else
361-
p = prev ? prev->next : NULL;
362361
}
363362
else
364-
{
365363
prev = p;
366-
p = prev->next;
367-
}
368364
}
369365
}
370366

0 commit comments

Comments
 (0)