Skip to content

Instantly share code, notes, and snippets.

@courtc
Last active August 29, 2015 14:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save courtc/75c0585e3943a2bf1150 to your computer and use it in GitHub Desktop.
Save courtc/75c0585e3943a2bf1150 to your computer and use it in GitHub Desktop.
Error file to patch line, with fuzzing
#!/usr/bin/env python2
import fileinput;
import sys;
import re;
import os;
def shortpath(name):
cwd = os.getcwd()
if name.startswith(cwd):
return name[len(cwd) + 1:]
return name
class Target:
def __init__(self):
self.start = 0
self.name = None
self.length = 0
self.xlate = 0
self.messages = []
def add(self, offset, message):
self.messages.append((offset, message))
def items(self):
for off, msg in self.messages:
yield "%d: %s" % (self.xlate + off, msg)
def fuzz(self, actual):
self.xlate += self.start - actual.start
class Patch:
def __init__(self, file):
self.filename = file
self.file = open(file, "r")
lineno = 1
target = None
targets = []
for line in self.file:
parts = line.strip('\r\n').split(' ')
if parts[0] == 'diff':
pass
elif parts[0] == "+++":
if target is not None:
targets.append(target)
target = Target()
target.name = parts[1]
elif parts[0] == '@@':
target.start = int(parts[2].split(',')[0][1:])
target.length = int(parts[2].split(',')[1])
target.xlate = lineno + 1
lineno += 1
if target is not None:
targets.append(target)
targets = sorted(targets, key=lambda x: x.start)
self.targets = sorted(targets, key=lambda x: x.name)
def parse(self, line):
if not re.match("[^\s:]+:[0-9]+:.*$", line):
return
file, lineno, message = line.split(':', 2)
lineno = int(lineno)
if re.match("[0-9]+:.*", message):
message = message.split(':', 1)[1].strip()
target = self.which(file, lineno)
if target is None:
return
target.add(lineno - target.start, message)
def which(self, file, lineno):
file = shortpath(file)
for target in self.targets:
#print "%s:%d <=> %s:%d::%d" % (file, lineno, target.name, target.start, target.start + target.length)
if "b/%s" % file != target.name:
continue
if lineno < target.start:
continue
if lineno >= target.start + target.length:
continue
return target
return None
def write(self):
for target in self.targets:
for msg in target.items():
print "%s:%s" % (shortpath(self.filename), msg)
def fuzz(self, actual):
for target, act in zip(self.targets, actual.targets):
target.fuzz(act)
def usage(name):
print "USAGE: %s <original-patch> [actual-patch]" % name
if __name__ == "__main__":
if len(sys.argv) < 2 or len(sys.argv) > 3:
usage(sys.argv[0])
sys.exit(1)
patch = Patch(sys.argv[1])
if len(sys.argv) == 3:
actual = Patch(sys.argv[2])
patch.fuzz(actual)
for line in sys.stdin.readlines():
line = line.strip('\n\r')
patch.parse(line)
print line
patch.write()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment