static bool verify_header(struct loader *loader) { const m0_mobheader *header = (m0_mobheader *)read(loader, sizeof *header); if(!header) return 0; if(memcmp(header->magic, HEADER.magic, sizeof HEADER.magic)) { cry(loader, "file <%s> has wrong magic number", loader->name); return 0; } if(memcmp(header->version, HEADER.version, sizeof HEADER.version)) { cry(loader, "file <%s> has wrong version", loader->name); return 0; } if(memcmp(header->config, HEADER.config, sizeof HEADER.config)) { cry(loader, "file <%s> has wrong type configuration", loader->name); return 0; } if(header->size != loader->size) { cry(loader, "file <%s> has incorrect size", loader->name); return 0; } return 1; }
static int load_dll(struct mg_context *ctx, const char *dll_name, struct ssl_func *sw) { union {void *p; void (*fp)(void);} u; void *dll_handle; struct ssl_func *fp; if ((dll_handle = dlopen(dll_name, RTLD_LAZY)) == NULL) { cry(fc(ctx), "%s: cannot load %s", __func__, dll_name); return 0; } for (fp = sw; fp->name != NULL; fp++) { #ifdef _WIN32 // GetProcAddress() returns pointer to function u.fp = (void (*)(void)) dlsym(dll_handle, fp->name); #else // dlsym() on UNIX returns void *. ISO C forbids casts of data pointers to // function pointers. We need to use a union to make a cast. u.p = dlsym(dll_handle, fp->name); #endif // _WIN32 if (u.fp == NULL) { cry(fc(ctx), "%s: %s: cannot find %s", __func__, dll_name, fp->name); return 0; } else { fp->ptr = u.fp; } } return 1; }
static bool load_chunks(struct loader *loader) { const m0_segment *dir = (m0_segment *)read(loader, sizeof *dir); if(!dir) return 0; // TODO: verify id - need to come up with a general scheme if(!m0_interp_reserve_chunks(loader->interp, dir->entry_count) || !m0_interp_reserve_chunk_map_slots(loader->interp, dir->entry_count)) { cry(loader, "failed to reserve %u chunks for file <%s>", (unsigned)dir->entry_count, loader->name); return 0; } for(size_t i = 0; i < dir->entry_count; ++i) { const m0_direntry *entry = (m0_direntry *)read(loader, sizeof *entry); if(!entry) return 0; // no need to rollback reserved chunks: // the worst that can happen are superfluous realloc() calls uint32_t *blocks = (uint32_t *)loader->mapping; if(entry->const_offset % sizeof *blocks || entry->meta_offset % sizeof *blocks || entry->code_offset % sizeof *blocks) { cry(loader, "illegal offsets in file <%s>", loader->name); return 0; } const m0_chunk chunk = { (m0_string *)loader->cursor, (m0_segment *)(blocks + entry->const_offset / sizeof *blocks), (m0_segment *)(blocks + entry->meta_offset / sizeof *blocks), (m0_segment *)(blocks + entry->code_offset / sizeof *blocks) }; size_t chunk_id = m0_interp_push_reserved_chunk( loader->interp, &chunk); if(!m0_interp_register_reserved_chunk( loader->interp, chunk.name, chunk_id)) { cry(loader, "allocation failure while loading file <%s>", loader->name); return 0; } // skip name read(loader, entry->byte_size - sizeof *entry); } return 1; }
// Dynamically load SSL library. Set up ctx->ssl_ctx pointer. static int set_ssl_option(struct mg_context *ctx) { int i, size; const char *pem; // If PEM file is not specified and the init_ssl callback // is not specified, skip SSL initialization. if ((pem = ctx->config[SSL_CERTIFICATE]) == NULL) { // MG_INIT_SSL // ctx->callbacks.init_ssl == NULL) { return 1; } #if !defined(NO_SSL_DL) if (!load_dll(ctx, SSL_LIB, ssl_sw) || !load_dll(ctx, CRYPTO_LIB, crypto_sw)) { return 0; } #endif // NO_SSL_DL // Initialize SSL library SSL_library_init(); SSL_load_error_strings(); if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) { cry(fc(ctx), "SSL_CTX_new (server) error: %s", ssl_error()); return 0; } // If user callback returned non-NULL, that means that user callback has // set up certificate itself. In this case, skip sertificate setting. // MG_INIT_SSL if (SSL_CTX_use_certificate_file(ctx->ssl_ctx, pem, 1) == 0 || SSL_CTX_use_PrivateKey_file(ctx->ssl_ctx, pem, 1) == 0) { cry(fc(ctx), "%s: cannot open %s: %s", __func__, pem, ssl_error()); return 0; } if (pem != NULL) { (void) SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, pem); } // Initialize locking callbacks, needed for thread safety. // http://www.openssl.org/support/faq.html#PROG1 size = sizeof(pthread_mutex_t) * CRYPTO_num_locks(); if ((ssl_mutexes = (pthread_mutex_t *) malloc((size_t)size)) == NULL) { cry(fc(ctx), "%s: cannot allocate mutexes: %s", __func__, ssl_error()); return 0; } for (i = 0; i < CRYPTO_num_locks(); i++) { pthread_mutex_init(&ssl_mutexes[i], NULL); } CRYPTO_set_locking_callback(&ssl_locking_callback); CRYPTO_set_id_callback(&ssl_id_callback); return 1; }
REPLACE_STATIC pid_t spawn_process(struct mg_connection *conn, const char *prog, char *envblk, char *envp[], int fd_stdin, int fd_stdout, const char *dir) { pid_t pid; const char *interp; envblk = NULL; // Unused if ((pid = fork()) == -1) { // Parent send_http_error(conn, 500, http_500_error, "fork(): %s", strerror(ERRNO)); } else if (pid == 0) { // Child if (chdir(dir) != 0) { cry(conn, "%s: chdir(%s): %s", __func__, dir, strerror(ERRNO)); } else if (dup2(fd_stdin, 0) == -1) { cry(conn, "%s: dup2(%d, 0): %s", __func__, fd_stdin, strerror(ERRNO)); } else if (dup2(fd_stdout, 1) == -1) { cry(conn, "%s: dup2(%d, 1): %s", __func__, fd_stdout, strerror(ERRNO)); } else { (void) dup2(fd_stdout, 2); (void) close(fd_stdin); (void) close(fd_stdout); // After exec, all signal handlers are restored to their default values, // with one exception of SIGCHLD. According to POSIX.1-2001 and Linux's // implementation, SIGCHLD's handler will leave unchanged after exec // if it was set to be ignored. Restore it to default action. signal(SIGCHLD, SIG_DFL); interp = conn->ctx->config[CGI_INTERPRETER]; if (interp == NULL) { (void) execle(prog, prog, NULL, envp); cry(conn, "%s: execle(%s): %s", __func__, prog, strerror(ERRNO)); } else { (void) execle(interp, interp, prog, NULL, envp); cry(conn, "%s: execle(%s %s): %s", __func__, interp, prog, strerror(ERRNO)); } } exit(EXIT_FAILURE); } // Parent. Close stdio descriptors (void) close(fd_stdin); (void) close(fd_stdout); return pid; }
struct mg_context *mg_start(mg_callback_t user_callback, void *user_data, int port) { struct mg_context *ctx; // Allocate context and initialize reasonable general case defaults. // TODO(lsm): do proper error handling here. ctx = (struct mg_context *) calloc(1, sizeof(*ctx)); ctx->user_callback = user_callback; ctx->user_data = user_data; if (!set_ports_option(ctx, port)) { free_context(ctx); return NULL; } // Ignore SIGPIPE signal, so if browser cancels the request, it // won't kill the whole process. (void) signal(SIGPIPE, SIG_IGN); (void) pthread_mutex_init(&ctx->mutex, NULL); (void) pthread_cond_init(&ctx->cond, NULL); (void) pthread_cond_init(&ctx->sq_empty, NULL); (void) pthread_cond_init(&ctx->sq_full, NULL); // Start master (listening) thread start_thread(ctx, (mg_thread_func_t) master_thread, ctx); // Start worker threads for (int i = 0; i < NUM_THREADS; i++) { if (start_thread(ctx, (mg_thread_func_t) worker_thread, ctx) != 0) { cry(fc(ctx), "Cannot start worker thread: %d", ERRNO); } else { ctx->num_threads++; } } return ctx; }
/* * Send error message back to a client. */ int send_error(struct mg_connection *conn, int status, const char *reason, const char *fmt, ...) { va_list ap; conn->status_code = status; (void) mg_printf(conn, "HTTP/1.1 %d %s\r\n" "Content-Type: text/html\r\n" "Connection: close\r\n" "\r\n", status, reason); /* Errors 1xx, 204 and 304 MUST NOT send a body */ if(status > 199 && status != 204 && status != 304) { char buf[BUFSIZ]; int len; conn->num_bytes_sent = 0; va_start(ap, fmt); len = mg_vsnprintf(conn, buf, sizeof(buf), fmt, ap); va_end(ap); conn->num_bytes_sent += mg_write(conn, buf, len); cry(conn, "%s", buf); } return(1); }
void mg_send_http_error(struct mg_connection *conn, int status, const char *reason, const char *fmt, ...) { char buf[BUFSIZ]; va_list ap; int len; conn->request_info.status_code = status; buf[0] = '\0'; len = 0; /* Errors 1xx, 204 and 304 MUST NOT send a body */ if (status > 199 && status != 204 && status != 304) { len = mg_snprintf(conn, buf, sizeof(buf), "Error %d: %s", status, reason); cry(conn, "%s", buf); buf[len++] = '\n'; va_start(ap, fmt); len += mg_vsnprintf(conn, buf + len, sizeof(buf) - len, fmt, ap); va_end(ap); } DEBUG_TRACE(("[%s]", buf)); mg_printf(conn, "HTTP/1.1 %d %s\r\n" "Content-Type: text/plain\r\n" "Content-Length: %d\r\n" "Connection: %s\r\n\r\n", status, reason, len, suggest_connection_header(conn)); conn->num_bytes_sent += mg_printf(conn, "%s", buf); }
// Like snprintf(), but never returns negative value, or the value // that is larger than a supplied buffer. // Thanks to Adam Zeldis to pointing snprintf()-caused vulnerability // in his audit report. static int mg_vsnprintf(struct mg_connection *conn, char *buf, size_t buflen, const char *fmt, va_list ap) { int n; if (buflen == 0) return 0; n = vsnprintf(buf, buflen, fmt, ap); if (n < 0) { cry(conn, "vsnprintf error"); n = 0; } else if (n >= (int) buflen) { cry(conn, "truncating vsnprintf buffer: [%.*s]", n > 200 ? 200 : n, buf); n = (int) buflen - 1; } buf[n] = '\0'; return n; }
c_prog (EIF_OBJ animals) { int i; EIF_OBJ eiffel_string; char* c_string; for (i=array_of_animal_lower(animals); i <= array_of_animal_upper(animals); i++) { eiffel_string = cry(array_of_animal_item(animals,i)); c_string = string_to_external(eiffel_string); printf("%s\n",c_string); } }
static inline void *read(struct loader *loader, size_t size) { assert(size % sizeof *loader->cursor == 0); if(loader->remaining < size) { cry(loader, "premature end of file <%s>", loader->name); return NULL; } void *mark = loader->cursor; loader->remaining -= size; loader->cursor += size / sizeof *loader->cursor; return mark; }
void make_symbol_used(const char *key) { struct SYM *p = (struct SYM *)get_symbol(key); // wrong cast if (!p) { die("symbol '%s' not defined\n", key); } if (p->type != SYMBOL_EXTERN) { if (p->type != SYMBOL_NORMAL) { cry("using symbol '%s' is probably wrong\n", key); } p->used = USED; } }
static void maybe_symbol_forward(const char *arg) { char *tmp = copy_address_sym(arg); if (tmp) { add_symbol_forward(tmp, 0); if (try_symbol_extern(tmp)) { die("symbol '%s' is actually an address\n", tmp); } if (try_symbol_attr(tmp) & ATTRIB_CONSTANT) { cry("taking address of constant variable '%s'\n", tmp); } free(tmp); } }
static int set_ports_option(struct mg_context *ctx, int port) { int reuseaddr = 1, success = 1; socklen_t sock_len = sizeof(ctx->local_address); // MacOS needs that. If we do not zero it, subsequent bind() will fail. memset(&ctx->local_address, 0, sock_len); ctx->local_address.sin_family = AF_INET; ctx->local_address.sin_port = htons((uint16_t) port); ctx->local_address.sin_addr.s_addr = htonl(INADDR_ANY); struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 500 * 1000; if ((ctx->local_socket = socket(PF_INET, SOCK_STREAM, 6)) == INVALID_SOCKET || setsockopt(ctx->local_socket, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr)) != 0 || setsockopt(ctx->local_socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) != 0 || bind(ctx->local_socket, (const struct sockaddr *) &ctx->local_address, sock_len) != 0 || // TODO(steineldar): Replace 20 (max socket backlog len in connections). listen(ctx->local_socket, 20) != 0) { close(ctx->local_socket); cry(fc(ctx), "%s: cannot bind to port %d: %s", __func__, port, strerror(ERRNO)); success = 0; } else if (getsockname(ctx->local_socket, (struct sockaddr *) &ctx->local_address, &sock_len)) { close(ctx->local_socket); cry(fc(ctx), "%s: %s", __func__, strerror(ERRNO)); success = 0; } if (!success) { ctx->local_socket = INVALID_SOCKET; close_all_listening_sockets(ctx); } return success; }
static int is_loadable(struct node *n, BOOL allow_deref) { struct lval_node *p = (struct lval_node *)n; if (!is_loadable_sym(p->name)) { return 0; } if (p->deref && !allow_deref) { return 0; } if (!p->deref && try_symbol_extern(p->name)) { cry("symbol '%s' is actually an address\n", p->name); return -1; } return 1; }
static BOOL is_loadable_sym(const char *name) { enum use_t u = get_symbol_used(name); if (u != UNUSED) { if (u == CLOBBERED) { // XXX gets reported twice cry("symbol '%s' should be volatile\n", name); } return FALSE; } if (try_symbol_attr(name) & ATTRIB_VOLATILE) { return FALSE; } return TRUE; }
static int start_thread(struct mg_context *ctx, mg_thread_func_t func, void *param) { pthread_t thread_id; pthread_attr_t attr; int retval; (void) pthread_attr_init(&attr); (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); // TODO(lsm): figure out why mongoose dies on Linux if next line is enabled // (void) pthread_attr_setstacksize(&attr, sizeof(struct mg_connection) * 5); if ((retval = pthread_create(&thread_id, &attr, func, param)) != 0) { cry(fc(ctx), "%s: %s", __func__, strerror(retval)); } return retval; }
static bool mmap_file(struct loader *loader) { size_t size; void *mapping = m0_platform_mmap_file_private(loader->name, &size); if(!mapping) { cry(loader, "failed to mmap file <%s>", loader->name); return 0; } loader->mapping = mapping; loader->size = size; loader->cursor = (uint32_t *)loader->mapping; loader->remaining = size; return 1; }
JNIEnv* JRE::createJVM(bool debug) { int noptions = 7 + (debug ? 1 : 0); options_ = new JavaVMOption[noptions]; //C:\\Program Files (x86)\\Java\\jre6\\lib\\rt.jar //std::string classpath = "-Djava.class.path=D:\\workspace\\dispdrivertest\\bin;" + mol::tostring(classpath_); //std::string libpath = "-Djava.library.path=D:\\workspace\\dispdrivertest\\bin" + mol::tostring(libpath_); mol::win::AppBase& app = mol::App(); //JREApp& app = mol::app<JREApp>(); std::wstring path = app.getAppPath(); path = mol::Path::pathname(path); path = path + _T("\\lib"); std::string classpath = "-Djava.class.path=" + mol::tostring(path) + "\\classes;" + mol::tostring(path) + "\\dispdriver.jar"; if ( !classpath_.empty() ) { classpath += ";" + mol::tostring(classpath_); } std::string libpath = "-Djava.library.path=" + mol::tostring(path) ; if ( !libpath_.empty() ) { libpath += ";" + mol::tostring(libpath_); } options_[0].optionString = (char*)classpath.c_str(); options_[1].optionString = (char*)libpath.c_str(); options_[2].optionString = "-Xdebug"; options_[3].optionString = "-Xnoagent"; options_[4].optionString = "-Djava.compiler=NONE"; options_[5].optionString = "-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005"; options_[6].optionString = "-Dsun.java2d.d3d=false"; if ( debug ) options_[7].optionString = "-verbose:jni"; vm_args_.version = JNI_VERSION_1_6; vm_args_.nOptions = noptions; vm_args_.options = options_; vm_args_.ignoreUnrecognized = false; if (!jruntime_) jruntime_ = loadJVM(); if (!jruntime_) { cry(); return 0; } CreateJavaVM createJavaVM = (CreateJavaVM) ::GetProcAddress( jruntime_, "JNI_CreateJavaVM" ); if (!createJavaVM) return false; jint res = createJavaVM( &jvm_, (void**)&env_, &vm_args_ ); if( res != 0 ) return 0; jvm_->AttachCurrentThread((void**)&env_, &vm_args_); return env_; }
MemoryException::MemoryException (const char* file, int line) : _file (file), _line (line) { cry (cout); } // MemoryException::MemoryException
// mg.cry: Log an error. Default value for mg.onerror. static int lsp_cry(lua_State *L){ struct mg_connection *conn = lua_touserdata(L, lua_upvalueindex(1)); cry(conn, "%s", lua_tostring(L, -1)); return 0; }
void emit_nodes(struct node *n, const char *assignto, BOOL force, BOOL inloop) { char *fast = NULL; assert(n); if (n->next == NULL && n->type != NODE_CALL && !assignto && !force) { /* do not emit single node, unless it is a call or we really need it */ cry("statement with no effect\n"); return; } switch (n->type) { case NODE_IMM: { fast = AS_IMM(n)->value; maybe_symbol_forward(fast); if (force) { cry("constant expression '%s' in conditional\n", fast); } assert(!assignto); break; } case NODE_LVAL: { struct lval_node *p = AS_LVAL(n); int loadable = is_loadable(n, TRUE); if (loadable < 0) { fast = p->name; } else if (loadable > 0) { make_symbol_used(p->name); emit_load_direct(p->name, p->deref); } else { emit_load_indirect(p->name, p->deref); } break; } case NODE_CALL: { struct call_node *p = AS_CALL(n); struct node *parm; int deref0 = 0; char *args[MAX_FUNC_ARGS]; char *func; int i; BOOL retval = (n->next != NULL) || force || assignto; BOOL direct = FALSE; for (i = 0, parm = p->parm; parm; parm = parm->next, i++) { BOOL r0 = (i == 0 && arch_regparm); assert(i < MAX_FUNC_ARGS); if (parm->type == NODE_IMM) { args[i] = xstrdup(AS_IMM(parm)->value); maybe_symbol_forward(args[i]); } else if (parm->type == NODE_LVAL && is_loadable(parm, r0)) { struct lval_node *q = AS_LVAL(parm); args[i] = xstrdup(q->name); make_symbol_used(args[i]); if (q->deref) { deref0 = 1; } } else if (r0 && parm->next == NULL) { args[i] = NULL; direct = TRUE; emit_nodes(parm, NULL, TRUE, inloop); } else if (r0 && parm->type == NODE_LVAL) { struct lval_node *q = AS_LVAL(parm); args[i] = create_address_str(q->name); deref0 = 1; if (q->deref) { deref0++; } } else { args[i] = new_name("var"); emit_nodes(parm, args[i], FALSE, inloop); make_symbol_used(args[i]); } } func = p->func; if (retval && (p->attr & ATTRIB_NORETURN)) { cry("function '%s' does not return\n", func); } if (!is_loadable_sym(func)) { char *ptr = new_name("ptr"); emit_load_indirect(func, FALSE); add_symbol_forward(ptr, 0); emit_store_indirect(ptr); func = ptr; } else { func = xstrdup(func); } make_symbol_used(func); if (!(p->attr & ATTRIB_NORETURN)) { if ((p->attr & ATTRIB_STACK) || inloop) { if (!(p->attr & ATTRIB_STACK)) { cry("reserved [[stack]] for '%s' because of loop\n", func); } mark_all_used(PROTECTED); } else { mark_all_used(CLOBBERED); } } if (direct) { emit_call(func, NULL, 0, deref0, inloop, retval, p->attr); } else { emit_call(func, args, i, deref0, inloop, retval, p->attr); } free(func); while (--i >= 0) { free(args[i]); } break; } case NODE_ADD: { struct node *term; struct node *prev; int deref0 = 0; char *prev_tmp; prev = AS_ADD(n)->list; if (prev->type == NODE_IMM) { prev_tmp = xstrdup(AS_IMM(prev)->value); maybe_symbol_forward(prev_tmp); } else if (prev->type == NODE_LVAL && is_loadable(prev, TRUE)) { prev_tmp = xstrdup(AS_LVAL(prev)->name); make_symbol_used(prev_tmp); if (AS_LVAL(prev)->deref) { deref0 = TRUE; } } else if (prev->type == NODE_LVAL) { prev_tmp = create_address_str(AS_LVAL(prev)->name); deref0 = 1; if (AS_LVAL(prev)->deref) { deref0++; } } else { prev_tmp = new_name("var"); emit_nodes(prev, prev_tmp, FALSE, inloop); make_symbol_used(prev_tmp); } for (term = prev->next; term; term = term->next) { BOOL swap = FALSE; char *tmp; char *sum = new_name("sum"); if (term->type == NODE_IMM) { tmp = xstrdup(AS_IMM(term)->value); maybe_symbol_forward(tmp); } else if (term->type == NODE_LVAL && is_loadable(term, !deref0)) { tmp = xstrdup(AS_LVAL(term)->name); make_symbol_used(tmp); if (AS_LVAL(term)->deref) { swap = TRUE; deref0 = 1; } } else if (term->type == NODE_LVAL && !deref0) { tmp = create_address_str(AS_LVAL(term)->name); deref0 = 1; if (AS_LVAL(term)->deref) { swap = TRUE; deref0++; } } else { tmp = new_name("var"); emit_nodes(term, tmp, FALSE, inloop); make_symbol_used(tmp); } emit_add(prev_tmp, tmp, deref0, swap); deref0 = 0; if (term->next) { emit_store_indirect(sum); } free(prev_tmp); prev_tmp = sum; free(tmp); } free(prev_tmp); break; } } if (assignto) { add_symbol_forward(assignto, 0); emit_store_indirect(assignto); } else { BOOL loaded = FALSE; for (n = n->next; n; n = n->next) { BOOL later = FALSE; struct lval_node *p = AS_LVAL(n); assert(n->type == NODE_LVAL); if (fast) { if (optimize_imm && !p->deref && !get_symbol(p->name) && ((p->attr & ATTRIB_CONSTANT) || !inloop)) { emit_fast(p->name, fast); add_symbol_defined(p->name, fast, p->attr); continue; } if (!loaded) { loaded = TRUE; if (p->deref && !is_loadable_sym(p->name)) { later = TRUE; } else { emit_load_direct(fast, FALSE); } } } if (p->attr & ATTRIB_CONSTANT) { cry("useless const for '%s'\n", p->name); } if (p->deref) { /* XXX only addresses (imports/vectors) can be derefed */ if (!is_loadable_sym(p->name)) { /* XXX ok, this is very very shitty * tip1: store value to tmp_N for each future p->deref at once * tip2: calculate in advance how many derefs we will need and store pointers before calculating r0 (see above) */ char *ptr = new_name("ptr"); char *tmp; if (!later) { tmp = emit_save(); } emit_load_indirect(p->name, FALSE); emit_store_indirect(ptr); if (!later) { emit_restore(tmp); } else { emit_load_direct(fast, FALSE); } add_symbol_forward(ptr, 0); make_symbol_used(ptr); emit_store_direct(ptr); free(ptr); } else { make_symbol_used(p->name); emit_store_direct(p->name); } } else { add_symbol_forward(p->name, p->attr); if (try_symbol_extern(p->name)) { die("cannot assign to import address '%s'\n", p->name); } if (optimize_imm && (try_symbol_attr(p->name) & ATTRIB_CONSTANT)) { die("'%s' was declared constant\n", p->name); } emit_store_indirect(p->name); } } if (force && fast && !loaded) { emit_load_direct(fast, FALSE); } } }