OpenVAS Scanner  22.7.9
nasl_func.c
Go to the documentation of this file.
1 /* SPDX-FileCopyrightText: 2023 Greenbone AG
2  * SPDX-FileCopyrightText: 2002-2004 Tenable Network Security
3  *
4  * SPDX-License-Identifier: GPL-2.0-only
5  */
6 
7 #include "nasl_func.h"
8 
9 #include "exec.h"
10 #include "nasl_debug.h"
11 #include "nasl_global_ctxt.h"
12 #include "nasl_lex_ctxt.h"
13 #include "nasl_tree.h"
14 #include "nasl_var.h"
15 
16 #include <glib.h> /* for g_free */
17 #include <stdlib.h> /* for free */
18 #include <string.h> /* for strcmp */
19 
24 static nasl_func *
25 get_func (lex_ctxt *ctxt, const char *name)
26 {
27  lex_ctxt *c;
28 
29  for (c = ctxt; c != NULL; c = c->up_ctxt)
30  {
31  nasl_func *v = g_hash_table_lookup (c->functions, name);
32 
33  if (v)
34  return v;
35  }
36 
37  return func_is_internal (name);
38 }
39 
40 nasl_func *
41 insert_nasl_func (lex_ctxt *lexic, const char *fname, tree_cell *decl_node,
42  int lint_mode)
43 {
44  nasl_func *pf;
45 
46  if (get_func (lexic, fname))
47  {
48  if (lint_mode == 0)
49  nasl_perror (
50  lexic, "insert_nasl_func: function '%s' is already defined\n", fname);
51  return NULL;
52  }
53  pf = g_malloc0 (sizeof (nasl_func));
54  pf->func_name = g_strdup (fname);
55 
56  if (decl_node != NULL && decl_node != FAKE_CELL)
57  {
58  pf->block = decl_node->link[1];
59  ref_cell (pf->block);
60  }
61  g_hash_table_insert (lexic->functions, pf->func_name, pf);
62  return pf;
63 }
64 
65 tree_cell *
66 decl_nasl_func (lex_ctxt *lexic, tree_cell *decl_node, int lint_mode)
67 {
68  if (decl_node == NULL || decl_node == FAKE_CELL)
69  {
70  nasl_perror (lexic, "Cannot insert NULL or FAKE cell as function\n");
71  return NULL;
72  }
73 
74  if (insert_nasl_func (lexic, decl_node->x.str_val, decl_node, lint_mode)
75  == NULL)
76  return NULL;
77  else
78  return FAKE_CELL;
79 }
80 
81 nasl_func *
82 get_func_ref_by_name (lex_ctxt *ctxt, const char *name)
83 {
84  nasl_func *f;
85 
86  if ((f = get_func (ctxt, name)))
87  return f;
88  else
89  return NULL;
90 }
91 
92 extern FILE *nasl_trace_fp;
93 
94 tree_cell *
95 nasl_func_call (lex_ctxt *lexic, const nasl_func *f, tree_cell *arg_list)
96 {
97  int nb_u = 0, nb_a = 0;
98  tree_cell *pc = NULL, *pc2 = NULL, *retc = NULL;
99  lex_ctxt *lexic2 = NULL;
100  char *trace_buf = NULL;
101  char *temp_funname = NULL, *tmp_filename = NULL;
102  int trace_buf_len = 0, tn;
103 #define TRACE_BUF_SZ 255
104 
105  /* 1. Create a new context */
106  lexic2 = init_empty_lex_ctxt ();
107  lexic2->script_infos = lexic->script_infos;
108  lexic2->oid = lexic->oid;
109  lexic2->recv_timeout = lexic->recv_timeout;
110  lexic2->fct_ctxt = 1;
111 
112  if (nasl_trace_fp != NULL)
113  {
114  trace_buf = g_malloc0 (TRACE_BUF_SZ);
115  tn = snprintf (trace_buf, TRACE_BUF_SZ, "Call %s(", f->func_name);
116  if (tn > 0)
117  trace_buf_len += tn;
118  }
119 
120  for (pc = arg_list; pc != NULL; pc = pc->link[1])
121  if (pc->x.str_val == NULL)
122  nb_u++;
123 
124  /*
125  * I should look exactly how unnamed arguments works...
126  * Or maybe I should remove this feature?
127  */
128 
129  for (nb_u = 0, pc = arg_list; pc != NULL; pc = pc->link[1])
130  {
131  pc2 = cell2atom (lexic, pc->link[0]);
132  if (pc->x.str_val == NULL)
133  {
134  /* 2. Add unnamed (numbered) variables for unnamed args */
135  if (add_numbered_var_to_ctxt (lexic2, nb_u, pc2) == NULL)
136  goto error;
137  nb_u++;
138  if (nasl_trace_fp != NULL && trace_buf_len < TRACE_BUF_SZ)
139  {
140  tn = snprintf (trace_buf + trace_buf_len,
141  TRACE_BUF_SZ - trace_buf_len, "%s%d: %s",
142  nb_a > 0 ? ", " : "", nb_u, dump_cell_val (pc2));
143  if (tn > 0)
144  trace_buf_len += tn;
145  }
146  nb_a++;
147  }
148  else
149  {
150  /* 3. and add named variables for named args */
151  if (add_named_var_to_ctxt (lexic2, pc->x.str_val, pc2) == NULL)
152  goto error;
153  if (nasl_trace_fp != NULL && trace_buf_len < TRACE_BUF_SZ)
154  {
155  tn = snprintf (trace_buf + trace_buf_len,
156  TRACE_BUF_SZ - trace_buf_len, "%s%s: %s",
157  nb_a > 0 ? ", " : "", pc->x.str_val,
158  dump_cell_val (pc2));
159  if (tn > 0)
160  trace_buf_len += tn;
161  }
162  nb_a++;
163  }
164  deref_cell (pc2);
165  }
166 
167  if (nasl_trace_fp != NULL)
168  {
169  if (trace_buf_len < TRACE_BUF_SZ)
170  nasl_trace (lexic, "NASL> %s)\n", trace_buf);
171  else
172  nasl_trace (lexic, "NASL> %s ...)\n", trace_buf);
173  }
174  /* trace_buf freed here because nasl_trace_fp might get set to NULL during the
175  * execution of nasl_func_call and therefore not get freed if we only free in
176  * the previous if block. This is done to make static analyzer happy. */
177  g_free (trace_buf);
178 
179  /* 4. Chain new context to old (lexic) */
180  lexic2->up_ctxt = lexic;
181  /* 5. Execute */
182  tmp_filename = g_strdup (nasl_get_filename (NULL));
184  if (func_is_internal (f->func_name))
185  {
186 #pragma GCC diagnostic push
187 #pragma GCC diagnostic ignored "-Wpedantic"
188  // unless it is arcane system this void casting should work
189  // therefore ignoring pedantic here.
190  tree_cell *(*pf2) (lex_ctxt *) = f->block;
191 #pragma GCC diagnostic pop
192  retc = pf2 (lexic2);
193  }
194  else
195  {
196  temp_funname = g_strdup (nasl_get_function_name ());
198  retc = nasl_exec (lexic2, f->block);
199  deref_cell (retc);
200  retc = FAKE_CELL;
201  nasl_set_function_name (temp_funname);
202  g_free (temp_funname);
203  }
204  nasl_set_filename (tmp_filename);
205  g_free (tmp_filename);
206 
207  if ((retc == NULL || retc == FAKE_CELL)
208  && (lexic2->ret_val != NULL && lexic2->ret_val != FAKE_CELL))
209  {
210  retc = lexic2->ret_val;
211  ref_cell (retc);
212  }
213 
214  if (nasl_trace_enabled ())
215  nasl_trace (lexic, "NASL> Return %s: %s\n", f->func_name,
216  dump_cell_val (retc));
217  if (!nasl_is_leaf (retc))
218  {
219  nasl_perror (lexic,
220  "nasl_func_call: return value from %s is not atomic!\n",
221  f->func_name);
222  nasl_dump_tree (retc);
223  }
224 
225  free_lex_ctxt (lexic2);
226  lexic2 = NULL;
227  return retc;
228 
229 error:
230  g_free (trace_buf);
231  free_lex_ctxt (lexic2);
232  return NULL;
233 }
234 
235 tree_cell *
237 {
238  tree_cell *c;
239 
240  retv = cell2atom (ctxt, retv);
241  if (retv == NULL)
242  retv = FAKE_CELL;
243 
244  if (retv != FAKE_CELL && retv->type == REF_ARRAY)
245  /* We have to "copy" it as the referenced array will be freed */
246  {
247  c = copy_ref_array (retv);
248  deref_cell (retv);
249  retv = c;
250  }
251 
252  while (ctxt != NULL)
253  {
254  ctxt->ret_val = retv;
255  ref_cell (retv);
256  if (ctxt->fct_ctxt)
257  break;
258  ctxt = ctxt->up_ctxt;
259  }
260  /* Bug? Do not return NULL, as we may test it to break the control flow */
261  deref_cell (retv);
262  return FAKE_CELL;
263 }
264 
265 void
267 {
268  if (!f)
269  return;
270 
271  g_free (f->func_name);
272  g_free (f);
273 }
get_func_ref_by_name
nasl_func * get_func_ref_by_name(lex_ctxt *ctxt, const char *name)
Definition: nasl_func.c:82
nasl_trace
void nasl_trace(lex_ctxt *lexic, char *msg,...)
Prints debug message in printf fashion to nasl_trace_fp if it exists.
Definition: nasl_debug.c:175
nasl_return
tree_cell * nasl_return(lex_ctxt *ctxt, tree_cell *retv)
Definition: nasl_func.c:236
add_named_var_to_ctxt
named_nasl_var * add_named_var_to_ctxt(lex_ctxt *, const char *, tree_cell *)
Definition: nasl_var.c:813
get_func
static nasl_func * get_func(lex_ctxt *ctxt, const char *name)
This function climbs up in the context list and searches for a given.
Definition: nasl_func.c:25
add_numbered_var_to_ctxt
anon_nasl_var * add_numbered_var_to_ctxt(lex_ctxt *, int, tree_cell *)
Definition: nasl_var.c:784
TC::str_val
char * str_val
Definition: nasl_tree.h:103
nasl_get_function_name
const char * nasl_get_function_name()
Definition: nasl_debug.c:82
nasl_dump_tree
void nasl_dump_tree(const tree_cell *c)
Definition: nasl_tree.c:366
TC::x
union TC::@5 x
struct_lex_ctxt::functions
GHashTable * functions
Definition: nasl_lex_ctxt.h:37
nasl_exec
tree_cell * nasl_exec(lex_ctxt *lexic, tree_cell *st)
Execute a parse tree.
Definition: exec.c:770
st_nasl_func
Definition: nasl_func.h:15
FAKE_CELL
#define FAKE_CELL
Definition: nasl_tree.h:110
nasl_set_function_name
void nasl_set_function_name(const char *funname)
Definition: nasl_debug.c:73
exec.h
name
const char * name
Definition: nasl_init.c:411
TRACE_BUF_SZ
#define TRACE_BUF_SZ
struct_lex_ctxt::up_ctxt
struct struct_lex_ctxt * up_ctxt
Definition: nasl_lex_ctxt.h:24
cell2atom
tree_cell * cell2atom(lex_ctxt *lexic, tree_cell *c1)
Definition: exec.c:194
nasl_debug.h
nasl_perror
void nasl_perror(lex_ctxt *lexic, char *msg,...)
Definition: nasl_debug.c:111
decl_nasl_func
tree_cell * decl_nasl_func(lex_ctxt *lexic, tree_cell *decl_node, int lint_mode)
Definition: nasl_func.c:66
nasl_trace_enabled
int nasl_trace_enabled(void)
Checks if the nasl_trace_fp is set.
Definition: nasl_debug.c:161
insert_nasl_func
nasl_func * insert_nasl_func(lex_ctxt *lexic, const char *fname, tree_cell *decl_node, int lint_mode)
Definition: nasl_func.c:41
func_is_internal
nasl_func * func_is_internal(const char *)
Definition: nasl_init.c:526
dump_cell_val
char * dump_cell_val(const tree_cell *c)
Definition: nasl_tree.c:234
nasl_lex_ctxt.h
struct_lex_ctxt::oid
const char * oid
Definition: nasl_lex_ctxt.h:31
free_lex_ctxt
void free_lex_ctxt(lex_ctxt *c)
Definition: nasl_lex_ctxt.c:43
struct_lex_ctxt::fct_ctxt
unsigned fct_ctxt
Definition: nasl_lex_ctxt.h:26
nasl_func.h
st_nasl_func::block
void * block
Definition: nasl_func.h:17
free_func
void free_func(nasl_func *f)
Definition: nasl_func.c:266
struct_lex_ctxt::script_infos
struct script_infos * script_infos
Definition: nasl_lex_ctxt.h:30
st_nasl_func::func_name
char * func_name
Definition: nasl_func.h:16
TC
Definition: nasl_tree.h:94
struct_lex_ctxt
Definition: nasl_lex_ctxt.h:23
TC::type
short type
Definition: nasl_tree.h:95
TC::link
struct TC * link[4]
Definition: nasl_tree.h:107
nasl_var.h
ref_cell
void ref_cell(tree_cell *c)
Definition: nasl_tree.c:167
nasl_global_ctxt.h
nasl_is_leaf
int nasl_is_leaf(const tree_cell *pc)
Definition: nasl_tree.c:389
nasl_func_call
tree_cell * nasl_func_call(lex_ctxt *lexic, const nasl_func *f, tree_cell *arg_list)
Definition: nasl_func.c:95
struct_lex_ctxt::recv_timeout
int recv_timeout
Definition: nasl_lex_ctxt.h:32
nasl_trace_fp
FILE * nasl_trace_fp
Definition: exec.c:357
copy_ref_array
tree_cell * copy_ref_array(const tree_cell *c1)
Definition: nasl_var.c:537
nasl_get_filename
const char * nasl_get_filename(const char *function)
Definition: nasl_debug.c:60
REF_ARRAY
@ REF_ARRAY
Definition: nasl_tree.h:89
nasl_set_filename
void nasl_set_filename(const char *filename)
Definition: nasl_debug.c:88
deref_cell
void deref_cell(tree_cell *c)
Definition: nasl_tree.c:181
init_empty_lex_ctxt
lex_ctxt * init_empty_lex_ctxt()
Definition: nasl_lex_ctxt.c:20
nasl_tree.h
struct_lex_ctxt::ret_val
tree_cell * ret_val
Definition: nasl_lex_ctxt.h:25