From: Fabian Maurer dark.shadow4@web.de
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=55115 --- tools/widl/typegen.c | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-)
diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index b3373ded11d..a45474159b2 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -747,8 +747,22 @@ static int type_has_pointers(const type_t *type) }
static int type_has_full_pointer(const type_t *type, const attr_list_t *attrs, - int toplevel_param) + int toplevel_param, int visited_structs_pos) { + static type_t **visited_structs; + static int visited_structs_count; + + if (!visited_structs) + { + visited_structs_count = 100; + visited_structs = xmalloc(sizeof (type_t*) * visited_structs_count); + } + + if (visited_structs_pos >= visited_structs_count) + { + visited_structs_count *= 2; + visited_structs = xrealloc(visited_structs, sizeof (type_t*) * visited_structs_count); + } switch (typegen_detect_type(type, NULL, TDT_IGNORE_STRINGS)) { case TGT_USER_TYPE: @@ -762,14 +776,26 @@ static int type_has_full_pointer(const type_t *type, const attr_list_t *attrs, if (get_pointer_fc(type, attrs, toplevel_param) == FC_FP) return TRUE; else - return type_has_full_pointer(type_array_get_element_type(type), NULL, FALSE); + return type_has_full_pointer(type_array_get_element_type(type), NULL, FALSE, visited_structs_pos); case TGT_STRUCT: { + int i; var_list_t *fields = type_struct_get_fields(type); const var_t *field; + + visited_structs[visited_structs_pos] = type; + for (i = 0; i < visited_structs_pos; i++) + { + if (visited_structs[i] == type) + { + /* Found struct we visted already, abort to prevent infinite loop */ + return FALSE; + } + } + if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) { - if (type_has_full_pointer(field->declspec.type, field->attrs, FALSE)) + if (type_has_full_pointer(field->declspec.type, field->attrs, FALSE, visited_structs_pos + 1)) return TRUE; } break; @@ -781,7 +807,7 @@ static int type_has_full_pointer(const type_t *type, const attr_list_t *attrs, fields = type_union_get_cases(type); if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) { - if (field->declspec.type && type_has_full_pointer(field->declspec.type, field->attrs, FALSE)) + if (field->declspec.type && type_has_full_pointer(field->declspec.type, field->attrs, FALSE, visited_structs_pos)) return TRUE; } break; @@ -2082,12 +2108,12 @@ static unsigned int type_buffer_alignment(const type_t *t) int is_full_pointer_function(const var_t *func) { const var_t *var; - if (type_has_full_pointer(type_function_get_rettype(func->declspec.type), func->attrs, TRUE)) + if (type_has_full_pointer(type_function_get_rettype(func->declspec.type), func->attrs, TRUE, 0)) return TRUE; if (!type_function_get_args(func->declspec.type)) return FALSE; LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), const var_t, entry ) - if (type_has_full_pointer( var->declspec.type, var->attrs, TRUE )) + if (type_has_full_pointer( var->declspec.type, var->attrs, TRUE, 0 )) return TRUE; return FALSE; }