Skip to content

Commit 52c7a44

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 fa92c18 commit 52c7a44

File tree

1 file changed

+33
-34
lines changed

1 file changed

+33
-34
lines changed

src/interfaces/ecpg/preproc/variable.c

+33-34
Original file line numberDiff line numberDiff line change
@@ -260,97 +260,96 @@ void
260260
remove_typedefs(int brace_level)
261261
{
262262
struct typedefs *p,
263-
*prev;
263+
*prev,
264+
*next;
264265

265-
for (p = prev = types; p;)
266+
for (p = types, prev = NULL; p; p = next)
266267
{
268+
next = p->next;
267269
if (p->brace_level >= brace_level)
268270
{
269271
/* remove it */
270-
if (p == types)
271-
prev = types = p->next;
272+
if (prev)
273+
prev->next = next;
272274
else
273-
prev->next = p->next;
275+
types = next;
274276

275277
if (p->type->type_enum == ECPGt_struct || p->type->type_enum == ECPGt_union)
276278
free(p->struct_member_list);
277279
free(p->type);
278280
free(p->name);
279281
free(p);
280-
if (prev == types)
281-
p = types;
282-
else
283-
p = prev ? prev->next : NULL;
284282
}
285283
else
286-
{
287284
prev = p;
288-
p = prev->next;
289-
}
290285
}
291286
}
292287

293288
void
294289
remove_variables(int brace_level)
295290
{
296291
struct variable *p,
297-
*prev;
292+
*prev,
293+
*next;
298294

299-
for (p = prev = allvariables; p;)
295+
for (p = allvariables, prev = NULL; p; p = next)
300296
{
297+
next = p->next;
301298
if (p->brace_level >= brace_level)
302299
{
303-
/* is it still referenced by a cursor? */
300+
/* remove it, but first remove any references from cursors */
304301
struct cursor *ptr;
305302

306303
for (ptr = cur; ptr != NULL; ptr = ptr->next)
307304
{
308305
struct arguments *varptr,
309-
*prevvar;
306+
*prevvar,
307+
*nextvar;
310308

311-
for (varptr = prevvar = ptr->argsinsert; varptr != NULL; varptr = varptr->next)
309+
for (varptr = ptr->argsinsert, prevvar = NULL;
310+
varptr != NULL; varptr = nextvar)
312311
{
312+
nextvar = varptr->next;
313313
if (p == varptr->variable)
314314
{
315315
/* remove from list */
316-
if (varptr == ptr->argsinsert)
317-
ptr->argsinsert = varptr->next;
316+
if (prevvar)
317+
prevvar->next = nextvar;
318318
else
319-
prevvar->next = varptr->next;
319+
ptr->argsinsert = nextvar;
320320
}
321+
else
322+
prevvar = varptr;
321323
}
322-
for (varptr = prevvar = ptr->argsresult; varptr != NULL; varptr = varptr->next)
324+
for (varptr = ptr->argsresult, prevvar = NULL;
325+
varptr != NULL; varptr = nextvar)
323326
{
327+
nextvar = varptr->next;
324328
if (p == varptr->variable)
325329
{
326330
/* remove from list */
327-
if (varptr == ptr->argsresult)
328-
ptr->argsresult = varptr->next;
331+
if (prevvar)
332+
prevvar->next = nextvar;
329333
else
330-
prevvar->next = varptr->next;
334+
ptr->argsresult = nextvar;
331335
}
336+
else
337+
prevvar = varptr;
332338
}
333339
}
334340

335341
/* remove it */
336-
if (p == allvariables)
337-
prev = allvariables = p->next;
342+
if (prev)
343+
prev->next = next;
338344
else
339-
prev->next = p->next;
345+
allvariables = next;
340346

341347
ECPGfree_type(p->type);
342348
free(p->name);
343349
free(p);
344-
if (prev == allvariables)
345-
p = allvariables;
346-
else
347-
p = prev ? prev->next : NULL;
348350
}
349351
else
350-
{
351352
prev = p;
352-
p = prev->next;
353-
}
354353
}
355354
}
356355

0 commit comments

Comments
 (0)