Skip to content
Snippets Groups Projects
mini_parser.py 3.21 KiB
Newer Older
  • Learn to ignore specific revisions
  • from os.path import basename
    import re
    import sys
    
    # A very limited parser whose job is to process the compatibility mapping
    # files and retrieve type and attribute information until proper support is
    # built into libsepol
    
    # get the text in the next matching parens
    
    class MiniCilParser:
        types = set() # types declared in mapping
        pubtypes = set()
        typeattributes = set() # attributes declared in mapping
        typeattributesets = {} # sets defined in mapping
        rTypeattributesets = {} # reverse mapping of above sets
        apiLevel = None
    
        def _getNextStmt(self, infile):
            parens = 0
            s = ""
            c = infile.read(1)
            # get to first statement
            while c and c != "(":
                c = infile.read(1)
    
            parens += 1
            c = infile.read(1)
            while c and parens != 0:
                s += c
                c = infile.read(1)
                if c == ';':
                    # comment, get rid of rest of the line
                    while c != '\n':
                        c = infile.read(1)
                elif c == '(':
                    parens += 1
                elif c == ')':
                    parens -= 1
            return s
    
        def _parseType(self, stmt):
            m = re.match(r"type\s+(.+)", stmt)
    
            return
    
        def _parseTypeattribute(self, stmt):
            m = re.match(r"typeattribute\s+(.+)", stmt)
    
            self.typeattributes.add(m.group(1))
    
            return
    
        def _parseTypeattributeset(self, stmt):
            m = re.match(r"typeattributeset\s+(.+?)\s+\((.+?)\)", stmt, flags = re.M |re.S)
            ta = m.group(1)
            # this isn't proper expression parsing, but will do for our
            # current use
            tas = m.group(2).split()
    
            if self.typeattributesets.get(ta) is None:
                self.typeattributesets[ta] = set()
            self.typeattributesets[ta].update(set(tas))
            for t in tas:
                if self.rTypeattributesets.get(t) is None:
                    self.rTypeattributesets[t] = set()
                self.rTypeattributesets[t].update(set(ta))
    
            # check to see if this typeattributeset is a versioned public type
            pub = re.match(r"(\w+)_\d+_\d+", ta)
            if pub is not None:
    
            return
    
        def _parseStmt(self, stmt):
            if re.match(r"type\s+.+", stmt):
                self._parseType(stmt)
            elif re.match(r"typeattribute\s+.+", stmt):
                self._parseTypeattribute(stmt)
            elif re.match(r"typeattributeset\s+.+", stmt):
                self._parseTypeattributeset(stmt)
            else:
                m = re.match(r"(\w+)\s+.+", stmt)
                ret = "Warning: Unknown statement type (" + m.group(1) + ") in "
                ret += "mapping file, perhaps consider adding support for it in "
                ret += "system/sepolicy/tests/mini_parser.py!\n"
                print ret
            return
    
        def __init__(self, policyFile):
            with open(policyFile, 'r') as infile:
                s = self._getNextStmt(infile)
                while s:
                    self._parseStmt(s)
                    s = self._getNextStmt(infile)
            fn = basename(policyFile)
            m = re.match(r"(\d+\.\d+).+\.cil", fn)
            self.apiLevel = m.group(1)
    
    if __name__ == '__main__':
        f = sys.argv[1]
        p = MiniCilParser(f)