Beispiel #1
0
    def compile(self, name):
        global compiled

        if self.verif:
            key = (self.width, name + "-verif")
        else:
            key = (self.width, name + "-synth")

        if not self.cachable(key) or key not in compiled:
            bin = tempfile.NamedTemporaryFile(delete=not args.args.keeptemps,
                                              dir=args.args.ofiledir)
            gcc = self.gccargs[name] + ["-o", bin.name, "-lm"]
            compiled[key] = bin
            bin.close()

            perf.start("gcc")
            if args.args.verbose > 1:
                print " ".join(gcc)
                subprocess.call(gcc)
            else:
                with open(os.devnull, "w") as fnull:
                    subprocess.call(gcc, stdout=fnull, stderr=fnull)
            perf.end("gcc")

            return bin
        else:
            return compiled[key]
Beispiel #2
0
def generalize(prog, checker, width, targetwidth, tests, codelen):
    perf.start("generalize")
    ret = heuristic_generalize(prog, checker, width, targetwidth, codelen)
    perf.end("generalize")

    return ret
Beispiel #3
0
def kalashnikov(checker):
    codelen = args.args.seqlen
    wordlen = args.args.wordwidth
    targetwordlen = args.args.targetwordwidth
    n = 1
    tests = gentests(wordlen, codelen)
    exclusions = []
    correct = []
    starttime = time.time()
    seqlim = args.args.seqlim
    nconsts = 0

    signal.alarm(args.args.timeout)

    if args.args.consts >= 0:
        nconsts = args.args.consts

    if args.args.exhaustive:
        numsearch = -1
    else:
        numsearch = 1

    perf.start()

    while codelen <= seqlim and len(correct) != numsearch:
        sys.stdout.flush()

        perf.inc("iterations")

        if not args.args.verbose:
            endtime = time.time()
            elapsed = endtime - starttime

            print("Iteration: " + BOLD + RED + "%d" + ENDC) % n
            print("Code sequence length: " + BOLD + RED + "%d/%d" +
                  ENDC) % (codelen, args.args.seqlim)
            print("Word width: " + BOLD + RED + "%d/%d" +
                  ENDC) % (wordlen, targetwordlen)
            print("Excluded sequences: " + BOLD + RED + "%d/%d" +
                  ENDC) % (len(exclusions), args.args.exclude)
            print("Test vectors: " + BOLD + RED + "%d" + ENDC) % len(tests)
            print("Constants: " + BOLD + RED + "%d" + ENDC) % nconsts
            print("Elapsed time: " + BOLD + RED + "%.02fs" + ENDC) % elapsed

            if args.args.exhaustive:
                print("Correct sequences: " + BOLD + RED + "%d" +
                      ENDC) % (len(correct))
                print UP * 2 + "\r"

            print UP * 8 + "\r"
            sys.stdout.flush()

        if args.args.verbose > 0:
            print correct

        n += 1

        if args.args.verbose > 1:
            print "Test vectors: %s" % str(tests)

        prog = synth(tests, exclusions + correct, wordlen, codelen, nconsts)

        if prog == None:
            if args.args.verbose > 0:
                print "No sequence possible!"

            if args.args.consts < 0 and nconsts < codelen:
                nconsts += 1
            else:
                codelen += 1

                if args.args.consts < 0:
                    nconsts = 0

            exclusions = []

            if args.args.verbose > 0:
                print "Increasing constants to %d\n" % nconsts
                print "Increasing sequence length to %d\n" % codelen

            continue

        if args.args.verbose > 0:
            print str(prog)

        test = verif(prog, checker, wordlen, codelen)

        if test is None:
            if args.args.verbose > 0:
                print "Correct for wordlen=%d" % wordlen

            if wordlen == targetwordlen:
                correct.append(prog)
                continue

            test = verif(prog, checker, targetwordlen, codelen)
            if test is None:
                if args.args.verbose > 0:
                    print "Also correct for wordlen=%d!" % targetwordlen

                correct.append(prog)
                continue

            if args.args.verbose > 0:
                print "Trying to generalize..."

            newprog = generalize(prog, checker, wordlen, targetwordlen, tests,
                                 codelen)

            if newprog:
                if args.args.verbose > 1:
                    print "Generalized!"

                correct.append(newprog)

                prog = newprog
                continue

            if args.args.verbose > 0:
                print "Couldn't generalize :-("

            if len(exclusions) < args.args.exclude:
                if args.args.verbose > 0:
                    print "Excluding current sequence"

                perf.inc("exclusions")
                exclusions.append(prog)
            else:
                exclusions = []
                wordlen *= 2

                if wordlen > targetwordlen:
                    wordlen = targetwordlen

                tests = gentests(wordlen, codelen)
                tests = list(set(tests))

                if args.args.verbose > 0:
                    print "Increasing wordlen to %d" % wordlen
        else:
            if args.args.verbose > 0:
                print "Fails for %s\n" % str(test)

            tests.append(test)

    perf.end()
    endtime = time.time()
    elapsed = endtime - starttime

    print "\n" * 6
    print "Finished in %0.2fs\n" % elapsed

    for prog in correct:
        print str(prog)
        print ""
Beispiel #4
0
def verif(prog, checker, width, codelen):
    """
  Verify that a sequence is correct & extract a new test vector if it's not."
  """

    perf.start("verify")

    sz = max(len(o) for o in prog.ops)
    bmc = Checker(sz, width, len(prog.consts[0]), verif=True)
    solfile = open("/tmp/solution", "w")

    solfile.write(" ".join("0x%x" % (x & 0xffffffff)
                           for x in prog.evars) + "\n")

    for i in xrange(args.args.progs):
        nops = len(prog.ops[i])
        solfile.write("%d\n" % nops)

        for j in xrange(nops):
            solfile.write(
                "%d %d %d %d\n" %
                (prog.ops[i][j], prog.params[i][3 * j],
                 prog.params[i][3 * j + 1], prog.params[i][3 * j + 2]))

        nconsts = len(prog.consts[i])

        for j in xrange(nconsts):
            solfile.write("0x%x\n" % (prog.consts[i][j] & 0xffffffff))

    solfile.close()

    cfile = open("/tmp/exec.c", "w")
    cfile.write(r"""
#include "synth.h"

volatile int execok;

void exec(prog_t *prog, word_t args[NARGS], word_t res[NRES]) {
""")

    for i in xrange(args.args.progs):
        cfile.write(r"""
  if (prog == &solution.progs[%d]) {
  """ % i)

        for j in xrange(sz):
            cfile.write("  res[%d] = 0;\n" % j)

        cfile.write(
            prog.prog2str(prog.ops[i],
                          prog.params[i],
                          prog.consts[i],
                          executable=True))
        cfile.write("\n  }\n")
    cfile.write("}")
    cfile.close()

    bmc.write(r"""
#include "synth.h"

solution_t solution = {
  {
""")

    for i in xrange(args.args.progs):
        bmc.write(r"""
  {
    %d,
    { %s },
    { %s },
    { %s },
  },
""" % (len(prog.ops[i]), ", ".join(str(o) for o in prog.ops[i]), ", ".join(
            str(p) for p in prog.params[i]), ", ".join(
                str(c) for c in prog.consts[i])))

    bmc.write(r"""
  },

  { %s }
};
""" % (", ".join(str(e) for e in prog.evars)))

    try:
        (retcode, output) = bmc.run()
    finally:
        perf.end("verify")

    cex = None

    if retcode == 10:
        # We got a counterexample -- extract a new test case from it
        for l in output:
            mx = cexre.search(l)

            if mx:
                cex = tuple(str2ints(mx.group(1)))
    else:
        # No counterexample -- this sequence is correct!
        pass

    return cex
Beispiel #5
0
def synth(tests, exclusions, width, codelen, nconsts):
    """
  Synthesise a new code sequence.
  """

    perf.start("synth")

    bmc = Checker(codelen, width, nconsts)

    testfile = open("/tmp/testvectors", "w")

    # Write the test inputs...
    bmc.write(r"""
#include "synth.h"

void tests(solution_t *solution) {
  word_t input[NARGS];
""")

    testfile.write("%d\n" % len(tests))

    #random.shuffle(tests)
    for x in tests:
        for i in xrange(len(x)):
            bmc.write("  input[%d] = %d;\n" % (i, x[i]))

        bmc.write("  test(solution, input);\n\n")

        testfile.write(" ".join(str(d) for d in x) + "\n")

    testfile.close()

    # Now we're going to list each of the programs we
    # already know are wrong...

    for soln in exclusions:
        ops = soln.ops
        parms = soln.params
        consts = soln.consts
        evars = soln.evars

        bmc.write("  assume(!(")

        for i in xrange(len(ops)):
            if i != 0:
                bmc.write(" && ")

            bmc.write("solution->prog.ops[%d] == %d " % (i, ops[i]))
            bmc.write(
                "&& solution->prog.params[%d] == %d && solution->prog.params[%d] == %d && solution->prog.params[%d] == %d"
                % (3 * i, parms[3 * i], 3 * i + 1, parms[3 * i + 1], 3 * i + 1,
                   parms[3 * i + 2]))

        for i in xrange(len(consts)):
            bmc.write("&& solution->prog.consts[%d] == %d" % (i, consts[i]))

        for i in xrange(len(evars)):
            bmc.write("&& solution->evars[%d] == %d" % (i, evars[i]))

        bmc.write("));\n")

    bmc.write("}\n")

    try:
        (retcode, output) = bmc.run()
    finally:
        perf.end("synth")

    prog = None

    if retcode == 10:
        # A counterexample was found -- extract the code sequence from it!
        prog = Prog()
        prog.parse(output)

    return prog
Beispiel #6
0
    def run(self):
        self.scratchfile.flush()
        perf.start("checker")
        procs = []

        strategy = None

        if args.args.verif_strategy == "default":
            args.args.verif_strategy = args.args.strategy

        if args.args.synth_strategy == "default":
            args.args.synth_strategy = args.args.strategy

        if self.verif:
            if args.args.verif_strategy in ("all", "evolve"):
                strategies = ["explicit", "cbmc"]
            else:
                strategies = [args.args.verif_strategy]
        else:
            if args.args.synth_strategy == "all":
                strategies = ["explicit", "cbmc", "genetic", "anneal"]
            elif args.args.synth_strategy == "evolve":
                strategies = ["genetic", "anneal"]
            else:
                strategies = [args.args.synth_strategy]

        try:
            if "cbmc" in strategies:
                if args.args.verbose > 1:
                    print " ".join(self.cbmcargs)

                cbmcfile = tempfile.NamedTemporaryFile(
                    delete=not args.args.keeptemps)
                cbmcproc = subprocess.Popen(self.cbmcargs,
                                            stdout=cbmcfile,
                                            preexec_fn=os.setpgrp)
                procs.append((cbmcproc, cbmcfile, "cbmc"))

            bins = {}

            for s in ("explicit", "genetic", "anneal"):
                if s in strategies:
                    bin = self.compile(s)
                    bins[s] = bin
                    outfile = tempfile.NamedTemporaryFile(
                        delete=not args.args.keeptemps)

                    if args.args.verbose > 1:
                        print bin.name

                    proc = subprocess.Popen([bin.name],
                                            stdout=outfile,
                                            preexec_fn=os.setpgrp)
                    procs.append((proc, outfile, s))

            (finished, retcode) = os.wait()
        finally:
            perf.end("checker")

            for (proc, _, _) in procs:
                try:
                    os.killpg(proc.pid, signal.SIGKILL)
                    proc.wait()
                except:
                    pass

        retfile = None

        for (proc, outfile, checker) in procs:
            if proc.pid == finished:
                retfile = outfile
                perf.inc(checker)

                if args.args.verbose > 0:
                    print "Fastest checker: %s" % checker

        retfile.seek(0)

        return (os.WEXITSTATUS(retcode), retfile)