int yr_execute_code( YR_RULES* rules, EVALUATION_CONTEXT* context, int timeout, time_t start_time) { int64_t r1; int64_t r2; int64_t r3; int64_t mem[MEM_SIZE]; int64_t stack[STACK_SIZE]; int32_t sp = 0; uint8_t* ip = rules->code_start; YR_RULE* rule; YR_STRING* string; YR_MATCH* match; YR_EXTERNAL_VARIABLE* external; int i; int found; int count; int result; int flags; int cycle = 0; int tidx = yr_get_tidx(); while(1) { switch(*ip) { case HALT: // When the halt instruction is reached the stack // should be empty. assert(sp == 0); return ERROR_SUCCESS; case PUSH: r1 = *(uint64_t*)(ip + 1); ip += sizeof(uint64_t); push(r1); break; case POP: pop(r1); break; case CLEAR_M: r1 = *(uint64_t*)(ip + 1); ip += sizeof(uint64_t); mem[r1] = 0; break; case ADD_M: r1 = *(uint64_t*)(ip + 1); ip += sizeof(uint64_t); pop(r2); mem[r1] += r2; break; case INCR_M: r1 = *(uint64_t*)(ip + 1); ip += sizeof(uint64_t); mem[r1]++; break; case PUSH_M: r1 = *(uint64_t*)(ip + 1); ip += sizeof(uint64_t); push(mem[r1]); break; case POP_M: r1 = *(uint64_t*)(ip + 1); ip += sizeof(uint64_t); pop(mem[r1]); break; case SWAPUNDEF: r1 = *(uint64_t*)(ip + 1); ip += sizeof(uint64_t); pop(r2); if (r2 != UNDEFINED) push(r2); else push(mem[r1]); break; case JNUNDEF: pop(r1); push(r1); if (r1 != UNDEFINED) { ip = *(uint8_t**)(ip + 1); // ip will be incremented at the end of the loop, // decrement it here to compensate. ip--; } else { ip += sizeof(uint64_t); } break; case JLE: pop(r2); pop(r1); push(r1); push(r2); if (r1 <= r2) { ip = *(uint8_t**)(ip + 1); // ip will be incremented at the end of the loop, // decrement it here to compensate. ip--; } else { ip += sizeof(uint64_t); } break; case AND: pop(r2); pop(r1); push(r1 & r2); break; case OR: pop(r2); pop(r1); push(r1 | r2); break; case NOT: pop(r1); push(!r1); break; case LT: pop(r2); pop(r1); push(comparison(<, r1, r2)); break; case GT: pop(r2); pop(r1); push(comparison(>, r1, r2)); break; case LE: pop(r2); pop(r1); push(comparison(<=, r1, r2)); break; case GE: pop(r2); pop(r1); push(comparison(>=, r1, r2)); break; case EQ: pop(r2); pop(r1); push(comparison(==, r1, r2)); break; case NEQ: pop(r2); pop(r1); push(comparison(!=, r1, r2)); break; case ADD: pop(r2); pop(r1); push(operation(+, r1, r2)); break; case SUB: pop(r2); pop(r1); push(operation(-, r1, r2)); break; case MUL: pop(r2); pop(r1); push(operation(*, r1, r2)); break; case DIV: pop(r2); pop(r1); push(operation(/, r1, r2)); break; case MOD: pop(r2); pop(r1); push(operation(%, r1, r2)); break; case NEG: pop(r1); push(IS_UNDEFINED(r1) ? UNDEFINED : ~r1); break; case SHR: pop(r2); pop(r1); push(operation(>>, r1, r2)); break; case SHL: pop(r2); pop(r1); push(operation(<<, r1, r2)); break; case XOR: pop(r2); pop(r1); push(operation(^, r1, r2)); break; case RULE_PUSH: rule = *(YR_RULE**)(ip + 1); ip += sizeof(uint64_t); push(rule->t_flags[tidx] & RULE_TFLAGS_MATCH ? 1 : 0); break; case RULE_POP: pop(r1); rule = *(YR_RULE**)(ip + 1); ip += sizeof(uint64_t); if (r1) rule->t_flags[tidx] |= RULE_TFLAGS_MATCH; break; case EXT_INT: external = *(YR_EXTERNAL_VARIABLE**)(ip + 1); ip += sizeof(uint64_t); push(external->integer); break; case EXT_STR: external = *(YR_EXTERNAL_VARIABLE**)(ip + 1); ip += sizeof(uint64_t); push(PTR_TO_UINT64(external->string)); break; case EXT_BOOL: external = *(YR_EXTERNAL_VARIABLE**)(ip + 1); ip += sizeof(uint64_t); if (external->type == EXTERNAL_VARIABLE_TYPE_FIXED_STRING || external->type == EXTERNAL_VARIABLE_TYPE_MALLOC_STRING) push(external->string[0] != '\0'); else push(external->integer); break; case SFOUND: pop(r1); string = UINT64_TO_PTR(YR_STRING*, r1); push(string->matches[tidx].tail != NULL ? 1 : 0); break; case SFOUND_AT: pop(r2); pop(r1); if (IS_UNDEFINED(r1)) { push(0); break; } string = UINT64_TO_PTR(YR_STRING*, r2); match = string->matches[tidx].head; found = 0; while (match != NULL) { if (r1 == match->offset) { push(1); found = 1; break; } if (r1 < match->offset) break; match = match->next; } if (!found) push(0); break; case SFOUND_IN: pop(r3); pop(r2); pop(r1); if (IS_UNDEFINED(r1) || IS_UNDEFINED(r2)) { push(0); break; } string = UINT64_TO_PTR(YR_STRING*, r3); match = string->matches[tidx].head; found = FALSE; while (match != NULL && !found) { if (match->offset >= r1 && match->offset <= r2) { push(1); found = TRUE; } if (match->offset > r2) break; match = match->next; } if (!found) push(0); break; case SCOUNT: pop(r1); string = UINT64_TO_PTR(YR_STRING*, r1); match = string->matches[tidx].head; found = 0; while (match != NULL) { found++; match = match->next; } push(found); break; case SOFFSET: pop(r2); pop(r1); if (IS_UNDEFINED(r1)) { push(UNDEFINED); break; } string = UINT64_TO_PTR(YR_STRING*, r2); match = string->matches[tidx].head; i = 1; found = FALSE; while (match != NULL && !found) { if (r1 == i) { push(match->offset); found = TRUE; } i++; match = match->next; } if (!found) push(UNDEFINED); break; case OF: found = 0; count = 0; pop(r1); while (r1 != UNDEFINED) { string = UINT64_TO_PTR(YR_STRING*, r1); if (string->matches[tidx].tail != NULL) found++; count++; pop(r1); } pop(r2); if (r2 != UNDEFINED) push(found >= r2 ? 1 : 0); else push(found >= count ? 1 : 0); break; case SIZE: push(context->file_size); break; case ENTRYPOINT: push(context->entry_point); break; case INT8: pop(r1); push(read_int8_t(context->mem_block, r1)); break; case INT16: pop(r1); push(read_int16_t(context->mem_block, r1)); break; case INT32: pop(r1); push(read_int32_t(context->mem_block, r1)); break; case UINT8: pop(r1); push(read_uint8_t(context->mem_block, r1)); break; case UINT16: pop(r1); push(read_uint16_t(context->mem_block, r1)); break; case UINT32: pop(r1); push(read_uint32_t(context->mem_block, r1)); break; case CONTAINS: pop(r2); pop(r1); push(strstr(UINT64_TO_PTR(char*, r1), UINT64_TO_PTR(char*, r2)) != NULL); break; case MATCHES: pop(r3); pop(r2); pop(r1); flags = (int) r3; count = strlen(UINT64_TO_PTR(char*, r1)); if (count == 0) { push(FALSE); break; } result = yr_re_exec( UINT64_TO_PTR(uint8_t*, r2), UINT64_TO_PTR(uint8_t*, r1), count, flags | RE_FLAGS_SCAN, NULL, NULL); push(result >= 0); break; default: // Unknown instruction, this shouldn't happen. assert(FALSE); } if (timeout > 0) // timeout == 0 means no timeout { // Check for timeout every 10 instruction cycles. if (++cycle == 10) { if (difftime(time(NULL), start_time) > timeout) return ERROR_SCAN_TIMEOUT; cycle = 0; } } ip++; } // After executing the code the stack should be empty. assert(sp == 0); return ERROR_SUCCESS; }
void response_split_task(void * arg) { client_info_t * client = arg; DBG_FUNC_ENTER(); DBG_VERBOSE("%s: client: %p\n", __FUNCTION__, client); /* variables for handling response split */ char temp[1024]; uint32_t temp_len = 0; read_stages_t stage = HEADER_LEN_READ; uint32_t payload_offset = 0; response_t * resp = NULL; uint32_t rem_size = 0; txn_buf_t * cur_buf = NULL; while (1) { if (cur_buf != NULL) { DBG_ALLOC("%s: FREE cur_buf->buf: %p cur_buf: %p\n", __FUNCTION__, cur_buf->buf, cur_buf); free(cur_buf->buf); free(cur_buf); cur_buf = NULL; } cur_buf = (txn_buf_t *)queue_pop(client->buf_q); DBG_VERBOSE("%s: buf: %p len: %ld offset: %ld\n", __FUNCTION__, cur_buf->buf, cur_buf->len, cur_buf->offset); /* write a response split using fixed len */ rem_size = cur_buf->len - cur_buf->offset; DBG_VERBOSE("rem_size: %u\n", rem_size); while ((temp_len > 0) && (rem_size > 0)) { switch(stage) { case HEADER_LEN_READ: { uint32_t hdr_len = 0; if ((rem_size + temp_len) < HEADER_SIZE) { memcpy(temp + temp_len, cur_buf->buf + cur_buf->offset, rem_size); temp_len += rem_size; rem_size = 0; } else { resp = malloc(sizeof(response_t)); assert(resp != NULL); DBG_ALLOC("%s: ALLOC request: %p\n", __FUNCTION__, resp); resp->buf = NULL; if (temp_len < HEADER_SIZE) { memcpy((uint8_t *)&hdr_len, temp, temp_len); memcpy(((uint8_t *)&hdr_len) + temp_len, cur_buf->buf + cur_buf->offset, HEADER_SIZE - temp_len); DBG_VERBOSE("HEADER length: %u\n", hdr_len); temp_len = 0; rem_size -= HEADER_SIZE + temp_len; } else { memcpy((uint8_t *)&hdr_len, temp, HEADER_SIZE); temp_len -= HEADER_SIZE; } resp->header_len = hdr_len; stage = HEADER_READ; } break; } case HEADER_READ: { if ((rem_size + temp_len) < resp->header_len) { memcpy(temp + temp_len, cur_buf->buf + cur_buf->offset, rem_size); temp_len += rem_size; rem_size = 0; } else { if (temp_len < resp->header_len) { memcpy((uint8_t *)&resp->hdr, temp, temp_len); memcpy(((uint8_t *)&resp->hdr) + temp_len, cur_buf->buf + cur_buf->offset, resp->header_len - temp_len); temp_len = 0; rem_size -= (resp->header_len - temp_len); } else { memcpy((uint8_t *)&resp->hdr, temp, resp->header_len); DBG_VERBOSE("REQUEST id: %u\n", resp->hdr.id); temp_len -= resp->header_len; } stage = PAYLOAD_READ; resp->buf = malloc(resp->hdr.len); assert(resp->buf != NULL); } break; } case PAYLOAD_READ: { if (temp_len < resp->hdr.len) { memcpy(resp->buf, temp, temp_len); temp_len = 0; } break; } default: DBG_ERR("INVALID case needs to be find out"); assert(0); break; } } while (rem_size > 0) { switch(stage) { case HEADER_LEN_READ: if (rem_size < HEADER_SIZE){ memcpy(temp, cur_buf->buf + cur_buf->offset, rem_size); temp_len = rem_size; cur_buf->offset += rem_size; rem_size = 0; } else { resp = malloc(sizeof(response_t)); assert(resp != NULL); DBG_PRINT("Allocated resp: %p\n", resp); resp->buf = NULL; read_uint32_t((uint8_t *)cur_buf->buf + cur_buf->offset, HEADER_SIZE, &resp->header_len); cur_buf->offset += HEADER_SIZE; rem_size -= HEADER_SIZE; DBG_VERBOSE("HEADER: %u\n", resp->header_len); stage = HEADER_READ; } break; case HEADER_READ: if (rem_size < resp->header_len) { memcpy(temp, cur_buf->buf + cur_buf->offset, rem_size); temp_len = rem_size; cur_buf->offset += rem_size; rem_size = 0; } else { read_pkt_hdr((uint8_t *)cur_buf->buf + cur_buf->offset, resp->header_len, &resp->hdr); DBG_VERBOSE("HEADER: %x %x %x %x\n", resp->hdr.magic, resp->hdr.len, resp->hdr.id, resp->hdr.future); rem_size -= resp->header_len; resp->buf = malloc(resp->hdr.len); assert(resp->buf != NULL); DBG_ALLOC("ALLOC resp->buf: %p\n", resp->buf); cur_buf->offset += resp->header_len; stage = PAYLOAD_READ; } break; case PAYLOAD_READ: { size_t len_to_read = resp->hdr.len - payload_offset; if (rem_size < len_to_read) { memcpy(resp->buf + payload_offset, cur_buf->buf + cur_buf->offset, rem_size); payload_offset += rem_size; cur_buf->offset += rem_size; rem_size = 0; } else { memcpy(resp->buf + payload_offset, cur_buf->buf + cur_buf->offset, len_to_read); payload_offset = 0; rem_size -= len_to_read; cur_buf->offset += len_to_read; /* request is done, lets push it into the queue */ DBG_VERBOSE("GOT THE RESPONSE for ID: %u\n", resp->hdr.id); queue_push(client->res_q, (void *)resp); resp = NULL; stage = HEADER_LEN_READ; } } break; default: DBG_ERR("Invalid stage\n"); assert(0); } } } DBG_FUNC_EXIT(); }
int yr_execute_code( YR_RULES* rules, YR_SCAN_CONTEXT* context, int timeout, time_t start_time) { int64_t r1; int64_t r2; int64_t r3; int64_t mem[MEM_SIZE]; int64_t stack[STACK_SIZE]; int64_t args[MAX_FUNCTION_ARGS]; int32_t sp = 0; uint8_t* ip = rules->code_start; YR_RULE* rule; YR_STRING* string; YR_MATCH* match; YR_OBJECT* object; YR_OBJECT_FUNCTION* function; char* identifier; char* args_fmt; int i; int found; int count; int result; int cycle = 0; int tidx = yr_get_tidx(); #ifdef PROFILING_ENABLED clock_t start = clock(); #endif while(1) { switch(*ip) { case OP_HALT: // When the halt instruction is reached the stack // should be empty. assert(sp == 0); return ERROR_SUCCESS; case OP_PUSH: r1 = *(uint64_t*)(ip + 1); ip += sizeof(uint64_t); push(r1); break; case OP_POP: pop(r1); break; case OP_CLEAR_M: r1 = *(uint64_t*)(ip + 1); ip += sizeof(uint64_t); mem[r1] = 0; break; case OP_ADD_M: r1 = *(uint64_t*)(ip + 1); ip += sizeof(uint64_t); pop(r2); mem[r1] += r2; break; case OP_INCR_M: r1 = *(uint64_t*)(ip + 1); ip += sizeof(uint64_t); mem[r1]++; break; case OP_PUSH_M: r1 = *(uint64_t*)(ip + 1); ip += sizeof(uint64_t); push(mem[r1]); break; case OP_POP_M: r1 = *(uint64_t*)(ip + 1); ip += sizeof(uint64_t); pop(mem[r1]); break; case OP_SWAPUNDEF: r1 = *(uint64_t*)(ip + 1); ip += sizeof(uint64_t); pop(r2); if (r2 != UNDEFINED) push(r2); else push(mem[r1]); break; case OP_JNUNDEF: pop(r1); push(r1); if (r1 != UNDEFINED) { ip = *(uint8_t**)(ip + 1); // ip will be incremented at the end of the loop, // decrement it here to compensate. ip--; } else { ip += sizeof(uint64_t); } break; case OP_JLE: pop(r2); pop(r1); push(r1); push(r2); if (r1 <= r2) { ip = *(uint8_t**)(ip + 1); // ip will be incremented at the end of the loop, // decrement it here to compensate. ip--; } else { ip += sizeof(uint64_t); } break; case OP_AND: pop(r2); pop(r1); if (IS_UNDEFINED(r1) || IS_UNDEFINED(r2)) push(0); else push(r1 && r2); break; case OP_OR: pop(r2); pop(r1); if (IS_UNDEFINED(r1)) push(r2); else if (IS_UNDEFINED(r2)) push(r1); else push(r1 || r2); break; case OP_NOT: pop(r1); if (IS_UNDEFINED(r1)) push(UNDEFINED); else push(!r1); break; case OP_LT: pop(r2); pop(r1); push(COMPARISON(<, r1, r2)); break; case OP_GT: pop(r2); pop(r1); push(COMPARISON(>, r1, r2)); break; case OP_LE: pop(r2); pop(r1); push(COMPARISON(<=, r1, r2)); break; case OP_GE: pop(r2); pop(r1); push(COMPARISON(>=, r1, r2)); break; case OP_EQ: pop(r2); pop(r1); push(COMPARISON(==, r1, r2)); break; case OP_NEQ: pop(r2); pop(r1); push(COMPARISON(!=, r1, r2)); break; case OP_SZ_EQ: pop(r2); pop(r1); if (IS_UNDEFINED(r1) || IS_UNDEFINED(r2)) push(UNDEFINED); else push(strcmp(UINT64_TO_PTR(char*, r1), UINT64_TO_PTR(char*, r2)) == 0); break; case OP_SZ_NEQ: pop(r2); pop(r1); if (IS_UNDEFINED(r1) || IS_UNDEFINED(r2)) push(UNDEFINED); else push(strcmp(UINT64_TO_PTR(char*, r1), UINT64_TO_PTR(char*, r2)) != 0); break; case OP_SZ_TO_BOOL: pop(r1); if (IS_UNDEFINED(r1)) push(UNDEFINED); else push(strlen(UINT64_TO_PTR(char*, r1)) > 0); break; case OP_ADD: pop(r2); pop(r1); push(OPERATION(+, r1, r2)); break; case OP_SUB: pop(r2); pop(r1); push(OPERATION(-, r1, r2)); break; case OP_MUL: pop(r2); pop(r1); push(OPERATION(*, r1, r2)); break; case OP_DIV: pop(r2); pop(r1); push(OPERATION(/, r1, r2)); break; case OP_MOD: pop(r2); pop(r1); push(OPERATION(%, r1, r2)); break; case OP_SHR: pop(r2); pop(r1); push(OPERATION(>>, r1, r2)); break; case OP_SHL: pop(r2); pop(r1); push(OPERATION(<<, r1, r2)); break; case OP_BITWISE_NOT: pop(r1); push(IS_UNDEFINED(r1) ? UNDEFINED : ~r1); break; case OP_BITWISE_AND: pop(r2); pop(r1); push(OPERATION(&, r1, r2)); break; case OP_BITWISE_OR: pop(r2); pop(r1); push(OPERATION(|, r1, r2)); break; case OP_BITWISE_XOR: pop(r2); pop(r1); push(OPERATION(^, r1, r2)); break; case OP_PUSH_RULE: rule = *(YR_RULE**)(ip + 1); ip += sizeof(uint64_t); push(rule->t_flags[tidx] & RULE_TFLAGS_MATCH ? 1 : 0); break; case OP_MATCH_RULE: pop(r1); rule = *(YR_RULE**)(ip + 1); ip += sizeof(uint64_t); if (!IS_UNDEFINED(r1) && r1) rule->t_flags[tidx] |= RULE_TFLAGS_MATCH; #ifdef PROFILING_ENABLED rule->clock_ticks += clock() - start; start = clock(); #endif break; case OP_OBJ_LOAD: identifier = *(char**)(ip + 1); ip += sizeof(uint64_t); object = (YR_OBJECT*) yr_hash_table_lookup( context->objects_table, identifier, NULL); assert(object != NULL); push(PTR_TO_UINT64(object)); break; case OP_OBJ_FIELD: pop(r1); identifier = *(char**)(ip + 1); ip += sizeof(uint64_t); if (IS_UNDEFINED(r1)) { push(UNDEFINED); break; } object = UINT64_TO_PTR(YR_OBJECT*, r1); object = yr_object_lookup_field(object, identifier); assert(object != NULL); push(PTR_TO_UINT64(object)); break; case OP_OBJ_VALUE: pop(r1); if (IS_UNDEFINED(r1)) { push(UNDEFINED); break; } object = UINT64_TO_PTR(YR_OBJECT*, r1); switch(object->type) { case OBJECT_TYPE_INTEGER: push(((YR_OBJECT_INTEGER*) object)->value); break; case OBJECT_TYPE_STRING: if (((YR_OBJECT_STRING*) object)->value != NULL) push(PTR_TO_UINT64(((YR_OBJECT_STRING*) object)->value)); else push(UNDEFINED); break; default: assert(FALSE); } break; case OP_INDEX_ARRAY: pop(r1); // index pop(r2); // array if (IS_UNDEFINED(r1)) { push(UNDEFINED); break; } object = UINT64_TO_PTR(YR_OBJECT*, r2); assert(object->type == OBJECT_TYPE_ARRAY); object = yr_object_array_get_item(object, 0, r1); if (object != NULL) push(PTR_TO_UINT64(object)); else push(UNDEFINED); break; case OP_LOOKUP_DICT: pop(r1); // key pop(r2); // dictionary if (IS_UNDEFINED(r1)) { push(UNDEFINED); break; } object = UINT64_TO_PTR(YR_OBJECT*, r2); assert(object->type == OBJECT_TYPE_DICTIONARY); object = yr_object_dict_get_item( object, 0, UINT64_TO_PTR(const char*, r1)); if (object != NULL) push(PTR_TO_UINT64(object)); else push(UNDEFINED); break; case OP_CALL: args_fmt = *(char**)(ip + 1); ip += sizeof(uint64_t); i = strlen(args_fmt); // pop arguments from stack and copy them to args array while (i > 0) { pop(args[i - 1]); i--; } pop(r2); function = UINT64_TO_PTR(YR_OBJECT_FUNCTION*, r2); result = ERROR_INTERNAL_FATAL_ERROR; for (i = 0; i < MAX_OVERLOADED_FUNCTIONS; i++) { if (function->prototypes[i].arguments_fmt == NULL) break; if (strcmp(function->prototypes[i].arguments_fmt, args_fmt) == 0) { result = function->prototypes[i].code( (void*) args, context, function); break; } } assert(i < MAX_OVERLOADED_FUNCTIONS); if (result == ERROR_SUCCESS) push(PTR_TO_UINT64(function->return_obj)); else return result; break; case OP_STR_FOUND: pop(r1); string = UINT64_TO_PTR(YR_STRING*, r1); push(string->matches[tidx].tail != NULL ? 1 : 0); break; case OP_STR_FOUND_AT: pop(r2); pop(r1); if (IS_UNDEFINED(r1)) { push(0); break; } string = UINT64_TO_PTR(YR_STRING*, r2); match = string->matches[tidx].head; found = 0; while (match != NULL) { if (r1 == match->base + match->offset) { push(1); found = 1; break; } if (r1 < match->base + match->offset) break; match = match->next; } if (!found) push(0); break; case OP_STR_FOUND_IN: pop(r3); pop(r2); pop(r1); if (IS_UNDEFINED(r1) || IS_UNDEFINED(r2)) { push(UNDEFINED); break; } string = UINT64_TO_PTR(YR_STRING*, r3); match = string->matches[tidx].head; found = FALSE; while (match != NULL && !found) { if (match->base + match->offset >= r1 && match->base + match->offset <= r2) { push(1); found = TRUE; } if (match->base + match->offset > r2) break; match = match->next; } if (!found) push(0); break; case OP_STR_COUNT: pop(r1); string = UINT64_TO_PTR(YR_STRING*, r1); push(string->matches[tidx].count); break; case OP_STR_OFFSET: pop(r2); pop(r1); if (IS_UNDEFINED(r1)) { push(UNDEFINED); break; } string = UINT64_TO_PTR(YR_STRING*, r2); match = string->matches[tidx].head; i = 1; found = FALSE; while (match != NULL && !found) { if (r1 == i) { push(match->base + match->offset); found = TRUE; } i++; match = match->next; } if (!found) push(UNDEFINED); break; case OP_OF: found = 0; count = 0; pop(r1); while (r1 != UNDEFINED) { string = UINT64_TO_PTR(YR_STRING*, r1); if (string->matches[tidx].tail != NULL) found++; count++; pop(r1); } pop(r2); if (r2 != UNDEFINED) push(found >= r2 ? 1 : 0); else push(found >= count ? 1 : 0); break; case OP_FILESIZE: push(context->file_size); break; case OP_ENTRYPOINT: push(context->entry_point); break; case OP_INT8: pop(r1); push(read_int8_t(context->mem_block, r1)); break; case OP_INT16: pop(r1); push(read_int16_t(context->mem_block, r1)); break; case OP_INT32: pop(r1); push(read_int32_t(context->mem_block, r1)); break; case OP_UINT8: pop(r1); push(read_uint8_t(context->mem_block, r1)); break; case OP_UINT16: pop(r1); push(read_uint16_t(context->mem_block, r1)); break; case OP_UINT32: pop(r1); push(read_uint32_t(context->mem_block, r1)); break; case OP_CONTAINS: pop(r2); pop(r1); if (IS_UNDEFINED(r1) || IS_UNDEFINED(r2)) push(UNDEFINED); else push(strstr(UINT64_TO_PTR(char*, r1), UINT64_TO_PTR(char*, r2)) != NULL); break; case OP_IMPORT: r1 = *(uint64_t*)(ip + 1); ip += sizeof(uint64_t); FAIL_ON_ERROR(yr_modules_load( UINT64_TO_PTR(char*, r1), context)); break; case OP_MATCHES: pop(r2); pop(r1); count = strlen(UINT64_TO_PTR(char*, r1)); if (count == 0) { push(FALSE); break; } result = yr_re_exec( UINT64_TO_PTR(uint8_t*, r2), UINT64_TO_PTR(uint8_t*, r1), count, RE_FLAGS_SCAN, NULL, NULL); push(result >= 0); break; default: // Unknown instruction, this shouldn't happen. assert(FALSE); } if (timeout > 0) // timeout == 0 means no timeout { // Check for timeout every 10 instruction cycles. if (++cycle == 10) { if (difftime(time(NULL), start_time) > timeout) return ERROR_SCAN_TIMEOUT; cycle = 0; } } ip++; } // After executing the code the stack should be empty. assert(sp == 0); return ERROR_SUCCESS; }