📄 nasl_var.c
字号:
/* Nessus Attack Scripting Language * * Copyright (C) 2002 - 2004 Tenable Network Security * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, * as published by the Free Software Foundation * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */#include <includes.h>#include "nasl_tree.h"#include "nasl_global_ctxt.h"#include "nasl_func.h"#include "nasl_var.h"#include "nasl_lex_ctxt.h"#include "exec.h"#include "nasl_debug.h"#ifndef NASL_DEBUG#define NASL_DEBUG 0#endif/* Local prototypes */static void copy_array(nasl_array*, const nasl_array*, int);#if 0static inthash_int(int x){ return (unsigned) x % VAR_NAME_HASH;}#endifinthash_str2(const char* s, int n){ unsigned long h = 0; const char *p; if (s == NULL) return 0; for (p = s; *p != '\0'; p ++) h = (h << 3) + (unsigned char) *p; return h % n;}static inthash_str(const char* s){ return hash_str2(s, VAR_NAME_HASH);}anon_nasl_var*nasl_get_var_by_num(nasl_array* a, int num, int create){ anon_nasl_var *v = NULL; if (num < 0) { /* TBD: implement a min_index field, just like $[ in Perl */ nasl_perror(NULL, "Negative integer index are not supported yet!\n"); return NULL; } if (num < a->max_idx) v = a->num_elt[num]; if (v != NULL || ! create) return v; if (num >= a->max_idx) { a->num_elt = erealloc(a->num_elt, sizeof(anon_nasl_var*) * (num+1)); bzero(a->num_elt + a->max_idx, sizeof(anon_nasl_var*) * (num+1-a->max_idx)); a->max_idx = num +1; } v = emalloc(sizeof(anon_nasl_var)); v->var_type = VAR2_UNDEF; a->num_elt[num] = v; return v; }static named_nasl_var*get_var_by_name(nasl_array* a, const char* s){ int h = hash_str(s); named_nasl_var *v; if (a->hash_elt == NULL) a->hash_elt = emalloc(VAR_NAME_HASH * sizeof(named_nasl_var*)); for (v = a->hash_elt[h]; v != NULL; v = v->next_var) if (v->var_name != NULL && strcmp(s, v->var_name) == 0) return v; v = emalloc(sizeof(named_nasl_var)); v->var_name = estrdup(s); v->u.var_type = VAR2_UNDEF; v->next_var = a->hash_elt[h]; a->hash_elt[h] = v; return v;}/* This function climbs up in the context list */static named_nasl_var*get_var_ref_by_name(lex_ctxt* ctxt, const char* name, int climb){ named_nasl_var *v, *prev; int h = hash_str(name); lex_ctxt *c; if(climb != 0) { for (c = ctxt; c != NULL; c = c->up_ctxt) if (c->ctx_vars.hash_elt != NULL) for (prev = NULL, v = c->ctx_vars.hash_elt[h]; v != NULL; v = v->next_var) if (v->var_name != NULL && strcmp(name, v->var_name) == 0) {#ifdef SILLY_OPT if (prev != NULL) /* Move it to start of list */ { prev->next_var = v->next_var; v->next_var = c->ctx_vars.hash_elt[h]; c->ctx_vars.hash_elt[h] = v; }#endif return v; }#ifdef SILLY_OPT else prev = v;#endif } else { if (ctxt->ctx_vars.hash_elt != NULL) for (prev = NULL, v = ctxt->ctx_vars.hash_elt[h]; v != NULL; v = v->next_var) if (v->var_name != NULL && strcmp(name, v->var_name) == 0) {#ifdef SILLY_OPT if (prev != NULL) /* Move it to start of list */ { prev->next_var = v->next_var; v->next_var = ctxt->ctx_vars.hash_elt[h]; ctxt->ctx_vars.hash_elt[h] = v; }#endif return v; }#ifdef SILLY_OPT else prev = v;#endif } if (ctxt->ctx_vars.hash_elt == NULL) ctxt->ctx_vars.hash_elt = emalloc(sizeof(named_nasl_var*) * VAR_NAME_HASH); v = emalloc(sizeof(named_nasl_var)); v->var_name = estrdup(name); v->u.var_type = VAR2_UNDEF; v->next_var = ctxt->ctx_vars.hash_elt[h]; ctxt->ctx_vars.hash_elt[h] = v; return v; }static anon_nasl_var*get_var_ref_by_num(lex_ctxt* ctxt, int num){ anon_nasl_var *v; if (num < 0) /* safer */ { nasl_perror(ctxt, "Negative index %d is invalid for array\n", num); return NULL; } if (ctxt->ctx_vars.max_idx <= num) { ctxt->ctx_vars.num_elt = erealloc(ctxt->ctx_vars.num_elt, sizeof(anon_nasl_var*) * (num+1)); bzero(ctxt->ctx_vars.num_elt + ctxt->ctx_vars.max_idx, sizeof(anon_nasl_var*) * (num+1 - ctxt->ctx_vars.max_idx)); ctxt->ctx_vars.max_idx = num+1; } v = ctxt->ctx_vars.num_elt[num]; if (v != NULL) return v; v = emalloc(sizeof(anon_nasl_var)); v->var_type = VAR2_UNDEF; ctxt->ctx_vars.num_elt[num] = v; return v; }tree_cell*var2cell(anon_nasl_var* v){ tree_cell *tc = alloc_tree_cell(0, NULL); tc->type = REF_VAR; tc->x.ref_val = v; /* No need to free this later! */ return tc;}tree_cell*get_variable_by_name(lex_ctxt* ctxt, const char* name){ if (name == NULL) return NULL; /* Broken: Need also code in get_array_elem */ if (strcmp(name, "_FCT_ANON_ARGS") == 0) { tree_cell *retc = alloc_typed_cell(DYN_ARRAY); nasl_array *a = retc->x.ref_val = emalloc(sizeof(nasl_array)); copy_array(a, &ctxt->ctx_vars, 0); return retc; } else { named_nasl_var * v = get_var_ref_by_name(ctxt, name, 1); return var2cell(&v->u); } /*NOTREACHED*/}static const char*get_var_name(anon_nasl_var *v){ static char str[16];#ifdef ALL_VARIABLES_NAMED if (v->av_name != NULL) return v->av_name;#endif snprintf(str, sizeof(str), "[%08x]", (int)v); return str;}tree_cell*get_array_elem(lex_ctxt* ctxt, const char* name, tree_cell* idx){ named_nasl_var *nv; anon_nasl_var *u, *av, fake_var; tree_cell *tc, idx0; /* Fake variable */ if (strcmp(name, "_FCT_ANON_ARGS") == 0) { lex_ctxt *c; for (c = ctxt; c != NULL && ! c->fct_ctxt; c = c->up_ctxt) ; if (c == NULL) return NULL; fake_var.var_type = VAR2_ARRAY; fake_var.v.v_arr = c->ctx_vars; fake_var.v.v_arr.hash_elt = NULL; /* mask named elements */ u = &fake_var; } else { named_nasl_var *v = get_var_ref_by_name(ctxt, name, 1); u = &v->u; } if (idx == NULL) {#if NASL_DEBUG > 0 nasl_perror(ctxt, "get_array_elem: NULL index\n");#endif /* Treat it as zero */ idx = &idx0; idx->x.i_val = 0; idx->type = CONST_INT; } switch (u->var_type) { case VAR2_UNDEF: /* We define the array here */ u->var_type = VAR2_ARRAY; case VAR2_ARRAY: switch(idx->type) { case CONST_INT: av = nasl_get_var_by_num(&u->v.v_arr, idx->x.i_val, /* avoid dangling pointers */ strcmp(name, "_FCT_ANON_ARGS")); return var2cell(av); case CONST_STR: case CONST_DATA: nv = get_var_by_name(&u->v.v_arr, idx->x.str_val); return var2cell(nv != NULL ? &nv->u : NULL); default: nasl_perror(ctxt, "get_array_elem: unhandled index type 0x%x\n", idx->type); return NULL; } /*NOTREACHED*/ break; case VAR2_INT: nasl_perror(ctxt, "get_array_elem: variable %s is an integer\n", name); return NULL; case VAR2_STRING: case VAR2_DATA: if (idx->type == CONST_INT) { int l = u->v.v_str.s_siz; if (idx->x.i_val >= l) { nasl_perror(ctxt, "get_array_elem: requesting character after end of string %s (%d >= %d)\n", name, idx->x.i_val, l); tc = alloc_expr_cell(idx->line_nb, CONST_DATA /*CONST_STR*/, NULL, NULL); tc->x.str_val = estrdup(""); tc->size = 0; return tc; } else { if ( idx->x.i_val < 0) { nasl_perror(ctxt, "Negative index !\n"); return NULL; } tc = alloc_expr_cell(idx->line_nb, CONST_DATA /*CONST_STR*/, NULL, NULL); tc->x.str_val = emalloc(2); tc->x.str_val[0] = u->v.v_str.s_val[idx->x.i_val]; tc->x.str_val[1] = '\0'; tc->size = 1; return tc; } } else { nasl_perror(ctxt, "get_array_elem: Cannot use a non integer index (type 0x%x) in string\n", idx->type); return NULL; } /*NOTREACHED*/ break; default: nasl_perror(ctxt, "Severe bug: unknown variable type 0x%x %s\n", u->var_type, get_line_nb(idx)); return NULL; } /*NOTREACHED*/ return NULL;}static void free_var_chain(named_nasl_var*);static void free_anon_var(anon_nasl_var*);/* * Note: the function does not free the nasl_array structure. * Do it if necessary */voidfree_array(nasl_array* a){ int i; if (a == NULL) return; if (a->num_elt != NULL) { for (i = 0; i < a->max_idx; i ++) free_anon_var(a->num_elt[i]); efree(&a->num_elt); } if (a->hash_elt != NULL) { for (i = 0; i < VAR_NAME_HASH; i ++) free_var_chain(a->hash_elt[i]); efree(&a->hash_elt); } return;}static voidfree_var_chain(named_nasl_var* v){ if (v == NULL) return; free_var_chain(v->next_var); efree(&v->var_name); switch(v->u.var_type) { case VAR2_STRING: case VAR2_DATA: efree(&v->u.v.v_str.s_val); break; case VAR2_ARRAY: free_array(&v->u.v.v_arr); break; } efree(&v);}static voidfree_anon_var(anon_nasl_var* v){ if (v == NULL) return; switch(v->var_type) { case VAR2_STRING: case VAR2_DATA: efree(&v->v.v_str.s_val); break; case VAR2_ARRAY: free_array(&v->v.v_arr); break; } efree(&v);}static voidclear_array(nasl_array *a){ int i; if (a->num_elt != NULL) { for (i = 0; i < a->max_idx; i ++) free_anon_var(a->num_elt[i]); efree(&a->num_elt); } a->max_idx = 0; if (a->hash_elt != NULL) { for (i = 0; i < VAR_NAME_HASH; i ++) free_var_chain(a->hash_elt[i]); efree(&a->hash_elt); }}voidclear_anon_var(anon_nasl_var* v){ if (v == NULL) return; switch (v->var_type) { case VAR2_INT: v->v.v_int = 0; break; case VAR2_STRING: case VAR2_DATA: efree(&v->v.v_str.s_val); v->v.v_str.s_siz = 0; break; case VAR2_ARRAY: clear_array(&v->v.v_arr); break; } v->var_type = VAR2_UNDEF; return;}static voidcopy_anon_var(anon_nasl_var* v1, const anon_nasl_var *v2){ /* TBD: free variable if necessary? */ v1->var_type = v2->var_type; switch(v2->var_type) { case VAR2_STRING: case VAR2_DATA: if(v2->v.v_str.s_val != NULL) { v1->v.v_str.s_val = emalloc(v2->v.v_str.s_siz); memcpy(v1->v.v_str.s_val, v2->v.v_str.s_val, v2->v.v_str.s_siz); v1->v.v_str.s_siz = v2->v.v_str.s_siz; } else { v1->v.v_str.s_val = NULL; v1->v.v_str.s_siz = 0; } break; case VAR2_UNDEF: break; case VAR2_INT: v1->v.v_int = v2->v.v_int; break; case VAR2_ARRAY: copy_array(&v1->v.v_arr, &v2->v.v_arr, 0); break; default: nasl_perror(NULL, "copy_anon_var: unhandled type 0x%x\n", v2->var_type); clear_anon_var(v1); }}static anon_nasl_var*dup_anon_var(const anon_nasl_var* v){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -