summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2017-12-08 20:47:09 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2017-12-08 20:47:09 (GMT)
commitcf11fcf862b98ef57935bcfccd6f2f6ae3f925f6 (patch)
treed7ae9d965b8eea03adfaf7a4d42907aae683d0f9
parent48ac5e6e8fe50c1ff4b9e77440a6365f8b01021f (diff)
Improved the way vmpa_t types are compared.
-rw-r--r--ChangeLog14
-rw-r--r--plugins/pychrysa/arch/vmpa.c31
-rw-r--r--src/arch/vmpa.c52
-rw-r--r--src/arch/vmpa.h3
-rwxr-xr-xtests/arch/vmpa.py26
5 files changed, 108 insertions, 18 deletions
diff --git a/ChangeLog b/ChangeLog
index 47c0570..7cc6a93 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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)