about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--miasm/jitter/compat_py23.h88
1 files changed, 79 insertions, 9 deletions
diff --git a/miasm/jitter/compat_py23.h b/miasm/jitter/compat_py23.h
index 60cf8c96..596f14cc 100644
--- a/miasm/jitter/compat_py23.h
+++ b/miasm/jitter/compat_py23.h
@@ -1,14 +1,48 @@
 #ifndef __COMPAT_PY23_H__
 #define __COMPAT_PY23_H__
 
-
-
 #if PY_MAJOR_VERSION >= 3
+#include "bn.h"
 #define PyGetInt_uint_t(size_type, item, value)				\
 	if (PyLong_Check(item)) {					\
-		unsigned long long tmp;					\
-		tmp = PyLong_AsLongLong(item);				\
-		if ( tmp > (size_type) -1) {				\
+		bn_t bn;						\
+		int j;							\
+		PyObject* py_long = item;				\
+		PyObject* py_long_new;					\
+		PyObject* py_tmp;					\
+		PyObject* cst_32;					\
+		PyObject* cst_ffffffff;					\
+		uint64_t tmp;						\
+		cst_ffffffff = PyLong_FromLong(0xffffffff);		\
+		cst_32 = PyLong_FromLong(32);				\
+		bn = bignum_from_int(0);				\
+		int neg = 0;    					\
+									\
+		if (Py_SIZE(py_long) < 0) {				\
+			neg = 1;					\
+			py_long_new = PyObject_CallMethod(py_long, "__neg__", NULL); \
+			Py_DECREF(py_long);				\
+			py_long = py_long_new;				\
+		}							\
+									\
+		for (j = 0; j < BN_BYTE_SIZE; j += 4) {			\
+			py_tmp = PyObject_CallMethod(py_long, "__and__", "O", cst_ffffffff); \
+			py_long_new = PyObject_CallMethod(py_long, "__rshift__", "O", cst_32); \
+			Py_DECREF(py_long);				\
+			py_long = py_long_new;				\
+			tmp = PyLong_AsUnsignedLongLongMask(py_tmp);	\
+			Py_DECREF(py_tmp);				\
+			bn = bignum_or(bn, bignum_lshift(bignum_from_uint64(tmp), 8 * j)); \
+		}							\
+		tmp = bignum_to_uint64(bn);				\
+									\
+		if (neg) {						\
+			if ( tmp > (size_type) -1) {                \
+				RAISE(PyExc_TypeError, "Arg too big for " #size_type ""); \
+			} 						\
+			tmp = (1<<(sizeof(size_type)*8))-tmp; 		\
+		}							\
+		else if ( tmp > (size_type) -1) {                       \
 			RAISE(PyExc_TypeError, "Arg too big for " #size_type ""); \
 		}							\
 		value = (size_type) tmp;				\
@@ -20,11 +54,47 @@
 
 #define PyGetInt_uint_t_retneg(size_type, item, value)			\
 	if (PyLong_Check(item)) {					\
-		unsigned long long tmp;					\
-		tmp = PyLong_AsLongLong(item);				\
-		if ( tmp > (size_type) -1) {				\
+		bn_t bn;						\
+		int j;							\
+		PyObject* py_long = item;				\
+		PyObject* py_long_new;					\
+		PyObject* py_tmp;					\
+		PyObject* cst_32;					\
+		PyObject* cst_ffffffff;					\
+		uint64_t tmp;						\
+		cst_ffffffff = PyLong_FromLong(0xffffffff);		\
+		cst_32 = PyLong_FromLong(32);				\
+		bn = bignum_from_int(0);				\
+		int neg = 0;    					\
+									\
+		if (Py_SIZE(py_long) < 0) {				\
+			neg = 1;					\
+			py_long_new = PyObject_CallMethod(py_long, "__neg__", NULL); \
+			Py_DECREF(py_long);				\
+			py_long = py_long_new;				\
+		}							\
+									\
+		for (j = 0; j < BN_BYTE_SIZE; j += 4) {			\
+			py_tmp = PyObject_CallMethod(py_long, "__and__", "O", cst_ffffffff); \
+			py_long_new = PyObject_CallMethod(py_long, "__rshift__", "O", cst_32); \
+			Py_DECREF(py_long);				\
+			py_long = py_long_new;				\
+			tmp = PyLong_AsUnsignedLongLongMask(py_tmp);	\
+			Py_DECREF(py_tmp);				\
+			bn = bignum_or(bn, bignum_lshift(bignum_from_uint64(tmp), 8 * j)); \
+		}							\
+		tmp = bignum_to_uint64(bn);				\
+									\
+		if (neg) {						\
+			if ( tmp > (size_type) -1) {                \
+				PyErr_SetString(PyExc_TypeError, "Arg too big for " #size_type ""); \
+				return -1; 				\
+			} 						\
+			tmp = (1<<(sizeof(size_type)*8))-tmp; 		\
+		}							\
+		else if ( tmp > (size_type) -1) {                       \
 			PyErr_SetString(PyExc_TypeError, "Arg too big for " #size_type ""); \
-			return -1;					\
+			return -1; 					\
 		}							\
 		value = (size_type) tmp;				\
 	}								\