From 675058768ad167e84f9ec02dc21a357cb1fab047 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?= <grubba@grubba.org> Date: Mon, 23 Jun 2014 16:28:44 +0200 Subject: [PATCH] Compiler: Improved cycle detection in implements() and is_compatible(). Under some circumstances the new cache entries could be overwritten before the functions had completed, leading to infinite recursion. Fixes [InfoKOM 775534]. --- src/program.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/program.c b/src/program.c index 95e65e3be6..f62216bf7e 100644 --- a/src/program.c +++ b/src/program.c @@ -11697,8 +11697,14 @@ int find_child(struct program *parent, struct program *child) /* returns 1 if a implements b */ static int low_implements(struct program *a, struct program *b) { + DECLARE_CYCLIC(); int e; + int ret = 1; struct pike_string *s=findstring("__INIT"); + + if (BEGIN_CYCLIC(a, b)) return 1; /* Tentatively ok, */ + SET_CYCLIC_RET(1); + for(e=0;e<b->num_identifier_references;e++) { struct identifier *bid; @@ -11714,7 +11720,8 @@ static int low_implements(struct program *a, struct program *b) #if 0 fprintf(stderr, "Missing identifier \"%s\"\n", bid->name->str); #endif /* 0 */ - return 0; + ret = 0; + break; } if (!pike_types_le(bid->type, ID_FROM_INT(a, i)->type)) { @@ -11723,7 +11730,8 @@ static int low_implements(struct program *a, struct program *b) fprintf(stderr, "Identifier \"%s\" is incompatible.\n", bid->name->str); #endif /* 0 */ - return 0; + ret = 0; + break; } else { #if 0 fprintf(stderr, "Identifier \"%s\" is not strictly compatible.\n", @@ -11732,7 +11740,9 @@ static int low_implements(struct program *a, struct program *b) } } } - return 1; + + END_CYCLIC(); + return ret; } #define IMPLEMENTS_CACHE_SIZE 1024 @@ -11770,9 +11780,14 @@ PMOD_EXPORT int implements(struct program *a, struct program *b) /* Returns 1 if a is compatible with b */ static int low_is_compatible(struct program *a, struct program *b) { + DECLARE_CYCLIC(); int e; + int ret = 1; struct pike_string *s=findstring("__INIT"); + if (BEGIN_CYCLIC(a, b)) return 1; + SET_CYCLIC_RET(1); + /* Optimize the loop somewhat */ if (a->num_identifier_references < b->num_identifier_references) { struct program *tmp = a; @@ -11804,10 +11819,13 @@ static int low_is_compatible(struct program *a, struct program *b) fprintf(stderr, "Identifier \"%s\" is incompatible.\n", bid->name->str); #endif /* 0 */ - return 0; + ret = 0; + break; } } - return 1; + + END_CYCLIC(); + return ret; } static struct implements_cache_s is_compatible_cache[IMPLEMENTS_CACHE_SIZE]; -- GitLab