📄 nasl_func.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"static inthash_str(const char* s){ return hash_str2(s, FUNC_NAME_HASH);}/* This function climbs up in the context list */static nasl_func*get_func(lex_ctxt* ctxt, const char* name, int h){ nasl_func *v, *prev; lex_ctxt *c; for (c = ctxt; c != NULL; c = c->up_ctxt) { for (prev = NULL, v = c->functions[h]; v != NULL; v = v->next_func) if (v->func_name != NULL && strcmp(name, v->func_name) == 0) {#ifdef SILLY_OPT if (prev != NULL) /* Move it to start of list */ { prev->next_func = v->next_func; v->next_func = c->functions[h]; c->functions[h]= v; }#endif return v; }#ifdef SILLY_OPT else prev = v;#endif } return NULL;}nasl_func*insert_nasl_func(lex_ctxt* lexic, const char* fname, tree_cell* decl_node){ int h = hash_str(fname); int i; nasl_func *pf; tree_cell *pc; if (get_func(lexic, fname, h) != NULL) { nasl_perror(lexic, "insert_nasl_func: function '%s' is already defined\n", fname); return NULL; } pf = emalloc(sizeof(nasl_func)); pf->func_name = estrdup(fname); if (decl_node != NULL && decl_node != FAKE_CELL) { for (pc = decl_node->link[0]; pc != NULL; pc = pc->link[0]) if (pc->x.str_val == NULL) pf->nb_unnamed_args ++; else pf->nb_named_args ++; pf->args_names = emalloc(sizeof(char*) * pf->nb_named_args); for (i = 0, pc = decl_node->link[0]; pc != NULL; pc = pc->link[0]) if (pc->x.str_val != NULL) pf->args_names[i ++] = estrdup(pc->x.str_val); /* sort arg names */ qsort(pf->args_names, pf->nb_named_args, sizeof(pf->args_names[0]), strcmp); pf->block = decl_node->link[1]; ref_cell(pf->block); } /* Allow variable number of arguments for user defined functions */ if (decl_node != NULL) pf->nb_unnamed_args = 9999; pf->next_func = lexic->functions[h]; lexic->functions[h] = pf; return pf;}tree_cell*decl_nasl_func(lex_ctxt* lexic, tree_cell* decl_node){ if (decl_node == NULL || decl_node == FAKE_CELL) { nasl_perror(lexic, "Cannot insert NULL or FAKE cell as function\n"); return NULL; } if (insert_nasl_func(lexic, decl_node->x.str_val, decl_node) == NULL) return NULL; else return FAKE_CELL;}nasl_func*get_func_ref_by_name(lex_ctxt* ctxt, const char* name){ int h = hash_str(name); nasl_func *f; if ((f = get_func(ctxt, name, h)) != NULL) return f; else return NULL;}static intstringcompare(const void * a, const void * b){ char ** s1 = (char**)a, ** s2 = (char**)b; return strcmp(*s1, *s2);}extern FILE* nasl_trace_fp;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}tree_cell* nasl_return(lex_ctxt* ctxt, tree_cell* retv){ tree_cell *c; retv = cell2atom(ctxt, retv); if (retv == NULL) retv = FAKE_CELL; if (retv != FAKE_CELL && retv->type == REF_ARRAY) /* We have to "copy" it as the referenced array will be freed */ { c = copy_ref_array(retv); deref_cell(retv); retv = c; } while (ctxt != NULL) { ctxt->ret_val = retv; ref_cell(retv); if (ctxt->fct_ctxt) break; ctxt = ctxt->up_ctxt; } /* Bug? Do not return NULL, as we may test it to break the control flow */ deref_cell(retv); return FAKE_CELL;}static voidfree_func(nasl_func* f){ int i; efree(&f->func_name); if (! (f->flags & FUNC_FLAG_INTERNAL)) { for (i = 0; i < f->nb_named_args; i ++) efree(f->args_names + i); efree(&f->func_name); efree(&f->args_names); deref_cell(f->block); } free(f);}voidfree_func_chain(nasl_func* f){ if (f == NULL) return; free_func_chain(f->next_func); free_func(f);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -