diff options
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | plugins/pychrysa/arch/vmpa.c | 31 | ||||
-rw-r--r-- | src/arch/vmpa.c | 52 | ||||
-rw-r--r-- | src/arch/vmpa.h | 3 | ||||
-rwxr-xr-x | tests/arch/vmpa.py | 26 |
5 files changed, 108 insertions, 18 deletions
@@ -1,3 +1,17 @@ +17-12-08 Cyrille Bagard <nocbos@gmail.com> + + * plugins/pychrysa/arch/vmpa.c: + Update the comparison features for the Python bindings. + + * src/arch/vmpa.c: + Improve the way vmpa_t types are compared. + + * src/arch/vmpa.h: + Remove an useless macro. + + * tests/arch/vmpa.py: + Populate the test suite. + 17-12-07 Cyrille Bagard <nocbos@gmail.com> * plugins/pychrysa/analysis/routine.c: diff --git a/plugins/pychrysa/arch/vmpa.c b/plugins/pychrysa/arch/vmpa.c index af1557d..aaaede8 100644 --- a/plugins/pychrysa/arch/vmpa.c +++ b/plugins/pychrysa/arch/vmpa.c @@ -25,9 +25,13 @@ #include "vmpa.h" +#include <assert.h> #include <string.h> +#include <i18n.h> + + #include "../helpers.h" @@ -208,23 +212,43 @@ static PyObject *py_vmpa_richcompare(PyObject *a, PyObject *b, int op) PyObject *result; /* Bilan à retourner */ vmpa2t *addr_a; /* Première adresse à traiter */ vmpa2t addr_b; /* Seconde adresse à traiter */ + int comp; /* Résultat d'une comparaison */ addr_a = &((py_vmpa_t *)a)->addr; if (!convert_pyobj_to_vmpa(b, &addr_b)) return NULL; + comp = cmp_vmpa(addr_a, &addr_b); + switch (op) { + case Py_LT: + result = comp < 0 ? Py_True : Py_False; + break; + + case Py_LE: + result = comp <= 0 ? Py_True : Py_False; + break; + case Py_EQ: - result = are_equal(addr_a, &addr_b) ? Py_True : Py_False; + result = comp == 0 ? Py_True : Py_False; break; case Py_NE: - result = are_equal(addr_a, &addr_b) ? Py_False : Py_True; + result = comp != 0 ? Py_True : Py_False; + break; + + case Py_GT: + result = comp > 0 ? Py_True : Py_False; + break; + + case Py_GE: + result = comp >= 0 ? Py_True : Py_False; break; default: + assert(false); result = Py_NotImplemented; break; @@ -436,7 +460,10 @@ static bool convert_pyobj_to_vmpa(PyObject *obj, vmpa2t *addr) value = PyLong_AsLongLongAndOverflow(obj, &overflow); if (value == -1 && (overflow == 1 || PyErr_Occurred())) + { PyErr_Clear(); + PyErr_SetString(PyExc_TypeError, _("Unable to cast object as VMPA.")); + } else { diff --git a/src/arch/vmpa.c b/src/arch/vmpa.c index 6db62cc..f90ab22 100644 --- a/src/arch/vmpa.c +++ b/src/arch/vmpa.c @@ -193,8 +193,8 @@ int cmp_vmpa_by_phy(const vmpa2t *a, const vmpa2t *b) else { if (a->physical == VMPA_NO_PHYSICAL && b->physical == VMPA_NO_PHYSICAL) result = 0; - else if (a->physical == VMPA_NO_PHYSICAL) result = -1; - else result = 1; + else if (a->physical == VMPA_NO_PHYSICAL) result = 1; + else result = -1; } return result; @@ -228,8 +228,8 @@ int cmp_vmpa_by_virt(const vmpa2t *a, const vmpa2t *b) else { if (a->virtual == VMPA_NO_VIRTUAL && b->virtual == VMPA_NO_VIRTUAL) result = 0; - else if (a->virtual == VMPA_NO_VIRTUAL) result = -1; - else result = 1; + else if (a->virtual == VMPA_NO_VIRTUAL) result = 1; + else result = -1; } return result; @@ -253,22 +253,48 @@ int cmp_vmpa_by_virt(const vmpa2t *a, const vmpa2t *b) int cmp_vmpa(const vmpa2t *a, const vmpa2t *b) { int result; /* Bilan à retourner */ - bool half; /* Comparaison débutée */ + bool compared; /* Comparaison effectuée */ - result = -1; + if (a->physical == VMPA_NO_PHYSICAL && a->virtual == VMPA_NO_VIRTUAL + && b->physical == VMPA_NO_PHYSICAL && b->virtual == VMPA_NO_VIRTUAL) + { + result = 0; - half = false; + } - if (a->physical != VMPA_NO_PHYSICAL && b->physical != VMPA_NO_PHYSICAL) + else if (a->physical == VMPA_NO_PHYSICAL && a->virtual == VMPA_NO_VIRTUAL) { - result = cmp_vmpa_by_phy(a, b); - half = true; + result = 1; + } - if (a->virtual != VMPA_NO_VIRTUAL && b->virtual != VMPA_NO_VIRTUAL - && (!half || (half && result == 0))) + else if (b->physical == VMPA_NO_PHYSICAL && b->virtual == VMPA_NO_VIRTUAL) + { + result = -1; + + } + + else { - result = cmp_vmpa_by_virt(a, b); + compared = false; + + if (a->physical != VMPA_NO_PHYSICAL && b->physical != VMPA_NO_PHYSICAL) + { + result = cmp_vmpa_by_phy(a, b); + compared = true; + } + + if (a->virtual != VMPA_NO_VIRTUAL && b->virtual != VMPA_NO_VIRTUAL + && (!compared || (compared && result == 0))) + { + result = cmp_vmpa_by_virt(a, b); + compared = true; + } + + /* Cas particulier : les deux éléments n'ont aucun champ défini en commun ! */ + if (!compared) + result = cmp_vmpa_by_phy(a, b); + } return result; diff --git a/src/arch/vmpa.h b/src/arch/vmpa.h index 871e282..6ed7605 100644 --- a/src/arch/vmpa.h +++ b/src/arch/vmpa.h @@ -99,9 +99,6 @@ int cmp_vmpa_by_virt(const vmpa2t *, const vmpa2t *); /* Compare deux localisations selon leurs parties définies. */ int cmp_vmpa(const vmpa2t *, const vmpa2t *); -#define are_equal(a, b) \ - (cmp_vmpa_by_phy(a, b) == 0 && cmp_vmpa_by_virt(a, b) == 0) - #define get_phy_addr(a) (a)->physical #define get_virt_addr(a) (a)->virtual diff --git a/tests/arch/vmpa.py b/tests/arch/vmpa.py index def61ea..09c3d9d 100755 --- a/tests/arch/vmpa.py +++ b/tests/arch/vmpa.py @@ -33,3 +33,29 @@ class TestVmpa(ChrysalideTestCase): self.assertEqual(a, b) self.assertEqual(a, c) + + + def testCompareWrong(self): + """Verify unhandled comparisons with VMPA.""" + + a = vmpa() + + with self.assertRaisesRegex(Exception, 'Unable to cast object as VMPA.'): + + self.assertLess(a, 'b') + + + def testCompareFair(self): + """Verify right VMPA comparisons.""" + + a = vmpa(0) + b = vmpa() + + self.assertLess(a, b) + + self.assertGreater(b, a) + + a = vmpa() + b = vmpa() + + self.assertEqual(a, b) |