Protect against crash in the `relation_possible` predicate with ambiguous relations. stable
authorFlorent Cayre <florent.cayre@logilab.fr>
Mon, 15 Jul 2013 10:40:49 +0200
branchstable
changeset 9152 b0155bfd4e17
parent 9011 810a05fba1a4
child 9153 bc1b8e77d6ce
Protect against crash in the `relation_possible` predicate with ambiguous relations. It was still possible to get a KeyError when using relations that are ambiguous at both ends, like (Executable, version_of, Program) & (Version, version_of, Project). Closes #3010148.
predicates.py
test/unittest_predicates.py
--- a/predicates.py	Fri Jun 14 16:02:39 2013 +0200
+++ b/predicates.py	Mon Jul 15 10:40:49 2013 +0200
@@ -994,7 +994,11 @@
             return 0 # relation not supported
         if self.action:
             if self.target_etype is not None:
-                rschema = rschema.role_rdef(entity.e_schema, self.target_etype, self.role)
+                try:
+                    rschema = rschema.role_rdef(entity.e_schema,
+                                                self.target_etype, self.role)
+                except KeyError:
+                    return 0
             if self.role == 'subject':
                 if not rschema.has_perm(entity._cw, self.action, fromeid=entity.eid):
                     return 0
--- a/test/unittest_predicates.py	Fri Jun 14 16:02:39 2013 +0200
+++ b/test/unittest_predicates.py	Mon Jul 15 10:40:49 2013 +0200
@@ -203,6 +203,17 @@
                          select=select, filtered_variable=select.defined_vars['X'])
         self.assertEqual(score, 1)
 
+    def test_ambiguous(self):
+        # Ambiguous relations are :
+        # (Service, fabrique_par, Personne) and (Produit, fabrique_par, Usine)
+        # There used to be a crash here with a bad rdef choice in the strict
+        # checking case.
+        selector = relation_possible('fabrique_par', role='object',
+                                     target_etype='Personne', strict=True)
+        req = self.request()
+        usine = req.create_entity('Usine', lieu=u'here')
+        score = selector(None, req, rset=usine.as_rset())
+        self.assertEqual(0, score)
 
 class MatchUserGroupsTC(CubicWebTC):
     def test_owners_group(self):