int __fd_ftruncate(int fd, off64_t length) { static int n_calls = 0; exe_file_t *f = __get_file(fd); n_calls++; if (!f) { errno = EBADF; return -1; } if (__exe_fs.max_failures && *__exe_fs.ftruncate_fail == n_calls) { __exe_fs.max_failures--; errno = EIO; return -1; } if (f->dfile) { klee_warning("symbolic file, ignoring (EIO)"); errno = EIO; return -1; } #if __WORDSIZE == 64 return syscall(__NR_ftruncate, f->fd, length); #else return syscall(__NR_ftruncate64, f->fd, length); #endif }
int fstatat(int fd, const char *path, struct stat *buf, int flags) { if (fd != AT_FDCWD) { exe_file_t *f = __get_file(fd); if (!f) { errno = EBADF; return -1; } else if (f->dfile) { klee_warning("symbolic file descriptor, ignoring (ENOENT)"); errno = ENOENT; return -1; } fd = f->fd; } exe_disk_file_t *dfile = __get_sym_file(path); if (dfile) { memcpy(buf, dfile->stat, sizeof(*dfile->stat)); return 0; } #if (defined __NR_newfstatat) && (__NR_newfstatat != 0) return syscall(__NR_newfstatat, (long)fd, (path ? __concretize_string(path) : NULL), buf, (long)flags); #else return syscall(__NR_fstatat64, (long)fd, (path ? __concretize_string(path) : NULL), buf, (long)flags); #endif }
int __fd_statfs(const char *path, struct statfs *buf) { exe_disk_file_t *dfile = __get_sym_file(path); if (dfile) { /* XXX incorrect */ klee_warning("symbolic file, ignoring (ENOENT)"); errno = ENOENT; return -1; } return syscall(__NR_statfs, __concretize_string(path), buf); }
int chdir(const char *path) { exe_disk_file_t *dfile = __get_sym_file(path); if (dfile) { /* XXX incorrect */ klee_warning("symbolic file, ignoring (ENOENT)"); errno = ENOENT; return -1; } return syscall(__NR_chdir, __concretize_string(path)); }
int __fd_openat(int basefd, const char *pathname, int flags, mode_t mode) { exe_file_t *f; int fd; if (basefd != AT_FDCWD) { exe_file_t *bf = __get_file(basefd); if (!bf) { errno = EBADF; return -1; } else if (bf->dfile) { klee_warning("symbolic file descriptor, ignoring (ENOENT)"); errno = ENOENT; return -1; } basefd = bf->fd; } if (__get_sym_file(pathname)) { /* for a symbolic file, it doesn't matter if/where it exists on disk */ return __fd_open(pathname, flags, mode); } for (fd = 0; fd < MAX_FDS; ++fd) if (!(__exe_env.fds[fd].flags & eOpen)) break; if (fd == MAX_FDS) { errno = EMFILE; return -1; } f = &__exe_env.fds[fd]; /* Should be the case if file was available, but just in case. */ memset(f, 0, sizeof *f); int os_fd = syscall(__NR_openat, (long)basefd, __concretize_string(pathname), (long)flags, mode); if (os_fd == -1) return -1; f->fd = os_fd; f->flags = eOpen; if ((flags & O_ACCMODE) == O_RDONLY) { f->flags |= eReadable; } else if ((flags & O_ACCMODE) == O_WRONLY) { f->flags |= eWriteable; } else { /* XXX What actually happens here if != O_RDWR. */ f->flags |= eReadable | eWriteable; } return fd; }
int fcntl(int fd, int cmd, ...) { exe_file_t *f = __get_file(fd); va_list ap; unsigned arg; /* 32 bit assumption (int/ptr) */ if (!f) { errno = EBADF; return -1; } if (cmd==F_GETFD || cmd==F_GETFL || cmd==F_GETOWN || cmd==F_GETSIG || cmd==F_GETLEASE || cmd==F_NOTIFY) { arg = 0; } else { va_start(ap, cmd); arg = va_arg(ap, int); va_end(ap); } if (f->dfile) { switch(cmd) { case F_GETFD: { int flags = 0; if (f->flags & eCloseOnExec) flags |= FD_CLOEXEC; return flags; } case F_SETFD: { f->flags &= ~eCloseOnExec; if (arg & FD_CLOEXEC) f->flags |= eCloseOnExec; return 0; } case F_GETFL: { /* XXX (CrC): This should return the status flags: O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, O_NONBLOCK. As of now, we discard these flags during open(). We should save them and return them here. These same flags can be set by F_SETFL, which we could also handle properly. */ return 0; } default: klee_warning("symbolic file, ignoring (EINVAL)"); errno = EINVAL; return -1; } } return syscall(__NR_fcntl, f->fd, cmd, arg); }
/* Trivial model: if path is "/" (basically no change) accept, otherwise reject */ int chroot(const char *path) { if (path[0] == '\0') { errno = ENOENT; return -1; } if (path[0] == '/' && path[1] == '\0') { return 0; } klee_warning("ignoring (ENOENT)"); errno = ENOENT; return -1; }
bool STPSolverImpl::computeInitialValues( const Query &query, const std::vector<const Array *> &objects, std::vector<std::vector<unsigned char> > &values, bool &hasSolution) { runStatusCode = SOLVER_RUN_STATUS_FAILURE; TimerStatIncrementer t(stats::queryTime); vc_push(vc); for (ConstraintManager::const_iterator it = query.constraints.begin(), ie = query.constraints.end(); it != ie; ++it) vc_assertFormula(vc, builder->construct(*it)); ++stats::queries; ++stats::queryCounterexamples; ExprHandle stp_e = builder->construct(query.expr); if (DebugDumpSTPQueries) { char *buf; unsigned long len; vc_printQueryStateToBuffer(vc, stp_e, &buf, &len, false); klee_warning("STP query:\n%.*s\n", (unsigned)len, buf); } bool success; if (useForkedSTP) { runStatusCode = runAndGetCexForked(vc, builder, stp_e, objects, values, hasSolution, timeout); success = ((SOLVER_RUN_STATUS_SUCCESS_SOLVABLE == runStatusCode) || (SOLVER_RUN_STATUS_SUCCESS_UNSOLVABLE == runStatusCode)); } else { runStatusCode = runAndGetCex(vc, builder, stp_e, objects, values, hasSolution); success = true; } if (success) { if (hasSolution) ++stats::queriesInvalid; else ++stats::queriesValid; } vc_pop(vc); return success; }
int fstatfs(int fd, struct statfs *buf) { exe_file_t *f = __get_file(fd); if (!f) { errno = EBADF; return -1; } if (f->dfile) { klee_warning("symbolic file, ignoring (EBADF)"); errno = EBADF; return -1; } return syscall(__NR_fstatfs, f->fd, buf); }
int fchdir(int fd) { exe_file_t *f = __get_file(fd); if (!f) { errno = EBADF; return -1; } if (f->dfile) { klee_warning("symbolic file, ignoring (ENOENT)"); errno = ENOENT; return -1; } return syscall(__NR_fchdir, f->fd); }
int rmdir(const char *pathname) { exe_disk_file_t *dfile = __get_sym_file(pathname); if (dfile) { /* XXX check access */ if (S_ISDIR(dfile->stat->st_mode)) { dfile->stat->st_ino = 0; return 0; } else { errno = ENOTDIR; return -1; } } klee_warning("ignoring (EPERM)"); errno = EPERM; return -1; }
int futimesat(int fd, const char* path, const struct timeval times[2]) { if (fd != AT_FDCWD) { exe_file_t *f = __get_file(fd); if (!f) { errno = EBADF; return -1; } else if (f->dfile) { klee_warning("symbolic file descriptor, ignoring (ENOENT)"); errno = ENOENT; return -1; } fd = f->fd; } if (__get_sym_file(path)) { return utimes(path, times); } return syscall(__NR_futimesat, (long)fd, (path ? __concretize_string(path) : NULL), times); }
int unlinkat(int dirfd, const char *pathname, int flags) { /* similar to unlink. keep them separated though to avoid problems if unlink changes to actually delete files */ exe_disk_file_t *dfile = __get_sym_file(pathname); if (dfile) { /* XXX check access */ if (S_ISREG(dfile->stat->st_mode)) { dfile->stat->st_ino = 0; return 0; } else if (S_ISDIR(dfile->stat->st_mode)) { errno = EISDIR; return -1; } else { errno = EPERM; return -1; } } klee_warning("ignoring (EPERM)"); errno = EPERM; return -1; }
ssize_t write(int fd, const void *buf, size_t count) { static int n_calls = 0; exe_file_t *f; n_calls++; f = __get_file(fd); if (!f) { errno = EBADF; return -1; } if (__exe_fs.max_failures && *__exe_fs.write_fail == n_calls) { __exe_fs.max_failures--; errno = EIO; return -1; } if (!f->dfile) { int r; buf = __concretize_ptr(buf); count = __concretize_size(count); /* XXX In terms of looking for bugs we really should do this check before concretization, at least once the routine has been fixed to properly work with symbolics. */ klee_check_memory_access(buf, count); if (f->fd == 1 || f->fd == 2) r = syscall(__NR_write, f->fd, buf, count); else r = syscall(__NR_pwrite64, f->fd, buf, count, (off64_t) f->off); if (r == -1) return -1; assert(r >= 0); if (f->fd != 1 && f->fd != 2) f->off += r; return r; } else { /* symbolic file */ size_t actual_count = 0; if (f->off + count <= f->dfile->size) actual_count = count; else { if (__exe_env.save_all_writes) assert(0); else { if (f->off < (off64_t) f->dfile->size) actual_count = f->dfile->size - f->off; } } if (actual_count) memcpy(f->dfile->contents + f->off, buf, actual_count); if (count != actual_count) klee_warning("write() ignores bytes.\n"); if (f->dfile == __exe_fs.sym_stdout) __exe_fs.stdout_writes += actual_count; f->off += count; return count; } }
static SolverImpl::SolverRunStatus runAndGetCexForked(::VC vc, STPBuilder *builder, ::VCExpr q, const std::vector<const Array *> &objects, std::vector<std::vector<unsigned char> > &values, bool &hasSolution, double timeout) { unsigned char *pos = shared_memory_ptr; unsigned sum = 0; for (std::vector<const Array *>::const_iterator it = objects.begin(), ie = objects.end(); it != ie; ++it) sum += (*it)->size; if (sum >= shared_memory_size) llvm::report_fatal_error("not enough shared memory for counterexample"); fflush(stdout); fflush(stderr); int pid = fork(); if (pid == -1) { klee_warning("fork failed (for STP)"); if (!IgnoreSolverFailures) exit(1); return SolverImpl::SOLVER_RUN_STATUS_FORK_FAILED; } if (pid == 0) { if (timeout) { ::alarm(0); /* Turn off alarm so we can safely set signal handler */ ::signal(SIGALRM, stpTimeoutHandler); ::alarm(std::max(1, (int)timeout)); } unsigned res = vc_query(vc, q); if (!res) { for (std::vector<const Array *>::const_iterator it = objects.begin(), ie = objects.end(); it != ie; ++it) { const Array *array = *it; for (unsigned offset = 0; offset < array->size; offset++) { ExprHandle counter = vc_getCounterExample(vc, builder->getInitialRead(array, offset)); *pos++ = getBVUnsigned(counter); } } } _exit(res); } else { int status; pid_t res; do { res = waitpid(pid, &status, 0); } while (res < 0 && errno == EINTR); if (res < 0) { klee_warning("waitpid() for STP failed"); if (!IgnoreSolverFailures) exit(1); return SolverImpl::SOLVER_RUN_STATUS_WAITPID_FAILED; } // From timed_run.py: It appears that linux at least will on // "occasion" return a status when the process was terminated by a // signal, so test signal first. if (WIFSIGNALED(status) || !WIFEXITED(status)) { klee_warning("STP did not return successfully. Most likely you forgot " "to run 'ulimit -s unlimited'"); if (!IgnoreSolverFailures) { exit(1); } return SolverImpl::SOLVER_RUN_STATUS_INTERRUPTED; } int exitcode = WEXITSTATUS(status); if (exitcode == 0) { hasSolution = true; } else if (exitcode == 1) { hasSolution = false; } else if (exitcode == 52) { klee_warning("STP timed out"); // mark that a timeout occurred return SolverImpl::SOLVER_RUN_STATUS_TIMEOUT; } else { klee_warning("STP did not return a recognized code"); if (!IgnoreSolverFailures) exit(1); return SolverImpl::SOLVER_RUN_STATUS_UNEXPECTED_EXIT_CODE; } if (hasSolution) { values = std::vector<std::vector<unsigned char> >(objects.size()); unsigned i = 0; for (std::vector<const Array *>::const_iterator it = objects.begin(), ie = objects.end(); it != ie; ++it) { const Array *array = *it; std::vector<unsigned char> &data = values[i++]; data.insert(data.begin(), pos, pos + array->size); pos += array->size; } } if (true == hasSolution) { return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_SOLVABLE; } else { return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_UNSOLVABLE; } } }
SolverImpl::SolverRunStatus Z3SolverImpl::handleSolverResponse( ::Z3_solver theSolver, ::Z3_lbool satisfiable, const std::vector<const Array *> *objects, std::vector<std::vector<unsigned char> > *values, bool &hasSolution) { switch (satisfiable) { case Z3_L_TRUE: { hasSolution = true; if (!objects) { // No assignment is needed assert(values == NULL); return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_SOLVABLE; } assert(values && "values cannot be nullptr"); ::Z3_model theModel = Z3_solver_get_model(builder->ctx, theSolver); assert(theModel && "Failed to retrieve model"); Z3_model_inc_ref(builder->ctx, theModel); values->reserve(objects->size()); for (std::vector<const Array *>::const_iterator it = objects->begin(), ie = objects->end(); it != ie; ++it) { const Array *array = *it; std::vector<unsigned char> data; data.reserve(array->size); for (unsigned offset = 0; offset < array->size; offset++) { // We can't use Z3ASTHandle here so have to do ref counting manually ::Z3_ast arrayElementExpr; Z3ASTHandle initial_read = builder->getInitialRead(array, offset); bool successfulEval = Z3_model_eval(builder->ctx, theModel, initial_read, /*model_completion=*/Z3_TRUE, &arrayElementExpr); assert(successfulEval && "Failed to evaluate model"); Z3_inc_ref(builder->ctx, arrayElementExpr); assert(Z3_get_ast_kind(builder->ctx, arrayElementExpr) == Z3_NUMERAL_AST && "Evaluated expression has wrong sort"); int arrayElementValue = 0; bool successGet = Z3_get_numeral_int(builder->ctx, arrayElementExpr, &arrayElementValue); assert(successGet && "failed to get value back"); assert(arrayElementValue >= 0 && arrayElementValue <= 255 && "Integer from model is out of range"); data.push_back(arrayElementValue); Z3_dec_ref(builder->ctx, arrayElementExpr); } values->push_back(data); } // Validate the model if requested if (Z3ValidateModels) { bool success = validateZ3Model(theSolver, theModel); if (!success) abort(); } Z3_model_dec_ref(builder->ctx, theModel); return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_SOLVABLE; } case Z3_L_FALSE: hasSolution = false; return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_UNSOLVABLE; case Z3_L_UNDEF: { ::Z3_string reason = ::Z3_solver_get_reason_unknown(builder->ctx, theSolver); if (strcmp(reason, "timeout") == 0 || strcmp(reason, "canceled") == 0 || strcmp(reason, "(resource limits reached)") == 0) { return SolverImpl::SOLVER_RUN_STATUS_TIMEOUT; } if (strcmp(reason, "unknown") == 0) { return SolverImpl::SOLVER_RUN_STATUS_FAILURE; } klee_warning("Unexpected solver failure. Reason is \"%s,\"\n", reason); abort(); } default: llvm_unreachable("unhandled Z3 result"); } }
int ioctl(int fd, unsigned long int request, ...) { #else int ioctl(int fd, unsigned long request, ...) { #endif exe_file_t *f = __get_file(fd); va_list ap; void *buf; #if 0 printf("In ioctl(%d, ...)\n", fd); #endif if (!f) { errno = EBADF; return -1; } va_start(ap, request); buf = va_arg(ap, void*); va_end(ap); if (f->dfile) { struct stat *stat = (struct stat*) f->dfile->stat; switch (request) { case TCGETS: { struct termios *ts = buf; klee_warning_once("(TCGETS) symbolic file, incomplete model"); /* XXX need more data, this is ok but still not good enough */ if (S_ISCHR(stat->st_mode)) { /* Just copied from my system, munged to match what fields uclibc thinks are there. */ ts->c_iflag = 27906; ts->c_oflag = 5; ts->c_cflag = 1215; ts->c_lflag = 35287; ts->c_line = 0; ts->c_cc[0] = '\x03'; ts->c_cc[1] = '\x1c'; ts->c_cc[2] = '\x7f'; ts->c_cc[3] = '\x15'; ts->c_cc[4] = '\x04'; ts->c_cc[5] = '\x00'; ts->c_cc[6] = '\x01'; ts->c_cc[7] = '\xff'; ts->c_cc[8] = '\x11'; ts->c_cc[9] = '\x13'; ts->c_cc[10] = '\x1a'; ts->c_cc[11] = '\xff'; ts->c_cc[12] = '\x12'; ts->c_cc[13] = '\x0f'; ts->c_cc[14] = '\x17'; ts->c_cc[15] = '\x16'; ts->c_cc[16] = '\xff'; ts->c_cc[17] = '\x0'; ts->c_cc[18] = '\x0'; return 0; } else { errno = ENOTTY; return -1; } } case TCSETS: { /* const struct termios *ts = buf; */ klee_warning_once("(TCSETS) symbolic file, silently ignoring"); if (S_ISCHR(stat->st_mode)) { return 0; } else { errno = ENOTTY; return -1; } } case TCSETSW: { /* const struct termios *ts = buf; */ klee_warning_once("(TCSETSW) symbolic file, silently ignoring"); if (fd==0) { return 0; } else { errno = ENOTTY; return -1; } } case TCSETSF: { /* const struct termios *ts = buf; */ klee_warning_once("(TCSETSF) symbolic file, silently ignoring"); if (S_ISCHR(stat->st_mode)) { return 0; } else { errno = ENOTTY; return -1; } } case TIOCGWINSZ: { struct winsize *ws = buf; ws->ws_row = 24; ws->ws_col = 80; klee_warning_once("(TIOCGWINSZ) symbolic file, incomplete model"); if (S_ISCHR(stat->st_mode)) { return 0; } else { errno = ENOTTY; return -1; } } case TIOCSWINSZ: { /* const struct winsize *ws = buf; */ klee_warning_once("(TIOCSWINSZ) symbolic file, ignoring (EINVAL)"); if (S_ISCHR(stat->st_mode)) { errno = EINVAL; return -1; } else { errno = ENOTTY; return -1; } } case FIONREAD: { int *res = buf; klee_warning_once("(FIONREAD) symbolic file, incomplete model"); if (S_ISCHR(stat->st_mode)) { if (f->off < (off64_t) f->dfile->size) { *res = f->dfile->size - f->off; } else { *res = 0; } return 0; } else { errno = ENOTTY; return -1; } } case MTIOCGET: { klee_warning("(MTIOCGET) symbolic file, ignoring (EINVAL)"); errno = EINVAL; return -1; } default: klee_warning("symbolic file, ignoring (EINVAL)"); errno = EINVAL; return -1; } } return syscall(__NR_ioctl, f->fd, request, buf); }
int __fd_getdents(unsigned int fd, struct dirent64 *dirp, unsigned int count) { exe_file_t *f = __get_file(fd); if (!f) { errno = EBADF; return -1; } if (f->dfile) { klee_warning("symbolic file, ignoring (EINVAL)"); errno = EINVAL; return -1; } else { if ((unsigned long) f->off < 4096u) { /* Return our dirents */ off64_t i, pad, bytes=0; /* What happens for bad offsets? */ i = f->off / sizeof(*dirp); if (((off64_t) (i * sizeof(*dirp)) != f->off) || i > __exe_fs.n_sym_files) { errno = EINVAL; return -1; } for (; i<__exe_fs.n_sym_files; ++i) { exe_disk_file_t *df = &__exe_fs.sym_files[i]; dirp->d_ino = df->stat->st_ino; dirp->d_reclen = sizeof(*dirp); dirp->d_type = IFTODT(df->stat->st_mode); dirp->d_name[0] = 'A' + i; dirp->d_name[1] = '\0'; dirp->d_off = (i+1) * sizeof(*dirp); bytes += dirp->d_reclen; ++dirp; } /* Fake jump to OS records by a "deleted" file. */ pad = count>=4096 ? 4096 : count; dirp->d_ino = 0; dirp->d_reclen = pad - bytes; dirp->d_type = DT_UNKNOWN; dirp->d_name[0] = '\0'; dirp->d_off = 4096; bytes += dirp->d_reclen; f->off = pad; return bytes; } else { off64_t os_pos = f->off - 4096; int res; off64_t s = 0; /* For reasons which I really don't understand, if I don't memset this then sometimes the kernel returns d_ino==0 for some valid entries? Am I crazy? Can writeback possibly be failing? Even more bizarre, interchanging the memset and the seek also case strange behavior. Really should be debugged properly. */ memset(dirp, 0, count); s = syscall(__NR_lseek, f->fd, os_pos, SEEK_SET); assert(s != (off64_t) -1); res = syscall(__NR_getdents64, f->fd, dirp, count); if (res > -1) { int pos = 0; f->off = syscall(__NR_lseek, f->fd, 0, SEEK_CUR); assert(f->off != (off64_t)-1); f->off += 4096; /* Patch offsets */ while (pos < res) { struct dirent64 *dp = (struct dirent64*) ((char*) dirp + pos); dp->d_off += 4096; pos += dp->d_reclen; } } return res; } } }
static int __df_chown(exe_disk_file_t *df, uid_t owner, gid_t group) { klee_warning("symbolic file, ignoring (EPERM)"); errno = EPERM; return -1; }
int pthread_attr_destroy(pthread_attr_t *attr) { klee_warning("pthread_attr_destroy does nothing"); return 0; }
int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) { printf("Hello the exp is f*****g working"); printf("**********************This is the weak reference of getaddrinfo***********************\n"); if (node == NULL && service == NULL) { return EAI_NONAME; } if (hints) { if (hints->ai_family != AF_INET && hints->ai_family != AF_UNSPEC) { klee_warning("unsupported family (EAI_ADDRFAMILY)"); return EAI_ADDRFAMILY; } if (hints->ai_socktype != SOCK_STREAM && hints->ai_socktype != 0) { klee_warning("unsupported socket type (EAI_SOCKTYPE)"); return EAI_SOCKTYPE; } if (hints->ai_protocol != 0 && hints->ai_protocol != IPPROTO_TCP) { klee_warning("unsupported protocol (EAI_SERVICE)"); return EAI_SERVICE; } // We kinda ignore all the flags, they don't make sense given the // current limitations of the model. if (hints->ai_addr || hints->ai_addrlen || hints->ai_canonname || hints->ai_next) { return EAI_SYSTEM; } } int port = 0; if (service != NULL) { klee_warning("Getting the port number for service\n"); port = atoi(service); if (port == 0 && strcmp(service, "0") != 0) { klee_warning("service name not numeric, unsupported by model"); return EAI_SERVICE; } if (port < 0 || port > 65535) { return EAI_SERVICE; } } if (node != NULL) { if (strcmp(node, "localhost") != 0 && strcmp(node, DEFAULT_HOST_NAME) != 0) { klee_warning("resolving to localhost\n"); } } struct addrinfo *info = (struct addrinfo*)malloc(sizeof(struct addrinfo)); memset(info, 0, sizeof(struct addrinfo)); struct sockaddr_in *addr = (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in)); memset(addr, 0, sizeof(struct sockaddr_in)); info->ai_addr = (struct sockaddr*)addr; info->ai_addrlen = sizeof(struct sockaddr_in); info->ai_family = AF_INET; info->ai_protocol = 0; info->ai_socktype = SOCK_STREAM; addr->sin_family = AF_INET; addr->sin_addr.s_addr = htonl(DEFAULT_NETWORK_ADDR); if (port != 0) addr->sin_port = htons((uint16_t)port); *res = info; return 0; }
int __fd_open(const char *pathname, int flags, mode_t mode) { exe_disk_file_t *df; exe_file_t *f; int fd; for (fd = 0; fd < MAX_FDS; ++fd) if (!(__exe_env.fds[fd].flags & eOpen)) break; if (fd == MAX_FDS) { errno = EMFILE; return -1; } f = &__exe_env.fds[fd]; /* Should be the case if file was available, but just in case. */ memset(f, 0, sizeof *f); df = __get_sym_file(pathname); if (df) { /* XXX Should check access against mode / stat / possible deletion. */ f->dfile = df; if ((flags & O_CREAT) && (flags & O_EXCL)) { errno = EEXIST; return -1; } if ((flags & O_TRUNC) && (flags & O_RDONLY)) { /* The result of using O_TRUNC with O_RDONLY is undefined, so we return error */ klee_warning("Undefined call to open(): O_TRUNC | O_RDONLY\n"); errno = EACCES; return -1; } if ((flags & O_EXCL) && !(flags & O_CREAT)) { /* The result of using O_EXCL without O_CREAT is undefined, so we return error */ klee_warning("Undefined call to open(): O_EXCL w/o O_RDONLY\n"); errno = EACCES; return -1; } if (!has_permission(flags, df->stat)) { errno = EACCES; return -1; } else f->dfile->stat->st_mode = ((f->dfile->stat->st_mode & ~0777) | (mode & ~__exe_env.umask)); } else { int os_fd = syscall(__NR_open, __concretize_string(pathname), flags, mode); if (os_fd == -1) return -1; f->fd = os_fd; } f->flags = eOpen; if ((flags & O_ACCMODE) == O_RDONLY) { f->flags |= eReadable; } else if ((flags & O_ACCMODE) == O_WRONLY) { f->flags |= eWriteable; } else { /* XXX What actually happens here if != O_RDWR. */ f->flags |= eReadable | eWriteable; } return fd; }
SolverImpl::SolverRunStatus MetaSMTSolverImpl<SolverContext>::runAndGetCexForked( const Query &query, const std::vector<const Array *> &objects, std::vector<std::vector<unsigned char> > &values, bool &hasSolution, double timeout) { unsigned char *pos = shared_memory_ptr; unsigned sum = 0; for (std::vector<const Array *>::const_iterator it = objects.begin(), ie = objects.end(); it != ie; ++it) { sum += (*it)->size; } // sum += sizeof(uint64_t); sum += sizeof(stats::queryConstructs); assert(sum < shared_memory_size && "not enough shared memory for counterexample"); fflush(stdout); fflush(stderr); int pid = fork(); if (pid == -1) { klee_warning("fork failed (for metaSMT)"); return (SolverImpl::SOLVER_RUN_STATUS_FORK_FAILED); } if (pid == 0) { if (timeout) { ::alarm(0); /* Turn off alarm so we can safely set signal handler */ ::signal(SIGALRM, metaSMTTimeoutHandler); ::alarm(std::max(1, (int)timeout)); } for (ConstraintManager::const_iterator it = query.constraints.begin(), ie = query.constraints.end(); it != ie; ++it) { assertion(_meta_solver, _builder->construct(*it)); // assumption(_meta_solver, _builder->construct(*it)); } std::vector<std::vector<typename SolverContext::result_type> > aux_arr_exprs; if (MetaSMTBackend == METASMT_BACKEND_BOOLECTOR) { for (std::vector<const Array *>::const_iterator it = objects.begin(), ie = objects.end(); it != ie; ++it) { std::vector<typename SolverContext::result_type> aux_arr; const Array *array = *it; assert(array); typename SolverContext::result_type array_exp = _builder->getInitialArray(array); for (unsigned offset = 0; offset < array->size; offset++) { typename SolverContext::result_type elem_exp = evaluate( _meta_solver, metaSMT::logic::Array::select( array_exp, bvuint(offset, array->getDomain()))); aux_arr.push_back(elem_exp); } aux_arr_exprs.push_back(aux_arr); } assert(aux_arr_exprs.size() == objects.size()); } // assume the negation of the query // can be also asserted instead of assumed as we are in a child process assumption(_meta_solver, _builder->construct(Expr::createIsZero(query.expr))); unsigned res = solve(_meta_solver); if (res) { if (MetaSMTBackend != METASMT_BACKEND_BOOLECTOR) { for (std::vector<const Array *>::const_iterator it = objects.begin(), ie = objects.end(); it != ie; ++it) { const Array *array = *it; assert(array); typename SolverContext::result_type array_exp = _builder->getInitialArray(array); for (unsigned offset = 0; offset < array->size; offset++) { typename SolverContext::result_type elem_exp = evaluate(_meta_solver, metaSMT::logic::Array::select( array_exp, bvuint(offset, array->getDomain()))); unsigned char elem_value = metaSMT::read_value(_meta_solver, elem_exp); *pos++ = elem_value; } } } else { typename std::vector< std::vector<typename SolverContext::result_type> >::const_iterator eit = aux_arr_exprs.begin(), eie = aux_arr_exprs.end(); for (std::vector<const Array *>::const_iterator it = objects.begin(), ie = objects.end(); it != ie, eit != eie; ++it, ++eit) { const Array *array = *it; const std::vector<typename SolverContext::result_type> &arr_exp = *eit; assert(array); assert(array->size == arr_exp.size()); for (unsigned offset = 0; offset < array->size; offset++) { unsigned char elem_value = metaSMT::read_value(_meta_solver, arr_exp[offset]); *pos++ = elem_value; } } } } assert((uint64_t *)pos); *((uint64_t *)pos) = stats::queryConstructs; _exit(!res); } else { int status; pid_t res; do { res = waitpid(pid, &status, 0); } while (res < 0 && errno == EINTR); if (res < 0) { klee_warning("waitpid() for metaSMT failed"); return (SolverImpl::SOLVER_RUN_STATUS_WAITPID_FAILED); } // From timed_run.py: It appears that linux at least will on // "occasion" return a status when the process was terminated by a // signal, so test signal first. if (WIFSIGNALED(status) || !WIFEXITED(status)) { klee_warning( "error: metaSMT did not return successfully (status = %d) \n", WTERMSIG(status)); return (SolverImpl::SOLVER_RUN_STATUS_INTERRUPTED); } int exitcode = WEXITSTATUS(status); if (exitcode == 0) { hasSolution = true; } else if (exitcode == 1) { hasSolution = false; } else if (exitcode == 52) { klee_warning("metaSMT timed out"); return (SolverImpl::SOLVER_RUN_STATUS_TIMEOUT); } else { klee_warning("metaSMT did not return a recognized code"); return (SolverImpl::SOLVER_RUN_STATUS_UNEXPECTED_EXIT_CODE); } if (hasSolution) { values = std::vector<std::vector<unsigned char> >(objects.size()); unsigned i = 0; for (std::vector<const Array *>::const_iterator it = objects.begin(), ie = objects.end(); it != ie; ++it) { const Array *array = *it; assert(array); std::vector<unsigned char> &data = values[i++]; data.insert(data.begin(), pos, pos + array->size); pos += array->size; } } stats::queryConstructs += (*((uint64_t *)pos) - stats::queryConstructs); if (true == hasSolution) { return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_SOLVABLE; } else { return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_UNSOLVABLE; } } }
int pthread_attr_init(pthread_attr_t *attr) { klee_warning("pthread_attr_init does nothing"); return 0; }