def write(self, fd, databyte, pid): self.add_selfpid(pid) if not self.getproc(pid).fd_map.contains(fd): return {'r': -1, 'errno': errno.EBADF} if self.getproc(pid).fd_map[fd].ispipe: if not self.getproc(pid).fd_map[fd].pipewriter: return {'r': -1, 'errno': errno.EBADF} pipeid = self.getproc(pid).fd_map[fd].pipeid pipe = self.pipes[pipeid] otherfd = SFdNum.var('otherfd') if simsym.symnot(simsym.symor([ simsym.exists(otherfd, simsym.symand([self.proc0.fd_map.contains(otherfd), self.proc0.fd_map._map[otherfd].ispipe, simsym.symnot(self.proc0.fd_map._map[otherfd].pipewriter), self.proc0.fd_map._map[otherfd].pipeid == pipeid])), simsym.exists(otherfd, simsym.symand([self.proc1.fd_map.contains(otherfd), self.proc1.fd_map._map[otherfd].ispipe, simsym.symnot(self.proc1.fd_map._map[otherfd].pipewriter), self.proc1.fd_map._map[otherfd].pipeid == pipeid]))])): # XXX This condition has the same problem as the one # in read. return {'r': -1, 'errno': errno.EPIPE} simsym.assume(pipe.data.len() < DATA_MAX_LEN) pipe.data.append(databyte) return {'r': DATAVAL_BYTES} off = self.getproc(pid).fd_map[fd].off self.getproc(pid).fd_map[fd].off = off + 1 return self.iwrite(self.getproc(pid).fd_map[fd].inum, off, databyte)
def iused(self, inum): dir = SInum.var('dir') fn = SFn.var('fn') fd = SFdNum.var('fd') pid = SPid.var('pid') # If we try to simply index into dirmap, its __getitem__ # won't have access to the supposition that it contains the right # key, and throw an exception. Thus, we use _map directly. return simsym.symor([ ## XXX Directories impl: # simsym.exists(dir, # simsym.symand([ # self.i_map[dir].isdir, # simsym.exists(fn, # simsym.symand([self.i_map[dir].dirmap.contains(fn), # self.i_map[dir].dirmap._map[fn] == inum]))])), ## XXX Non-directories impl: simsym.exists(fn, simsym.symand([self.root_dir.contains(fn), self.root_dir._map[fn] == inum])), simsym.exists(fd, simsym.symand([self.proc0.fd_map.contains(fd), simsym.symnot(self.proc0.fd_map._map[fd].ispipe), self.proc0.fd_map._map[fd].inum == inum])), simsym.exists(fd, simsym.symand([self.proc1.fd_map.contains(fd), simsym.symnot(self.proc1.fd_map._map[fd].ispipe), self.proc1.fd_map._map[fd].inum == inum])), ])
def enqueue_proc_prio_queue(self, pid, pprio): simsym.assume(pid >= NULLPROCREF) simsym.assume(pid <= IDLEPROCREF) simsym.assume(pprio >= 0) simsym.assume(pprio <= MAXPROCS) self.qprio.create(pid) self.qprio[pid] = pprio if procs_prev.empty(): # empty queue procs_prev.create(pid) procs_prev[pid] = NULLPROCREF procs_next.create(pid) procs_next[pid] = NULLPROCREF else: # find the right place to add the new pid in pcut = PRef.var() simsym.assume(simsym.exists(pcut, symand(qprio.contains(pcut), symor(symand(qprio[pcut] >= pprio, symor(qprio[proces_prev[pcut]] < pprio, proces_prev[pcut] == NULLPROCREF), symand(qprio[pcut] <= pprio, symor(qprio[proces_next[pcut]] > pprio, proces_next[pcut] == NULLPROCREF))))))) # find a process with higer priority if qprio[proces_prev[pcut]] < pprio or proces_prev[pcut] == NULLPROCREF: # --- < pid <= pcut <= --- procs_prev.create(pid) procs_prev[pid] = proces_prev[pcut] procs_next.create(pid) procs_next[pid] = pcut proces_prev[pcut] = pid # find a process with lower priority else: # --- <= pcut <= pid < --- procs_next.create(pid) procs_next[pid] = proces_next[pcut] procs_prev.create(pid) procs_prev[pid] = pcut proces_next[pcut] = pid
def read(self, fd, pid): self.add_selfpid(pid) if not self.getproc(pid).fd_map.contains(fd): return {'r': -1, 'errno': errno.EBADF} if self.getproc(pid).fd_map[fd].ispipe: if self.getproc(pid).fd_map[fd].pipewriter: return {'r': -1, 'errno': errno.EBADF} pipeid = self.getproc(pid).fd_map[fd].pipeid pipe = self.pipes[pipeid] if pipe.data.len() == 0: otherfd = SFdNum.var('otherfd') if simsym.symor([ simsym.exists( otherfd, simsym.symand([ self.proc0.fd_map.contains(otherfd), self.proc0.fd_map._map[otherfd].ispipe, self.proc0.fd_map._map[otherfd].pipewriter, self.proc0.fd_map._map[otherfd].pipeid == pipeid ])), simsym.exists( otherfd, simsym.symand([ self.proc1.fd_map.contains(otherfd), self.proc1.fd_map._map[otherfd].ispipe, self.proc1.fd_map._map[otherfd].pipewriter, self.proc1.fd_map._map[otherfd].pipeid == pipeid ])) ]): return {'r': -1, 'errno': errno.EAGAIN} else: # XXX The above condition can always be satisfied # by making up some other FD, but testgen may # never see that FD, so the real test may not # reflect its presence. return {'r': 0} d = pipe.data[0] pipe.data.shift() return {'r': DATAVAL_BYTES, 'data': d} off = self.getproc(pid).fd_map[fd].off r = self.iread(self.getproc(pid).fd_map[fd].inum, off) if 'data' in r: self.getproc(pid).fd_map[fd].off = off + 1 return r
def pipe(self, pid): self.add_selfpid(pid) internal_pipeid = SPipeId.var('internal_pipeid*') xfd = SFdNum.var('xfd') simsym.assume(simsym.symnot(simsym.symor([ simsym.exists(xfd, simsym.symand([self.proc0.fd_map.contains(xfd), self.proc0.fd_map._map[xfd].ispipe, self.proc0.fd_map._map[xfd].pipeid == internal_pipeid])), simsym.exists(xfd, simsym.symand([self.proc1.fd_map.contains(xfd), self.proc1.fd_map._map[xfd].ispipe, self.proc1.fd_map._map[xfd].pipeid == internal_pipeid]))]))) empty_pipe = self.pipes[internal_pipeid] empty_pipe.data._len = 0 ## lowest FD for read end internal_fd_r = SFdNum.var('internal_fd_r*') simsym.assume(internal_fd_r >= 0) simsym.assume(simsym.symnot(self.getproc(pid).fd_map.contains(internal_fd_r))) simsym.assume(simsym.symnot(simsym.exists(xfd, simsym.symand([xfd >= 0, xfd < internal_fd_r, self.getproc(pid).fd_map.contains(xfd)])))) fd_r_data = self.getproc(pid).fd_map.create(internal_fd_r) fd_r_data.ispipe = True fd_r_data.pipeid = internal_pipeid fd_r_data.pipewriter = False ## lowest FD for write end internal_fd_w = SFdNum.var('internal_fd_w*') simsym.assume(internal_fd_w >= 0) simsym.assume(simsym.symnot(self.getproc(pid).fd_map.contains(internal_fd_w))) simsym.assume(simsym.symnot(simsym.exists(xfd, simsym.symand([xfd >= 0, xfd < internal_fd_w, self.getproc(pid).fd_map.contains(xfd)])))) fd_w_data = self.getproc(pid).fd_map.create(internal_fd_w) fd_w_data.ispipe = True fd_w_data.pipeid = internal_pipeid fd_w_data.pipewriter = True return {'r': 0, 'fds[0]': internal_fd_r, 'fds[1]': internal_fd_w}
def write(self, fd, databyte, pid): self.add_selfpid(pid) if not self.getproc(pid).fd_map.contains(fd): return {'r': -1, 'errno': errno.EBADF} if self.getproc(pid).fd_map[fd].ispipe: if not self.getproc(pid).fd_map[fd].pipewriter: return {'r': -1, 'errno': errno.EBADF} pipeid = self.getproc(pid).fd_map[fd].pipeid pipe = self.pipes[pipeid] otherfd = SFdNum.var('otherfd') if simsym.symnot( simsym.symor([ simsym.exists( otherfd, simsym.symand([ self.proc0.fd_map.contains(otherfd), self.proc0.fd_map._map[otherfd].ispipe, simsym.symnot(self.proc0.fd_map._map[otherfd]. pipewriter), self.proc0.fd_map._map[otherfd].pipeid == pipeid ])), simsym.exists( otherfd, simsym.symand([ self.proc1.fd_map.contains(otherfd), self.proc1.fd_map._map[otherfd].ispipe, simsym.symnot(self.proc1.fd_map._map[otherfd]. pipewriter), self.proc1.fd_map._map[otherfd].pipeid == pipeid ])) ])): # XXX This condition has the same problem as the one # in read. return {'r': -1, 'errno': errno.EPIPE} simsym.assume(pipe.data.len() < DATA_MAX_LEN) pipe.data.append(databyte) return {'r': DATAVAL_BYTES} off = self.getproc(pid).fd_map[fd].off self.getproc(pid).fd_map[fd].off = off + 1 return self.iwrite(self.getproc(pid).fd_map[fd].inum, off, databyte)
def open(self, pn, creat, excl, trunc, anyfd, pid): # XXX O_RDONLY, O_WRONLY, O_RDWR self.add_selfpid(pid) internal_time = STime.var('internal_time*') created = False anyfd = False _, pndirmap, pnlast = self.nameiparent(pn) if creat: if not pndirmap.contains(pnlast): internal_alloc_inum = SInum.var('internal_alloc_inum*') simsym.assume(simsym.symnot(self.iused(internal_alloc_inum))) simsym.assume(internal_time >= self.i_map[internal_alloc_inum].atime) simsym.assume(internal_time >= self.i_map[internal_alloc_inum].mtime) simsym.assume(internal_time >= self.i_map[internal_alloc_inum].ctime) inode = self.i_map[internal_alloc_inum] inode.data._len = 0 inode.nlink = 1 inode.atime = inode.mtime = inode.ctime = internal_time pndirmap[pnlast] = internal_alloc_inum created = True else: if excl: return {'r': -1, 'errno': errno.EEXIST} if not pndirmap.contains(pnlast): return {'r': -1, 'errno': errno.ENOENT} inum = pndirmap[pnlast] if trunc: if not created: simsym.assume(internal_time >= self.i_map[inum].mtime) simsym.assume(internal_time >= self.i_map[inum].ctime) self.i_map[inum].mtime = internal_time self.i_map[inum].ctime = internal_time self.i_map[inum].data._len = 0 internal_ret_fd = SFdNum.var('internal_ret_fd*') simsym.assume(internal_ret_fd >= 0) simsym.assume(simsym.symnot(self.getproc(pid).fd_map.contains(internal_ret_fd))) ## Lowest FD otherfd = SFdNum.var('fd') simsym.assume(simsym.symor([anyfd, simsym.symnot(simsym.exists(otherfd, simsym.symand([otherfd >= 0, otherfd < internal_ret_fd, self.getproc(pid).fd_map.contains(otherfd)])))])) fd_data = self.getproc(pid).fd_map.create(internal_ret_fd) fd_data.inum = inum fd_data.off = 0 fd_data.ispipe = False return {'r': internal_ret_fd}
def next_from_proc_prio_queue(self): simsym.assume phead = PRef.var() simsym.assume(simsym.exists(phead, procs_prev[phead] == NULLPROCREF)) if (procs_next[phead] != NULLPROCREF): procs_prev[procs_next[phead]] = NULLPROCREF # is this the correct way to delete an element from the tdict? del procs_next[phead] del procs_prev[phead] del qprio[phead] return phead;
def remove_element(self, x): i = simsym.SInt.var() simsym.assume(simsym.exists(i, simsym.symand(self.elts.len() > i, self.elts[i] == x))) newElts = symtypes.tlist(simsym.SInt, APref).var() k = simsym.SInt.var() k = 0 while k < self.elts.len(): if k != i: newElts.append(elts[k]) k = k + 1 self.elts = newElts
def iused(self, inum): dir = SInum.var('dir') fn = SFn.var('fn') fd = SFdNum.var('fd') pid = SPid.var('pid') # If we try to simply index into dirmap, its __getitem__ # won't have access to the supposition that it contains the right # key, and throw an exception. Thus, we use _map directly. return simsym.symor([ ## XXX Directories impl: # simsym.exists(dir, # simsym.symand([ # self.i_map[dir].isdir, # simsym.exists(fn, # simsym.symand([self.i_map[dir].dirmap.contains(fn), # self.i_map[dir].dirmap._map[fn] == inum]))])), ## XXX Non-directories impl: simsym.exists( fn, simsym.symand([ self.root_dir.contains(fn), self.root_dir._map[fn] == inum ])), simsym.exists( fd, simsym.symand([ self.proc0.fd_map.contains(fd), simsym.symnot(self.proc0.fd_map._map[fd].ispipe), self.proc0.fd_map._map[fd].inum == inum ])), simsym.exists( fd, simsym.symand([ self.proc1.fd_map.contains(fd), simsym.symnot(self.proc1.fd_map._map[fd].ispipe), self.proc1.fd_map._map[fd].inum == inum ])), ])
def read(self, fd, pid): self.add_selfpid(pid) if not self.getproc(pid).fd_map.contains(fd): return {'r': -1, 'errno': errno.EBADF} if self.getproc(pid).fd_map[fd].ispipe: if self.getproc(pid).fd_map[fd].pipewriter: return {'r': -1, 'errno': errno.EBADF} pipeid = self.getproc(pid).fd_map[fd].pipeid pipe = self.pipes[pipeid] if pipe.data.len() == 0: otherfd = SFdNum.var('otherfd') if simsym.symor([ simsym.exists(otherfd, simsym.symand([self.proc0.fd_map.contains(otherfd), self.proc0.fd_map._map[otherfd].ispipe, self.proc0.fd_map._map[otherfd].pipewriter, self.proc0.fd_map._map[otherfd].pipeid == pipeid])), simsym.exists(otherfd, simsym.symand([self.proc1.fd_map.contains(otherfd), self.proc1.fd_map._map[otherfd].ispipe, self.proc1.fd_map._map[otherfd].pipewriter, self.proc1.fd_map._map[otherfd].pipeid == pipeid]))]): return {'r': -1, 'errno': errno.EAGAIN} else: # XXX The above condition can always be satisfied # by making up some other FD, but testgen may # never see that FD, so the real test may not # reflect its presence. return {'r': 0} d = pipe.data[0] pipe.data.shift() return {'r': DATAVAL_BYTES, 'data': d} off = self.getproc(pid).fd_map[fd].off r = self.iread(self.getproc(pid).fd_map[fd].inum, off) if 'data' in r: self.getproc(pid).fd_map[fd].off = off + 1 return r
def do_callset(base, callset, test_writer): print ' '.join([c.__name__ for c in callset]) test_writer.begin_call_set(callset) reporter = progress.ProgressReporter( ' {0.npath} paths ({0.ncompath} commutative), {0.nmodel} testcases,' + ' {0.nerror} errors', test_writer) condlists = collections.defaultdict(list) terminated = False diverged = set() all_internals = [] for sar in simsym.symbolic_apply(test, base, *callset): if sar.type == 'value': is_commutative = (len(sar.value.diverge) == 0) diverged.update(sar.value.diverge) condlists[is_commutative].append(sar.path_condition) all_internals.extend(sar.internals) test_writer.on_result(sar) if not test_writer.keep_going(): terminated = True break test_writer.end_call_set() reporter.end() if terminated: print ' enumeration incomplete; skipping conditions' return conds = collections.defaultdict(lambda: [simsym.wrap(z3.BoolVal(False))]) for result, condlist in condlists.items(): conds[result] = condlist if True in condlists: commute = simsym.symor(condlists[True]) # Internal variables help deal with situations where, for the # same assignment of initial state + external inputs, two # operations both can commute and can diverge (depending on # internal choice, like the inode number for file creation). cannot_commute = simsym.symnot(simsym.exists(all_internals, commute)) print_cond('can commute', commute) else: cannot_commute = True if False in condlists: diverge = simsym.symor(condlists[False]) print_cond('can not commute; %s' % str_diverge(diverged), simsym.symand([diverge, cannot_commute]))
def socket(self, domain, type, prot, anyfd, pid): self.add_selfpid(pid) if not ((domain == AF_INET or domain == AF_INET6) and type == SOCK_DGRAM and prot == 0): return {'r': -1, 'errno': errno.EAFNOSUPPORT} internal_ret_fd = SFdNum.var('internal_ret_fd*') simsym.assume(internal_ret_fd >= 0) simsym.assume( simsym.symnot(self.getproc(pid).fd_map.contains(internal_ret_fd))) ## Lowest FD otherfd = SFdNum.var('fd') simsym.assume( simsym.symor([ anyfd, simsym.symnot( simsym.exists( otherfd, simsym.symand([ otherfd >= 0, otherfd < internal_ret_fd, self.getproc(pid).fd_map.contains(otherfd) ]))) ])) sock = self.getproc(pid).fd_map.create(internal_ret_fd) sock.domain = domain sock.type = type sock.prot = prot sock.can_read = True sock.can_write = True sock.is_bound = False sock.is_connected = False sock.local_addr = 0 sock.local_port = 0 sock.remote_addr = 0 sock.remote_port = 0 return {'r': internal_ret_fd}
def open(self, pn, creat, excl, trunc, anyfd, pid): # XXX O_RDONLY, O_WRONLY, O_RDWR self.add_selfpid(pid) internal_time = STime.var('internal_time*') created = False anyfd = False _, pndirmap, pnlast = self.nameiparent(pn) if creat: if not pndirmap.contains(pnlast): internal_alloc_inum = SInum.var('internal_alloc_inum*') simsym.assume(simsym.symnot(self.iused(internal_alloc_inum))) simsym.assume( internal_time >= self.i_map[internal_alloc_inum].atime) simsym.assume( internal_time >= self.i_map[internal_alloc_inum].mtime) simsym.assume( internal_time >= self.i_map[internal_alloc_inum].ctime) inode = self.i_map[internal_alloc_inum] inode.data._len = 0 inode.nlink = 1 inode.atime = inode.mtime = inode.ctime = internal_time pndirmap[pnlast] = internal_alloc_inum created = True else: if excl: return {'r': -1, 'errno': errno.EEXIST} if not pndirmap.contains(pnlast): return {'r': -1, 'errno': errno.ENOENT} inum = pndirmap[pnlast] if trunc: if not created: simsym.assume(internal_time >= self.i_map[inum].mtime) simsym.assume(internal_time >= self.i_map[inum].ctime) self.i_map[inum].mtime = internal_time self.i_map[inum].ctime = internal_time self.i_map[inum].data._len = 0 internal_ret_fd = SFdNum.var('internal_ret_fd*') simsym.assume(internal_ret_fd >= 0) simsym.assume( simsym.symnot(self.getproc(pid).fd_map.contains(internal_ret_fd))) ## Lowest FD otherfd = SFdNum.var('fd') simsym.assume( simsym.symor([ anyfd, simsym.symnot( simsym.exists( otherfd, simsym.symand([ otherfd >= 0, otherfd < internal_ret_fd, self.getproc(pid).fd_map.contains(otherfd) ]))) ])) fd_data = self.getproc(pid).fd_map.create(internal_ret_fd) fd_data.inum = inum fd_data.off = 0 fd_data.ispipe = False return {'r': internal_ret_fd}
def test_callset(base, callset, monitors, check_conds=False, print_conds=False): """Test the SIM-commutativity of a call set. base must be a class type for the system state. calls must be the unbound methods of base to test for SIM commutativity. As the test proceeds, this will invoke the appropriate methods of the ExecutionMonitorBase instances in monitors. The caller is responsible for calling the 'finish' method of the monitors after all callsets are done. If check_conds is true, check commutativity conditions for sat/unsat and report this. If print_conds is true, print commutativity conditions. If print_conds is "simplify", use ctx-solver-simplify to further simplify conditions. """ monitor = MetaMonitor([StatMonitor()] + monitors) print " ".join([c.__name__ for c in callset]) monitor.begin_call_set(callset) reporter = progress.ProgressReporter(" " + monitor.get_progress_format(), monitor) condlists = collections.defaultdict(list) terminated = False diverged = set() all_internals = [] for sar in simsym.symbolic_apply(test, base, *callset): if sar.type == "value": is_commutative = len(sar.value.diverge) == 0 diverged.update(sar.value.diverge) condlists[is_commutative].append(sar.path_condition) all_internals.extend(sar.internals) monitor.on_path(sar) if monitor.stop_call_set(): terminated = True break monitor.end_call_set() reporter.end() if terminated: print " enumeration incomplete; skipping conditions" return conds = collections.defaultdict(lambda: [simsym.wrap(z3.BoolVal(False))]) for result, condlist in condlists.items(): conds[result] = condlist if True in condlists: commute = simsym.symor(condlists[True]) # Internal variables help deal with situations where, for the # same assignment of initial state + external inputs, two # operations both can commute and can diverge (depending on # internal choice, like the inode number for file creation). cannot_commute = simsym.symnot(simsym.exists(all_internals, commute)) print_cond("can commute", commute, check_conds, print_conds) else: cannot_commute = True if False in condlists: diverge = simsym.symor(condlists[False]) print_cond( "can not commute; %s" % ", ".join(map(str, diverged)), simsym.symand([diverge, cannot_commute]), check_conds, print_conds, )
projected_calls = list(calls) for p in projections: for c in calls: projected_calls.append(projected_call(p, projections[p], c)) for callset in itertools.combinations_with_replacement(projected_calls, ncomb): print ' '.join([c.__name__ for c in callset]) rvs = simsym.symbolic_apply(test, base, *callset) conds = collections.defaultdict(lambda: simsym.wrap(z3.BoolVal(False))) for cond, res in simsym.combine(rvs): conds[res] = cond pc = simsym.simplify(conds['']) pr = simsym.simplify(simsym.symor([conds['r'], conds['rs']])) ps = simsym.simplify(conds['s']) ex_pc = simsym.exists(simsym.internals(), pc) nex_pc = simsym.symnot(ex_pc) print "nex_pc", nex_pc ex_pr = simsym.exists(simsym.internals(), pr) nex_pr = simsym.symnot(ex_pr) ps2 = simsym.symand([ps, nex_pc, nex_pr]) ps_ex_pr = simsym.symand([ps, ex_pr]) pr2 = simsym.symand([simsym.symor([pr, ps_ex_pr]), nex_pc]) ps_ex_pc = simsym.symand([ps, ex_pc]) pr_ex_pc = simsym.symand([pr, ex_pc]) pc2 = simsym.symor([pc, ps_ex_pc, pr_ex_pc]) for msg, cond in (('commute', pc2), ('results diverge', pr2),
def _declare_assumptions(self, assume): super(ProcessQueue, self)._declare_assumptions(assume) # 'iseq' restriction i = simsym.SInt.var() j = simsym.SInt.var() assume(simsym.symnot(simsym.exists(i, simsym.exists(j, simsym.symand(i != j, i >= 0, j >= 0, i < self.elts.len(), j < self.elts.len(), self.elts[i] == self.elts[j])))))
def pipe(self, pid): self.add_selfpid(pid) internal_pipeid = SPipeId.var('internal_pipeid*') xfd = SFdNum.var('xfd') simsym.assume( simsym.symnot( simsym.symor([ simsym.exists( xfd, simsym.symand([ self.proc0.fd_map.contains(xfd), self.proc0.fd_map._map[xfd].ispipe, self.proc0.fd_map._map[xfd].pipeid == internal_pipeid ])), simsym.exists( xfd, simsym.symand([ self.proc1.fd_map.contains(xfd), self.proc1.fd_map._map[xfd].ispipe, self.proc1.fd_map._map[xfd].pipeid == internal_pipeid ])) ]))) empty_pipe = self.pipes[internal_pipeid] empty_pipe.data._len = 0 ## lowest FD for read end internal_fd_r = SFdNum.var('internal_fd_r*') simsym.assume(internal_fd_r >= 0) simsym.assume( simsym.symnot(self.getproc(pid).fd_map.contains(internal_fd_r))) simsym.assume( simsym.symnot( simsym.exists( xfd, simsym.symand([ xfd >= 0, xfd < internal_fd_r, self.getproc(pid).fd_map.contains(xfd) ])))) fd_r_data = self.getproc(pid).fd_map.create(internal_fd_r) fd_r_data.ispipe = True fd_r_data.pipeid = internal_pipeid fd_r_data.pipewriter = False ## lowest FD for write end internal_fd_w = SFdNum.var('internal_fd_w*') simsym.assume(internal_fd_w >= 0) simsym.assume( simsym.symnot(self.getproc(pid).fd_map.contains(internal_fd_w))) simsym.assume( simsym.symnot( simsym.exists( xfd, simsym.symand([ xfd >= 0, xfd < internal_fd_w, self.getproc(pid).fd_map.contains(xfd) ])))) fd_w_data = self.getproc(pid).fd_map.create(internal_fd_w) fd_w_data.ispipe = True fd_w_data.pipeid = internal_pipeid fd_w_data.pipewriter = True return {'r': 0, 'fds[0]': internal_fd_r, 'fds[1]': internal_fd_w}