def _cdb_common(target_pid=None, target_cmd=None, symbols=None, env=None, callback=None,
                callback_args=None, timeout=_common.DEFAULT_TIMEOUT, memory_limit=None,
                idle_limit=None):
    assert target_pid is not None or target_cmd is not None
    assert target_pid is None or target_cmd is None
    classification = None
    if env is None:
        env = dict(os.environ)
    env["LIBC_FATAL_STDERR_"] = "1"
    if symbols is not None:
        env["_NT_ALT_SYMBOL_PATH"] = symbols
    elif target_cmd:
        env["_NT_ALT_SYMBOL_PATH"] = os.path.abspath(os.path.dirname(target_cmd[0]))
    cdb_cmd = [TOOL_CDB, "-x", "-lines", "-y",
               "SRV*c:\\websymbols*http://msdl.microsoft.com/download/symbols",
               "-c", "!gflag;g;.lastevent;r;kb;!msec.exploitable -m;" \
               "!heap -s 0;!heap -h;.echo;q"] # keep -c last
    start_time = _common.prof_timer()
    with tempfile.TemporaryFile(mode="w+t") as f:
        if target_pid is not None:
            cdb_cmd[-1] += "d" # change final 'q' to 'qd'
            cdb_cmd += ["-p", "%d" % target_pid]
            p = subprocess.Popen(cdb_cmd, stderr=f, stdout=f, env=env,
                                 stdin=subprocess.PIPE, creationflags=_common.POPEN_FLAGS)
        else:
            p = subprocess.Popen(cdb_cmd + target_cmd, stderr=f, stdout=f, env=env,
                                 stdin=subprocess.PIPE, creationflags=_common.POPEN_FLAGS)
            ps = psutil.Process(p.pid)
            bn = os.path.basename(target_cmd[0])
            try:
                while (_common.prof_timer() - start_time) < timeout:
                    if p.poll() is not None:
                        raise psutil.NoSuchProcess(p.pid)
                    for kid in ps.get_children():
                        if kid.name != bn:
                            continue # guard against catching something other than
                                     # the target being launched by the debugger
                        assert target_pid is None, "debugger has multiple children"
                        target_pid = kid.pid
                    if target_pid is not None:
                        #log.debug("got child pid in %0.2fs", (_common.prof_timer() - start_time))
                        break
                    time.sleep(POLL_SLEEP)
                assert target_pid is not None, "Failed to get child pid"
            except psutil.NoSuchProcess:
                # this means CDB is already gone. so we can't possibly hit a timeout and we
                # won't use target_pid for anything anyways
                log.debug("target done before pid was found")
                target_pid = p.pid
        try:
            cb_res = _common._call_callback(callback, callback_args, target_pid)
            if cb_res == _common.CB_ERROR:
                raise RuntimeError("callback() returned error")
            if p.poll() is None and target_cmd is None:
                try:
                    p.send_signal(signal.CTRL_BREAK_EVENT)
                except WindowsError as e:
                    f.write("alf.debug.cdb: failed to send Ctrl+Break to debugger (%s)\n" % e)
                    log.warn("failed to send Ctrl+Break to debugger")
            target_mon = _common.TargetMonitor(target_pid, idle_limit=idle_limit,
                                               memory_limit=memory_limit, time_limit=timeout)
            while p.poll() is None:
                if target_mon.check_memory():
                    f.write("memory limit of %0.2f MB was exceeded\n" % (memory_limit/1048576))
                    classification = _common.EXCESS_MEMORY_USAGE
                    break
                if target_mon.check_idle():
                    break
                if target_mon.check_timeout():
                    classification = _common.TIMEOUT
                    break
                time.sleep(POLL_SLEEP)
        finally:
            if p.poll() is None:
                attempt = 0
                pid = target_pid
                while True:
                    if attempt == 1:
                        try:
                            p.send_signal(signal.CTRL_BREAK_EVENT)
                        except WindowsError as e:
                            f.write("alf.debug.cdb: failed to send Ctrl+Break to debugger (%s)\n"
                                    % e)
                            log.warn("failed to send Ctrl+Break to debugger")
                    else:
                        with open(os.devnull, "w") as fp:
                            subprocess.call(["taskkill", "/pid", str(pid), "/f", "/t"],
                                            stdout=fp, stderr=fp)
                    st = _common.prof_timer()
                    while p.poll() is None and \
                            (_common.prof_timer() - st) < TIMEOUT_CHILD_EXIT_WAIT:
                        time.sleep(POLL_SLEEP)
                    if p.poll() is not None:
                        break
                    if attempt == 0:
                        f.write("[%0.1f]alf.debug.cdb: failed to kill child pid %d, trying to "
                                "break into debugger instead\n" % (time.time(), pid))
                    elif attempt == 1:
                        f.write("[%0.1f]alf.debug.cdb: failed to break into debugger, trying to "
                                "kill parent pid %d instead\n" % (time.time(), pid))
                    pid = p.pid
                    attempt += 1
                    assert attempt <= 3, "Failed to kill the debugger twice !?!"
                assert attempt <= 1, "Shouldn't need to kill the debugger."
            exit_code = p.wait()
        f.seek(0, os.SEEK_SET)
        debug_log = f.read()
    backtrace = []
    m = re.search(r"^The call to LoadLibrary\((?P<lib>[a-z]+)\) failed, Win32 error 0n2",
                  debug_log, re.MULTILINE)
    if m is not None:
        raise RuntimeError("cdb failed on call to LoadLibrary(%s)" % m.group("lib"))
    debug_class = _common.NOT_AN_EXCEPTION
    if ("Last event: %x." % target_pid) in debug_log:
        backtrace, debug_class, exit_code = _common.process_exploitable_output(debug_log)
    if cb_res == _common.CB_HANG:
        classification = _common.TIMEOUT
    elif classification is None:
        if cb_res == _common.CB_FAIL:
            classification = _common.UNKNOWN
        else:
            classification = debug_class
    debug_log = _common._limit_output_length(debug_log)
    return _common.FuzzResult(classification, debug_log, backtrace, exit_code=exit_code)
dataset/ETHPy150Open blackberry/ALF/alf/debug/_cdb.py/_cdb_common/original