def putStringMap(self, tests, level): # This handles the case of multiple strings mapping to mime names. # The operator must be equality. We have to build a table of # test data. These have all have a zero offset. indent = mkIndent(level) ind1 = mkIndent(1) mapName = "stringMap%d" % self.mapCount self.mapCount += 1 # A list of (bytes, targ, mime). These will be sorted targets = [] for t in tests: # Get a string literal which we can use sizeof on. bytes = utils.splitStringBytes(t.target) targ = utils.bytesToC(bytes) mime = utils.quoteForC(t.setMime) triple = (bytes, targ, mime) targets.append(triple) targets.sort(key=lambda triple: triple[0]) print >> self.data, "\nstatic StringMap %s[] = {" % mapName for (bytes, targ, mime) in targets: print >> self.data, '%s{%s, sizeof(%s) - 1, %s},' % ( ind1, targ, targ, mime) print >> self.data, "};" print >> self.data, "static const size_t %sCount = %d;" % ( mapName, len(targets)) # Presumably all tests have the same nesting level testLevel = tests[0].level testLine = tests[0].lnum if testLevel == 0: print >> self.code print >> self.code, '%s// line %s' % (indent, testLine) if RuntimeDebug: print >> self.code, "%s++testCount;" % indent print >> self.code, '%srslt = stringEqualMap(buf, len, %s, %sCount, mime);' % ( indent, mapName, mapName) print >> self.code, '%sif (rslt < 0) haveError = True;' % indent print >> self.code, '%sif (rslt > 0)' % indent print >> self.code, '%s{' % indent print >> self.code, '%sreturn Match;' % mkIndent(level + 1) print >> self.code, '%s}' % indent
def putSimpleString(self, test, level): indent = mkIndent(level) if test.targetOper in self.stringFuncs: func = self.stringFuncs[test.targetOper] # Get a string literal which we can use sizeof on. targ = utils.quoteForC(test.target) ovar = mkOvar(test.level) inner = OStream() if test.level == 0: print >> self.code print >> self.code, '%s// line %s' % (indent, test.lnum) if RuntimeDebug: print >> self.code, "%s++testCount;" % indent print >> inner, '%srslt = %s(buf, len, %s, sizeof(%s) - 1, &%s);' % \ (indent, func, targ, targ, ovar) print >> inner, '%sif (rslt < 0) haveError = True;' % indent self.genOffset(test, str(inner), level) self.putTestBody(test, level) elif test.targetOper == 'x': # Always match self.putTestContent(test, level) else: print >> sys.stderr, "Unrecognised string operator in:", test
def putTestBody(self, test, level): # This is the common structure after each test indent = mkIndent(level) print >> self.code, '%sif (rslt > 0)' % indent print >> self.code, '%s{' % indent self.putTestContent(test, level + 1) print >> self.code, '%s}' % indent
def putRoot(self, root): self.putTests(root.subtests, 1) # We need an 'offN' variable for each level of nesting. #print 'root depth', root.depth() decl = [] for n in range(root.depth()): decl.append('off%d' % n) print >> self.decls, "%ssize_t %s;" % (mkIndent(1), ', '.join(decl))
def putBeShortGroup(self, tests, level): # This handles the case of multiple strings mapping to mime names. # The operator must be equality. We have to build a table of # test data. These have all have a zero offset. indent = mkIndent(level) ind1 = mkIndent(1) mapName = "beshortMap%d" % self.mapCount self.mapCount += 1 # A list of (test, mask, mime). targets = [] for t in tests: # Get a string literal which we can use sizeof on. mask = '0xffff' if t.testMask == None else t.testMask triple = (t.target, mask, utils.quoteForC(t.setMime)) targets.append(triple) print >> self.data, "\nstatic ShortMap %s[] = {" % mapName for (targ, mask, mime) in targets: print >> self.data, '%s{%s, %s, %s},' % (ind1, targ, mask, mime) print >> self.data, "};" print >> self.data, "static const size_t %sCount = %d;" % ( mapName, len(targets)) # Presumably all tests have the same nesting level testLevel = tests[0].level testLine = tests[0].lnum if testLevel == 0: print >> self.code print >> self.code, '%s// line %s' % (indent, testLine) if RuntimeDebug: print >> self.code, "%s++testCount;" % indent print >> self.code, '%srslt = beShortGroup(buf, len, %s, %sCount, mime);' % ( indent, mapName, mapName) print >> self.code, '%sif (rslt < 0) haveError = True;' % indent print >> self.code, '%sif (rslt > 0)' % indent print >> self.code, '%s{' % indent print >> self.code, '%sreturn Match;' % mkIndent(level + 1) print >> self.code, '%s}' % indent
def genOffset(self, test, innerCode, level): # Generate the code for the offset. With indirection we need # something of the form: # rslt = getOffset(buf, len, off1, 's', &off1); # if (rslt < 0) haveError = True; # else # { # off1 += (30); # rslt = leShortMatch(buf, len, 0xcafe, CompareEq, 0xffffffff, off1); # if (rslt < 0) haveError = True; # } # For this we need the rest of the test passed in as a stream. indent = mkIndent(level) off = test.offset ovar = mkOvar(test.level) # Start with a simple offset print >> self.code, "%s%s = %s;" % (indent, ovar, off.offset) # It appears that (&0x7c.l+0x26) means *(0x7c + off) + 0x26 if off.indirect: # Go indirect through the buffer if off.innerRelative: outer = mkOvar(test.level - 1) print >> self.code, "%s%s += %s;" % (indent, ovar, outer) # getOffset(const Byte* buf, size_t len, size_t at, char type, size_t* offset) print >> self.code, "%srslt = getOffset(buf, len, %s, '%s', &%s);" % \ (indent, ovar, off.typeFlag, ovar) if off.operand: value = off.operand print >> self.code, "%s%s %s= %s;" % ( indent, ovar, off.operator, off.operand) if off.outerRelative: # Add the outer offset, for the direct and indirect cases print >> self.code, "%s%s += %s;" % (indent, ovar, mkOvar(test.level - 1)) if off.indirect: # We have a rslt from above to print >> self.code, "%sif (rslt < 0) haveError = True;" % indent print >> self.code, "%selse" % indent print >> self.code, "%s{" % indent innerCode = utils.addIndent(innerCode, 1) print >> self.code, innerCode, print >> self.code, "%s}" % indent else: print >> self.code, innerCode,
def putTestContent(self, test, level): # What to do if the test passes # The result is the number of bytes that were matched. We # must update the offset for inner tests. # *** If there are both subtests and a MIME we only set the # MIME. See also selectSimpleStringMime(). indent = mkIndent(level) if test.setMime: m = utils.quoteForC(test.setMime) print >> self.code, '%s*mime = %s;' % (indent, m) print >> self.code, '%sreturn Match;' % indent else: # No mime at this level, there must be subtests self.putTests(test.subtests, level)
def putGeneralTest(self, test, level): # Write any other kind of test # We don't find double or float in any of the tests we perform. # They could be added later if necessary. The date tests don't # appear in the current magic database. indent = mkIndent(level) ovar = mkOvar(test.level) if test.testCode == 'default' or test.targetOper == 'x': # Always match. The 'clear' operation doesn't seem to # be relevant to generating a MIME type. self.putTestContent(test, level) elif test.testCode == 'string': # handle combinations of flags and comparisons flags = ['0'] if 'w' in test.testFlags: flags.append('IgnoreWS') if 'W' in test.testFlags: flags.append('CompactWS') if 'c' in test.testFlags: flags.append('MatchLower') if 'C' in test.testFlags: flags.append('MatchUpper') flags = '|'.join(flags) oper = [] if '=' in test.targetOper: oper.append('CompareEq') if '<' in test.targetOper: oper.append('CompareLt') if '>' in test.targetOper: oper.append('CompareGt') if '!' in test.targetOper: oper.append('CompareNot') oper = '|'.join(oper) targ = utils.quoteForC(test.target) inner = OStream() if test.level == 0: print >> self.code print >> self.code, '%s// line %s' % (indent, test.lnum) if RuntimeDebug: print >> self.code, "%s++testCount;" % indent print >> inner, '%srslt = stringMatch(buf, len, %s, sizeof(%s) - 1, &%s, %s, %s);' % \ (indent, targ, targ, ovar, oper, flags) print >> inner, '%sif (rslt < 0) haveError = True;' % indent self.genOffset(test, str(inner), level) self.putTestBody(test, level) elif test.testCode == 'search': # handle combinations of flags and comparisons flags = ['0'] if 'w' in test.testFlags: flags.append('IgnoreWS') if 'W' in test.testFlags: flags.append('CompactWS') if 'c' in test.testFlags: flags.append('MatchLower') if 'C' in test.testFlags: flags.append('MatchUpper') flags = '|'.join(flags) # find the range limit limit = test.testLimit if limit == None: print >> sys.stderr, "Missing range limit in", test else: targ = utils.quoteForC(test.target) inner = OStream() if test.level == 0: print >> self.code print >> self.code, '%s// line %s' % (indent, test.lnum) if RuntimeDebug: print >> self.code, "%s++testCount;" % indent print >> inner, '%srslt = stringSearch(buf, len, %s, sizeof(%s) - 1, &%s, %s, %s);' % \ (indent, targ, targ, ovar, limit, flags) print >> inner, '%sif (rslt < 0) haveError = True;' % indent self.genOffset(test, str(inner), level) self.putTestBody(test, level) elif test.testCode == 'regex': # find the range limit limit = test.testLimit if limit == None: limit = '0' # handle combinations of flags and comparisons flags = ['0'] if 'c' in test.testFlags: flags.append('RegexNoCase') if 's' in test.testFlags: flags.append('RegexBegin') if 'l' in test.testFlags: limit += ' * 80' # pretend 80 chars per line flags = '|'.join(flags) targ = utils.quoteForC(test.target) inner = OStream() if test.level == 0: print >> self.code print >> self.code, '%s// line %s' % (indent, test.lnum) if RuntimeDebug: print >> self.code, "%s++testCount;" % indent print >> inner, '%srslt = regexMatch(buf, len, %s, &%s, %s, %s);' % ( indent, targ, ovar, limit, flags) print >> inner, '%sif (rslt < 0) haveError = True;' % indent self.genOffset(test, str(inner), level) self.putTestBody(test, level) elif test.testCode in self.simpleIntFuncs: func = self.simpleIntFuncs[test.testCode] value = test.target # this should be a C integer in string form compare = self.genCompareCodes(test) mask = test.testMask if test.testMask else "0xffffffff" inner = OStream() if test.level == 0: print >> self.code print >> self.code, '%s// line %s' % (indent, test.lnum) if RuntimeDebug: print >> self.code, "%s++testCount;" % indent print >> inner, '%srslt = %s(buf, len, %s, %s, %s, &%s);' % ( indent, func, value, compare, mask, ovar) print >> inner, '%sif (rslt < 0) haveError = True;' % indent self.genOffset(test, str(inner), level) self.putTestBody(test, level) else: print >> sys.stderr, "Unimplemented test", test