Skip to content

Commit 0e60607

Browse files
committed
ecpg: fix some memory leakage of data-type-related structures.
ECPGfree_type() and related functions were quite incomplete about removing subsidiary data structures. Possibly this is because ecpg wasn't careful to make sure said data structures always had their own storage. Previous patches in this series cleaned up a lot of that, and I had to add a couple more mm_strdup's here. Also, ecpg.trailer tended to overwrite struct_member_list[struct_level] without bothering to free up its previous contents, thus potentially leaking a lot of struct-member-related storage. Add ECPGfree_struct_member() calls at appropriate points. Discussion: https://postgr.es/m/2011420.1713493114@sss.pgh.pa.us
1 parent 5c32c21 commit 0e60607

File tree

5 files changed

+42
-13
lines changed

5 files changed

+42
-13
lines changed

src/interfaces/ecpg/preproc/ecpg.header

+15-2
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,19 @@ static char *actual_startline[STRUCT_DEPTH];
4444
static int varchar_counter = 1;
4545
static int bytea_counter = 1;
4646

47-
/* temporarily store struct members while creating the data structure */
47+
/*
48+
* We temporarily store struct members here while parsing struct declarations.
49+
* The struct_member_list (at a given nesting depth) is constructed while
50+
* scanning the fields within "struct { .... }", but we can't remove it upon
51+
* seeing the right brace. It's kept around and copied into the variables
52+
* or typedefs that follow, in order to handle cases like
53+
* "struct foo { ... } foovar1, foovar2;". We recycle the storage only
54+
* upon closing the current nesting level or starting the next struct
55+
* declaration within the same nesting level.
56+
* For cases like "struct foo foovar1, foovar2;", we copy the saved struct
57+
* field list for the typedef or struct tag into the struct_member_list
58+
* global variable, and then copy it again to the newly-declared variables.
59+
*/
4860
struct ECPGstruct_member *struct_member_list[STRUCT_DEPTH] = {NULL};
4961

5062
/* also store struct type so we can do a sizeof() later */
@@ -507,11 +519,12 @@ add_typedef(const char *name, const char *dimension, const char *length,
507519
this->name = mm_strdup(name);
508520
this->brace_level = braces_open;
509521
this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
522+
this->type->type_storage = NULL;
510523
this->type->type_enum = type_enum;
511524
this->type->type_str = mm_strdup(name);
512525
this->type->type_dimension = mm_strdup(dimension); /* dimension of array */
513526
this->type->type_index = mm_strdup(length); /* length of string */
514-
this->type->type_sizeof = ECPGstruct_sizeof;
527+
this->type->type_sizeof = ECPGstruct_sizeof ? mm_strdup(ECPGstruct_sizeof) : NULL;
515528
this->struct_member_list = (type_enum == ECPGt_struct || type_enum == ECPGt_union) ?
516529
ECPGstruct_member_dup(struct_member_list[struct_level]) : NULL;
517530

src/interfaces/ecpg/preproc/ecpg.trailer

+9-2
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,7 @@ var_type: simple_type
755755
else
756756
$$.type_sizeof = cat_str(3, "sizeof(", this->name, ")");
757757

758+
ECPGfree_struct_member(struct_member_list[struct_level]);
758759
struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
759760
}
760761
}
@@ -882,6 +883,7 @@ var_type: simple_type
882883
else
883884
$$.type_sizeof = cat_str(3, "sizeof(", this->name, ")");
884885

886+
ECPGfree_struct_member(struct_member_list[struct_level]);
885887
struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
886888
}
887889
}
@@ -904,6 +906,7 @@ var_type: simple_type
904906
$$.type_dimension = this->type->type_dimension;
905907
$$.type_index = this->type->type_index;
906908
$$.type_sizeof = this->type->type_sizeof;
909+
ECPGfree_struct_member(struct_member_list[struct_level]);
907910
struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
908911
}
909912
else
@@ -913,6 +916,7 @@ var_type: simple_type
913916
$$.type_dimension = "-1";
914917
$$.type_index = "-1";
915918
$$.type_sizeof = "";
919+
ECPGfree_struct_member(struct_member_list[struct_level]);
916920
struct_member_list[struct_level] = NULL;
917921
}
918922
}
@@ -928,6 +932,7 @@ enum_definition: '{' c_list '}'
928932

929933
struct_union_type_with_symbol: s_struct_union_symbol
930934
{
935+
ECPGfree_struct_member(struct_member_list[struct_level]);
931936
struct_member_list[struct_level++] = NULL;
932937
if (struct_level >= STRUCT_DEPTH)
933938
mmerror(PARSE_ERROR, ET_ERROR, "too many levels in nested structure/union definition");
@@ -969,12 +974,13 @@ struct_union_type_with_symbol: s_struct_union_symbol
969974
this->name = mm_strdup(su_type.type_str);
970975
this->brace_level = braces_open;
971976
this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
977+
this->type->type_storage = NULL;
972978
this->type->type_enum = su_type.type_enum;
973979
this->type->type_str = mm_strdup(su_type.type_str);
974980
this->type->type_dimension = mm_strdup("-1"); /* dimension of array */
975981
this->type->type_index = mm_strdup("-1"); /* length of string */
976-
this->type->type_sizeof = ECPGstruct_sizeof;
977-
this->struct_member_list = struct_member_list[struct_level];
982+
this->type->type_sizeof = ECPGstruct_sizeof ? mm_strdup(ECPGstruct_sizeof) : NULL;
983+
this->struct_member_list = ECPGstruct_member_dup(struct_member_list[struct_level]);
978984

979985
types = this;
980986
@$ = cat_str(4, su_type.type_str, "{", @4, "}");
@@ -984,6 +990,7 @@ struct_union_type_with_symbol: s_struct_union_symbol
984990
struct_union_type: struct_union_type_with_symbol
985991
| s_struct_union
986992
{
993+
ECPGfree_struct_member(struct_member_list[struct_level]);
987994
struct_member_list[struct_level++] = NULL;
988995
if (struct_level >= STRUCT_DEPTH)
989996
mmerror(PARSE_ERROR, ET_ERROR, "too many levels in nested structure/union definition");

src/interfaces/ecpg/preproc/type.c

+9-6
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,14 @@ ECPGmake_array_type(struct ECPGtype *type, const char *size)
9494
}
9595

9696
struct ECPGtype *
97-
ECPGmake_struct_type(struct ECPGstruct_member *rm, enum ECPGttype type, char *type_name, char *struct_sizeof)
97+
ECPGmake_struct_type(struct ECPGstruct_member *rm, enum ECPGttype type,
98+
const char *type_name, const char *struct_sizeof)
9899
{
99100
struct ECPGtype *ne = ECPGmake_simple_type(type, "1", 0);
100101

101102
ne->type_name = mm_strdup(type_name);
102103
ne->u.members = ECPGstruct_member_dup(rm);
103-
ne->struct_sizeof = struct_sizeof;
104+
ne->struct_sizeof = mm_strdup(struct_sizeof);
104105

105106
return ne;
106107
}
@@ -622,7 +623,7 @@ ECPGfree_struct_member(struct ECPGstruct_member *rm)
622623

623624
rm = rm->next;
624625
free(p->name);
625-
free(p->type);
626+
ECPGfree_type(p->type);
626627
free(p);
627628
}
628629
}
@@ -643,14 +644,13 @@ ECPGfree_type(struct ECPGtype *type)
643644
case ECPGt_struct:
644645
case ECPGt_union:
645646
/* Array of structs. */
646-
ECPGfree_struct_member(type->u.element->u.members);
647-
free(type->u.element);
647+
ECPGfree_type(type->u.element);
648648
break;
649649
default:
650650
if (!IS_SIMPLE_TYPE(type->u.element->type))
651651
base_yyerror("internal error: unknown datatype, please report this to <" PACKAGE_BUGREPORT ">");
652652

653-
free(type->u.element);
653+
ECPGfree_type(type->u.element);
654654
}
655655
break;
656656
case ECPGt_struct:
@@ -662,6 +662,9 @@ ECPGfree_type(struct ECPGtype *type)
662662
break;
663663
}
664664
}
665+
free(type->type_name);
666+
free(type->size);
667+
free(type->struct_sizeof);
665668
free(type);
666669
}
667670

src/interfaces/ecpg/preproc/type.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@ void ECPGmake_struct_member(const char *name, struct ECPGtype *type,
3838
struct ECPGtype *ECPGmake_simple_type(enum ECPGttype type, const char *size, int counter);
3939
struct ECPGtype *ECPGmake_array_type(struct ECPGtype *type, const char *size);
4040
struct ECPGtype *ECPGmake_struct_type(struct ECPGstruct_member *rm,
41-
enum ECPGttype type, char *type_name,
42-
char *struct_sizeof);
41+
enum ECPGttype type,
42+
const char *type_name,
43+
const char *struct_sizeof);
4344
struct ECPGstruct_member *ECPGstruct_member_dup(struct ECPGstruct_member *rm);
4445

4546
/* Frees a type. */

src/interfaces/ecpg/preproc/variable.c

+6-1
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,12 @@ remove_typedefs(int brace_level)
277277
prev->next = p->next;
278278

279279
if (p->type->type_enum == ECPGt_struct || p->type->type_enum == ECPGt_union)
280-
free(p->struct_member_list);
280+
ECPGfree_struct_member(p->struct_member_list);
281+
free(p->type->type_storage);
282+
free(p->type->type_str);
283+
free(p->type->type_dimension);
284+
free(p->type->type_index);
285+
free(p->type->type_sizeof);
281286
free(p->type);
282287
free(p->name);
283288
free(p);

0 commit comments

Comments
 (0)