summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--plugins/pychrysa/analysis/content.c62
-rw-r--r--tests/analysis/contents/restricted.py88
3 files changed, 144 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog
index aa699e0..3424bbf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
17-11-12 Cyrille Bagard <nocbos@gmail.com>
+ * plugins/pychrysa/analysis/content.c:
+ Improve the type of data read from loaded contents.
+
+ * tests/analysis/contents/restricted.py:
+ Update and extend the test suite.
+
+17-11-12 Cyrille Bagard <nocbos@gmail.com>
+
* plugins/pychrysa/analysis/binary.c:
Update the Python API.
diff --git a/plugins/pychrysa/analysis/content.c b/plugins/pychrysa/analysis/content.c
index 5565129..95f88f6 100644
--- a/plugins/pychrysa/analysis/content.c
+++ b/plugins/pychrysa/analysis/content.c
@@ -46,6 +46,9 @@ static PyObject *py_binary_content_get_checksum(PyObject *, PyObject *);
/* Détermine le nombre d'octets lisibles. */
static PyObject *py_binary_content_compute_size(PyObject *, PyObject *);
+/* Fournit une portion des données représentées. */
+static PyObject *py_binary_content_read_raw(PyObject *, PyObject *);
+
/* Lit un nombre non signé sur un octet. */
static PyObject *py_binary_content_read_u8(PyObject *, PyObject *);
@@ -125,6 +128,52 @@ static PyObject *py_binary_content_compute_size(PyObject *self, PyObject *args)
* Paramètres : self = contenu binaire à manipuler. *
* args = non utilisé ici. *
* *
+* Description : Fournit une portion des données représentées. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_binary_content_read_raw(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Instance à retourner */
+ GBinContent *content; /* Version GLib du format */
+ PyObject *addr_obj; /* Objet pour une position */
+ vmpa2t *addr; /* Position interne associée */
+ unsigned long long length; /* Quantité de données à lire */
+ int ret; /* Bilan de lecture des args. */
+ const bin_t *val; /* Valeur lue à faire suivre */
+
+ content = G_BIN_CONTENT(pygobject_get(self));
+ assert(content != NULL);
+
+ ret = PyArg_ParseTuple(args, "OK", &addr_obj, &length);
+ if (!ret) return NULL;
+
+ addr = get_internal_vmpa(addr_obj);
+ assert(addr != NULL);
+
+ val = g_binary_content_get_raw_access(content, addr, length);
+ if (val == NULL)
+ {
+ PyErr_SetString(PyExc_Exception, _("Invalid read access."));
+ return NULL;
+ }
+
+ result = PyBytes_FromStringAndSize((char *)val, length);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = contenu binaire à manipuler. *
+* args = non utilisé ici. *
+* *
* Description : Lit un nombre non signé sur un octet. *
* *
* Retour : Bilan de l'opération. *
@@ -159,7 +208,7 @@ static PyObject *py_binary_content_read_u8(PyObject *self, PyObject *args)
return NULL;
}
- result = PyBytes_FromStringAndSize((char *)&val, 1);
+ result = PyLong_FromUnsignedLong(val);
return result;
@@ -206,7 +255,7 @@ static PyObject *py_binary_content_read_u16(PyObject *self, PyObject *args)
return NULL;
}
- result = PyBytes_FromStringAndSize((char *)&val, 2);
+ result = PyLong_FromUnsignedLong(val);
return result;
@@ -253,7 +302,7 @@ static PyObject *py_binary_content_read_u32(PyObject *self, PyObject *args)
return NULL;
}
- result = PyBytes_FromStringAndSize((char *)&val, 4);
+ result = PyLong_FromUnsignedLong(val);
return result;
@@ -299,7 +348,7 @@ static PyObject *py_binary_content_read_u64(PyObject *self, PyObject *args)
return NULL;
}
- result = PyBytes_FromStringAndSize((char *)&val, 8);
+ result = PyLong_FromUnsignedLongLong(val);
return result;
@@ -332,6 +381,11 @@ PyTypeObject *get_python_binary_content_type(void)
"compute_size($self, /)\n--\n\nCompute the quantity of readable bytes."
},
{
+ "read_raw", py_binary_content_read_raw,
+ METH_VARARGS,
+ "read_raw($self, addr, length, /)\n--\n\nRead bytes from a given position."
+ },
+ {
"read_u8", py_binary_content_read_u8,
METH_VARARGS,
"read_u8($self, addr, /)\n--\n\nRead an unsigned byte from a given position."
diff --git a/tests/analysis/contents/restricted.py b/tests/analysis/contents/restricted.py
index e8d3e07..6484299 100644
--- a/tests/analysis/contents/restricted.py
+++ b/tests/analysis/contents/restricted.py
@@ -58,15 +58,39 @@ class TestRestrictedContent(ChrysalideTestCase):
self.assertIsNotNone(rcnt)
val = rcnt.read_u8(start)
- self.assertEqual(val, b'\x15')
+ self.assertEqual(val, 0x15)
val = rcnt.read_u8(start)
- self.assertEqual(val, b'\x16')
+ self.assertEqual(val, 0x16)
val = rcnt.read_u16(start, vmpa.SRE_LITTLE)
- self.assertEqual(val, b'\x17\x18')
+ self.assertEqual(val, 0x1817)
val = rcnt.read_u32(start, vmpa.SRE_LITTLE)
+ self.assertEqual(val, 0x24232221)
+
+
+ def testReadRawAccess(self):
+ """Check valid raw accesses to restricted content."""
+
+ fcnt = FileContent(self._out.name)
+
+ start = vmpa(12, vmpa.VMPA_NO_VIRTUAL)
+ covered = mrange(start, 12) # 0x15 ... 0x28
+
+ rcnt = RestrictedContent(fcnt, covered)
+ self.assertIsNotNone(rcnt)
+
+ val = rcnt.read_raw(start, 1)
+ self.assertEqual(val, b'\x15')
+
+ val = rcnt.read_raw(start, 1)
+ self.assertEqual(val, b'\x16')
+
+ val = rcnt.read_raw(start, 2)
+ self.assertEqual(val, b'\x17\x18')
+
+ val = rcnt.read_raw(start, 4)
self.assertEqual(val, b'\x21\x22\x23\x24')
@@ -83,34 +107,78 @@ class TestRestrictedContent(ChrysalideTestCase):
start = vmpa(12, vmpa.VMPA_NO_VIRTUAL)
val = rcnt.read_u8(start)
- self.assertEqual(val, b'\x15')
+ self.assertEqual(val, 0x15)
start = vmpa(12, vmpa.VMPA_NO_VIRTUAL)
val = rcnt.read_u16(start, vmpa.SRE_LITTLE)
- self.assertEqual(val, b'\x15\x16')
+ self.assertEqual(val, 0x1615)
start = vmpa(12, vmpa.VMPA_NO_VIRTUAL)
val = rcnt.read_u32(start, vmpa.SRE_LITTLE)
- self.assertEqual(val, b'\x15\x16\x17\x18')
+ self.assertEqual(val, 0x18171615)
start = vmpa(12, vmpa.VMPA_NO_VIRTUAL)
val = rcnt.read_u64(start, vmpa.SRE_LITTLE)
- self.assertEqual(val, b'\x15\x16\x17\x18\x21\x22\x23\x24')
+ self.assertEqual(val, 0x2423222118171615)
start = vmpa(23, vmpa.VMPA_NO_VIRTUAL)
val = rcnt.read_u8(start)
- self.assertEqual(val, b'\x28')
+ self.assertEqual(val, 0x28)
start = vmpa(22, vmpa.VMPA_NO_VIRTUAL)
val = rcnt.read_u16(start, vmpa.SRE_LITTLE)
- self.assertEqual(val, b'\x27\x28')
+ self.assertEqual(val, 0x2827)
start = vmpa(20, vmpa.VMPA_NO_VIRTUAL)
val = rcnt.read_u32(start, vmpa.SRE_LITTLE)
- self.assertEqual(val, b'\x25\x26\x27\x28')
+ self.assertEqual(val, 0x28272625)
start = vmpa(16, vmpa.VMPA_NO_VIRTUAL)
val = rcnt.read_u64(start, vmpa.SRE_LITTLE)
+ self.assertEqual(val, 0x2827262524232221)
+
+
+ def testBorderLineRawAccess(self):
+ """Check valid border line raw accesses to restricted content."""
+
+ fcnt = FileContent(self._out.name)
+
+ start = vmpa(12, vmpa.VMPA_NO_VIRTUAL)
+ covered = mrange(start, 12) # 0x15 ... 0x28
+
+ rcnt = RestrictedContent(fcnt, covered)
+ self.assertIsNotNone(rcnt)
+
+ start = vmpa(12, vmpa.VMPA_NO_VIRTUAL)
+ val = rcnt.read_raw(start, 1)
+ self.assertEqual(val, b'\x15')
+
+ start = vmpa(12, vmpa.VMPA_NO_VIRTUAL)
+ val = rcnt.read_raw(start, 2)
+ self.assertEqual(val, b'\x15\x16')
+
+ start = vmpa(12, vmpa.VMPA_NO_VIRTUAL)
+ val = rcnt.read_raw(start, 4)
+ self.assertEqual(val, b'\x15\x16\x17\x18')
+
+ start = vmpa(12, vmpa.VMPA_NO_VIRTUAL)
+ val = rcnt.read_raw(start, 8)
+ self.assertEqual(val, b'\x15\x16\x17\x18\x21\x22\x23\x24')
+
+ start = vmpa(23, vmpa.VMPA_NO_VIRTUAL)
+ val = rcnt.read_raw(start, 1)
+ self.assertEqual(val, b'\x28')
+
+ start = vmpa(22, vmpa.VMPA_NO_VIRTUAL)
+ val = rcnt.read_raw(start, 2)
+ self.assertEqual(val, b'\x27\x28')
+
+ start = vmpa(20, vmpa.VMPA_NO_VIRTUAL)
+ val = rcnt.read_raw(start, 4)
+ self.assertEqual(val, b'\x25\x26\x27\x28')
+
+ start = vmpa(16, vmpa.VMPA_NO_VIRTUAL)
+ val = rcnt.read_raw(start, 8)
self.assertEqual(val, b'\x21\x22\x23\x24\x25\x26\x27\x28')