static tree_cell* affect_to_anon_var(anon_nasl_var* v1, tree_cell* rval) { anon_nasl_var *v2 = NULL, v0; nasl_array *a = NULL; int t1, t2; void *p; t1 = v1->var_type; if (rval == NULL || rval == FAKE_CELL) { #if NASL_DEBUG > 1 nasl_perror(NULL, "nasl_affect: affecting NULL or FAKE cell undefines variable %s %s\n", get_var_name(v1), get_line_nb(rval)); #endif clear_anon_var(v1); if(nasl_trace_enabled())nasl_trace(NULL, "NASL> %s <- undef\n", get_var_name(v1)); return NULL; } switch (rval->type) { case CONST_INT: t2 = VAR2_INT; break; case CONST_STR: t2 = VAR2_STRING; break; case CONST_DATA: t2 = VAR2_DATA; break; case REF_VAR: v2 = rval->x.ref_val; if (v2 == v1) { #if NASL_DEBUG > 1 nasl_perror(NULL, "Copying variable %s to itself is useless and dangerous!\n", get_var_name(v1)); #endif return FAKE_CELL; } t2 = v2->var_type; if (t2 == VAR2_ARRAY) a = &v2->v.v_arr; /* ? */ break; case REF_ARRAY: case DYN_ARRAY: a = rval->x.ref_val; t2 = VAR2_ARRAY; if (v1->var_type == VAR2_ARRAY && &v1->v.v_arr == a) { #if NASL_DEBUG > 1 nasl_perror(NULL, "Copying array %s to itself is useless and dangerous!\n", get_var_name(v1)); #endif return FAKE_CELL; } break; default: nasl_perror(NULL, "Cannot affect rvalue 0x%x to variable\n", rval->type); return NULL; } /* * Bug #146: when executing * x = 'abc'; x = x; or x = make_list(...); x = x[0]; * the rvalue will be freed before it is copied to the lvalue */ v0 = *v1; if (t1 != VAR2_UNDEF && t2 == VAR2_UNDEF) { #if NASL_DEBUG > 0 nasl_perror(NULL, "Warning: Undefining defined variable %s %s\n", get_var_name(v1), get_line_nb(rval)); #endif } else if (t1 == VAR2_ARRAY && t2 != VAR2_ARRAY) { #if NASL_DEBUG > 1 nasl_perror(NULL, "Warning: affecting non array (0x%x) to array variable %s\n", t2, get_line_nb(rval)); #endif } else if ((t1 == VAR2_INT || t1 == VAR2_STRING || t1 == VAR2_DATA) && t2 == VAR2_ARRAY) { #if NASL_DEBUG > 1 nasl_perror(NULL ,"Warning: affecting array to atomic variable (0x%x) %s\n", t2, get_line_nb(rval)); #endif } /* Bug #146: this fake clear is necessary if we copy an array*/ memset(v1, 0, sizeof(*v1)); /* Bug #146: no risk with the type, we already copied it */ v1->var_type = t2; if (rval->type != REF_VAR && rval->type != REF_ARRAY && rval->type != DYN_ARRAY) switch (t2) { case VAR2_INT: v1->v.v_int = rval->x.i_val; break; case VAR2_STRING: case VAR2_DATA: if( rval->x.str_val == NULL ) { v1->v.v_str.s_val = NULL; v1->v.v_str.s_siz = 0; } else { p = emalloc(rval->size+1); memcpy(p, rval->x.str_val, rval->size+1); v1->v.v_str.s_siz = rval->size; v1->v.v_str.s_val = p; } break; } else /* REF_xxx */ switch(t2) { case VAR2_INT: v1->v.v_int = v2->v.v_int; break; case VAR2_STRING: case VAR2_DATA: if(v2->v.v_str.s_val == NULL) { v1->v.v_str.s_val = NULL; v1->v.v_str.s_siz = 0; } else { p = emalloc(v2->v.v_str.s_siz); memcpy(p, v2->v.v_str.s_val, v2->v.v_str.s_siz); v1->v.v_str.s_siz = v2->v.v_str.s_siz; v1->v.v_str.s_val = p; } break; case VAR2_ARRAY: copy_array(&v1->v.v_arr, a); if (v0.var_type == VAR2_ARRAY) bzero(&v0, sizeof(v0)); /* So that we don't clear the variable twice */ break; } if (nasl_trace_fp != NULL) switch(t2) { case VAR2_INT: nasl_trace(NULL, "NASL> %s <- %d\n", get_var_name(v1), v1->v.v_int); break; case VAR2_STRING: case VAR2_DATA: nasl_trace(NULL, "NASL> %s <- \"%s\"\n", get_var_name(v1), v1->v.v_str.s_val); break; case VAR2_ARRAY: nasl_trace(NULL, "NASL> %s <- (VAR2_ARRAY)\n", get_var_name(v1)); break; default: nasl_trace(NULL, "NASL> %s <- (Type 0x%x)\n", get_var_name(v1), t2); break; } clear_anon_var(&v0); return FAKE_CELL; }
tree_cell* nasl_read_var_ref(lex_ctxt* lexic, tree_cell* tc) { tree_cell *ret; anon_nasl_var *v; if (tc == NULL || tc == FAKE_CELL) { nasl_perror(lexic, "nasl_read_var_ref: cannot read NULL or FAKE cell\n"); return NULL; } if (tc->type != REF_VAR) { nasl_perror(lexic, "nasl_read_var_ref: argument (type=%d) is not REF_VAR %s\n", tc->type, get_line_nb(tc)); return NULL; } v = tc->x.ref_val; if (v == NULL) { nasl_perror(lexic, "nasl_read_var_ref: NULL variable in REF_VAR\n"); return NULL; } ret = alloc_tree_cell(tc->line_nb, NULL); switch (v->var_type) { case VAR2_INT: ret->type = CONST_INT; ret->x.i_val = v->v.v_int; if(nasl_trace_enabled())nasl_trace(lexic, "NASL> %s -> %d\n", get_var_name(v), ret->x.i_val); return ret; case VAR2_STRING: ret->type = CONST_STR; /* Fix bad string length */ if (v->v.v_str.s_siz <= 0 && v->v.v_str.s_val[0] != '\0') { v->v.v_str.s_siz = strlen(v->v.v_str.s_val); nasl_perror(lexic, "nasl_read_var_ref: Bad string length fixed\n"); } /* Go on next case */ case VAR2_DATA: ret->type = v->var_type == VAR2_STRING ? CONST_STR : CONST_DATA; if(v->v.v_str.s_val == NULL) { ret->x.str_val = NULL; ret->size = 0; } else { ret->x.str_val = emalloc(v->v.v_str.s_siz); memcpy(ret->x.str_val, v->v.v_str.s_val, v->v.v_str.s_siz); ret->size = v->v.v_str.s_siz; } if(nasl_trace_enabled())nasl_trace(lexic, "NASL> %s -> \"%s\"\n", get_var_name(v), ret->x.str_val); return ret; case VAR2_ARRAY: ret->type = REF_ARRAY; ret->x.ref_val = &v->v.v_arr; return ret; case VAR2_UNDEF: #if NASL_DEBUG > 0 name = get_var_name(v); if (strcmp(name, "NULL") != 0) /* special case */ nasl_perror(lexic, "nasl_read_var_ref: variable %s is undefined %s\n", name, get_line_nb(tc)); #endif if(nasl_trace_enabled())nasl_trace(lexic, "NASL> %s -> undef\n", get_var_name(v), v->var_type); break; default: nasl_perror(lexic, "nasl_read_var_ref: unhandled variable type %d\n", v->var_type); if(nasl_trace_enabled())nasl_trace(lexic, "NASL> %s -> ???? (Var type %d)\n", get_var_name(v), v->var_type); break; } deref_cell(ret); return NULL; }
tree_cell* nasl_func_call(lex_ctxt* lexic, const nasl_func* f, tree_cell* arg_list) { #if 0 return FAKE_CELL; #else int nb_u = 0, nb_n = 0, nb_a = 0; tree_cell *pc = NULL, *pc2 = NULL, *retc = NULL; lex_ctxt *lexic2 = NULL; char *trace_buf = NULL; int trace_buf_len = 0, tn; #define TRACE_BUF_SZ 255 #if 0 nasl_dump_tree(arg_list); #endif /* 1. Create a new context */ lexic2 = init_empty_lex_ctxt(); lexic2->script_infos = lexic->script_infos; lexic2->authenticated = lexic->authenticated; lexic2->recv_timeout = lexic->recv_timeout; lexic2->fct_ctxt = 1; if (nasl_trace_fp != NULL) { trace_buf = emalloc(TRACE_BUF_SZ); tn = snprintf(trace_buf, TRACE_BUF_SZ, "Call %s(", f->func_name); if (tn > 0) trace_buf_len += tn; } if (! (f->flags & FUNC_FLAG_COMPAT)) { for (pc = arg_list; pc != NULL; pc = pc->link[1]) if (pc->x.str_val == NULL) nb_u ++; else { size_t num = f->nb_named_args; if (lfind(&pc->x.str_val, f->args_names, &num, sizeof(char*), stringcompare) != NULL) nb_n ++; } if (nb_n + nb_u > f->nb_unnamed_args + f->nb_named_args) nasl_perror(lexic, "Too many args for function '%s' [%dN+%dU > %dN+%dU]\n", f->func_name, nb_n, nb_u, f->nb_unnamed_args, f->nb_named_args); /* * I should look exactly how unnamed arguments works... * Or maybe I should remove this feature? */ for (nb_u = 0, pc = arg_list; pc != NULL; pc = pc->link[1]) { #if 0 pc2 = pc->link[0]; ref_cell(pc2); do { pc22 = nasl_exec(lexic, pc2); deref_cell(pc2); pc2 = pc22; } while (! nasl_is_leaf(pc2)); #else pc2 = cell2atom(lexic, pc->link[0]); #endif if (pc->x.str_val == NULL) { /* 2. Add unnamed (numbered) variables for unnamed args */ if (add_numbered_var_to_ctxt(lexic2, nb_u, pc2) == NULL) goto error; nb_u ++; if (nasl_trace_fp != NULL && trace_buf_len < TRACE_BUF_SZ) { tn = snprintf(trace_buf + trace_buf_len, TRACE_BUF_SZ - trace_buf_len, "%s%d: %s", nb_a > 0 ? ", " : "", nb_u, dump_cell_val(pc2)); if (tn > 0) trace_buf_len += tn; } nb_a ++; } else { /* 3. and add named variables for named args */ if (add_named_var_to_ctxt(lexic2, pc->x.str_val, pc2) == NULL) goto error; if (nasl_trace_fp != NULL && trace_buf_len < TRACE_BUF_SZ) { tn = snprintf(trace_buf + trace_buf_len, TRACE_BUF_SZ - trace_buf_len, "%s%s: %s", nb_a > 0 ? ", " : "", pc->x.str_val, dump_cell_val(pc2)); if (tn > 0) trace_buf_len += tn; } nb_a ++; } deref_cell(pc2); } if (nasl_trace_fp != NULL) { if (trace_buf_len < TRACE_BUF_SZ) nasl_trace(lexic, "NASL> %s)\n", trace_buf); else nasl_trace(lexic, "NASL> %s ...)\n", trace_buf); trace_buf_len = 0; efree(&trace_buf); } /* 4. Chain new context to old (lexic) */ lexic2->up_ctxt = lexic; /* 5. Execute */ if (f->flags & FUNC_FLAG_INTERNAL) { tree_cell* (*pf2)(lex_ctxt*) = f->block; retc = pf2(lexic2); } else { retc = nasl_exec(lexic2, f->block); deref_cell(retc); retc = FAKE_CELL; } if ((retc == NULL || retc == FAKE_CELL) && (lexic2->ret_val != NULL && lexic2->ret_val != FAKE_CELL)) { #if 0 nasl_perror(lexic, "nasl_func_call: nasl_exec(%s) returns NULL or FAKE value, but context disagrees. Fixing...\n", f->func_name); nasl_dump_tree(retc); #endif retc = lexic2->ret_val; ref_cell(retc); } if(nasl_trace_enabled())nasl_trace(lexic, "NASL> Return %s: %s\n", f->func_name, dump_cell_val(retc)); #if 1 if (! nasl_is_leaf(retc)) { nasl_perror(lexic, "nasl_func_call: return value from %s is not atomic!\n", f->func_name); nasl_dump_tree(retc); } #endif free_lex_ctxt(lexic2); lexic2 = NULL; return retc; } error: free_lex_ctxt(lexic2); return NULL; #endif }