From bdab1296a563277ea89b948f487303a1bdfbc656 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 5 Nov 2015 11:57:51 +0530 Subject: [PATCH] Tag mapper: Prevent cycles in the replacement rules from causing the tag mapper to hang --- src/calibre/ebooks/metadata/tag_mapper.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/calibre/ebooks/metadata/tag_mapper.py b/src/calibre/ebooks/metadata/tag_mapper.py index f7b20ce6d9..aa08a0674f 100644 --- a/src/calibre/ebooks/metadata/tag_mapper.py +++ b/src/calibre/ebooks/metadata/tag_mapper.py @@ -36,8 +36,10 @@ def apply_rules(tag, rules): ans = [] tags = deque() tags.append(tag) - while tags: + maxiter = 20 + while tags and maxiter > 0: tag = tags.popleft() + maxiter -= 1 for rule, matches in rules: ltag = icu_lower(tag) if matches(ltag): @@ -98,3 +100,10 @@ def test(): {'action':'remove', 'query':'t2', 'match_type':'one_of'}, ] assert map_tags(['t1', 'x1'], rules) == ['t3', 'x1'] + rules = [{'action':'replace', 'query':'t1', 'match_type':'one_of', 'replace':'t1'}] + assert map_tags(['t1', 'x1'], rules) == ['t1', 'x1'] + rules = [ + {'action':'replace', 'query':'t1', 'match_type':'one_of', 'replace':'t2'}, + {'action':'replace', 'query':'t2', 'match_type':'one_of', 'replace':'t1'}, + ] + assert set(map_tags(['t1', 't2'], rules)) == {'t1', 't2'}