summaryrefslogtreecommitdiffstats
path: root/sploit/types
diff options
context:
space:
mode:
Diffstat (limited to 'sploit/types')
-rw-r--r--sploit/types/__init__.py2
-rw-r--r--sploit/types/index_entry.py44
-rw-r--r--sploit/types/indextbl.py103
3 files changed, 149 insertions, 0 deletions
diff --git a/sploit/types/__init__.py b/sploit/types/__init__.py
new file mode 100644
index 0000000..1316dad
--- /dev/null
+++ b/sploit/types/__init__.py
@@ -0,0 +1,2 @@
+from .indextbl import *
+from .index_entry import *
diff --git a/sploit/types/index_entry.py b/sploit/types/index_entry.py
new file mode 100644
index 0000000..a03ab92
--- /dev/null
+++ b/sploit/types/index_entry.py
@@ -0,0 +1,44 @@
+import copy
+
+class IndexEntry:
+ """
+ Generic IndexTbl entry object
+
+ IndexEntry is intended to be subclassed to create interesting types that are
+ compatible with IndexTbl directories. IndexEntry gives objects a baseline
+ int-like personality.
+
+ IndexEntry objects are convertable to int via int(), bin(), hex(), etc. This
+ integer value is manipulated via the object's "base" property, and a few
+ operators are implemented to provide nicer syntax for this as well. The use
+ of operators generally yield distinct copies of the original object.
+
+ The property name "base" is used since it has semantic meaning for the
+ IndexTbl class, which is itself an extension of this class.
+
+ base (int): Index integer value
+ """
+
+ base = 0
+
+ def __init__(self, base=0):
+ """Construct index with the given base value."""
+ self.base = base
+
+ def __index__(self):
+ """Convert index to base integer value."""
+ return int(self.base)
+
+ def __matmul__(self, base):
+ """Create new object with the given base value."""
+ new = copy.copy(self)
+ new.base = base
+ return new
+
+ def __add__(self, add):
+ """Create new object with the given relative base value."""
+ return self @ (self.base + add)
+
+ def __sub__(self, sub):
+ """Create new object with the given relative base value."""
+ return self @ (self.base - sub)
diff --git a/sploit/types/indextbl.py b/sploit/types/indextbl.py
new file mode 100644
index 0000000..4f57a59
--- /dev/null
+++ b/sploit/types/indextbl.py
@@ -0,0 +1,103 @@
+from abc import abstractmethod
+from collections.abc import Collection
+
+from sploit.types.index_entry import IndexEntry
+
+class IndexTbl(IndexEntry, Collection):
+ """
+ Abstract Index Table
+
+ IndexTbl is a common interface to an abstracted key-value store. The
+ storage mechanism as well as lookup semantics are defined by concrete
+ implementations. "Index" in this case is more akin to a directory index or
+ book index than a strictly numeric array index.
+
+ In general, concrete tables may store values of any or multiple different
+ types. In particular, tables should give special accommodation for values
+ of type IndexEntry. These objects usually represent "rich" versions of the
+ nominal data types the table expects to contain. Implementation repr()
+ methods usually also annotate which members are IndexEntries.
+
+ IndexTbl extends from IndexEntry, and so has a base value which represents
+ the "base index" of the table. The meaning of this depends on the
+ implementation. This inheritance also means that tables are generally
+ expected to be nestable.
+
+ IndexTbls allow indices to be accessed via attribute or subscript notation.
+ This is probably the key characteristic feature of the class. The class
+ namespace is kept as clean as possible to make for the fewest collisions
+ between index names and other (real) class attributes. Note that there are
+ abstract methods, required to be overridden, which implement the index
+ access. These methods are only called for normal indices, not the table
+ base.
+
+ Because this class overrides attribute access, normal automatic object
+ copying is broken. Because of this, implementations must also provide a
+ definition for the __copy__() method as well.
+ """
+
+ @abstractmethod
+ def __getindex__(self, index):
+ """Lookup and retrieve index value."""
+ raise NotImplementedError
+
+ @abstractmethod
+ def __setindex__(self, index, value):
+ """Lookup and set index value."""
+ raise NotImplementedError
+
+ @abstractmethod
+ def __delindex__(self, index):
+ """Lookup and delete index value."""
+ raise NotImplementedError
+
+ @abstractmethod
+ def __copy__(self):
+ """Create a copy of this IndexTbl object."""
+ raise NotImplementedError
+
+ def __contains__(self, index):
+ """Test the existence of the given index."""
+ try:
+ self.__getindex__(index)
+ except KeyError:
+ return False
+ else:
+ return True
+
+ # Attribute access methods
+
+ def __getattr__(self, index):
+ """Get value via attribute."""
+ return self[index]
+
+ def __setattr__(self, index, value):
+ """Set value via attribute."""
+ self[index] = value
+
+ def __delattr__(self, index):
+ """Delete value via attribute."""
+ del self[index]
+
+ # Subscript/item access methods
+
+ def __getitem__(self, index):
+ """Get value via subscript."""
+ if index == "base":
+ return self.base
+ return self.__getindex__(index)
+
+ def __setitem__(self, index, value):
+ """Set value via subscript."""
+ if index == "base":
+ object.__setattr__(self, "base", value)
+ elif index in dir(self):
+ raise KeyError(f"IndexTbl: Index is reserved: {index}")
+ else:
+ self.__setindex__(index, value)
+
+ def __delitem__(self, index):
+ """Delete value via subscript."""
+ if index == "base":
+ raise KeyError("IndexTbl: May not delete index: base")
+ self.__delindex__(index)