OpenVAS Scanner 23.32.3
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
24static nasl_func *
25get_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
41insert_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)
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
66decl_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
83{
84 nasl_func *f;
85
86 if ((f = get_func (ctxt, name)))
87 return f;
88 else
89 return NULL;
90}
91
92extern FILE *nasl_trace_fp;
93
95nasl_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));
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
229error:
230 g_free (trace_buf);
231 free_lex_ctxt (lexic2);
232 return NULL;
233}
234
235tree_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
265void
267{
268 if (!f)
269 return;
270
271 g_free (f->func_name);
272 g_free (f);
273}
FILE * nasl_trace_fp
Definition exec.c:357
tree_cell * cell2atom(lex_ctxt *lexic, tree_cell *c1)
Definition exec.c:194
tree_cell * nasl_exec(lex_ctxt *lexic, tree_cell *st)
Execute a parse tree.
Definition exec.c:770
int nasl_trace_enabled(void)
Checks if the nasl_trace_fp is set.
Definition nasl_debug.c:155
void nasl_set_function_name(const char *funname)
Definition nasl_debug.c:67
void nasl_set_filename(const char *filename)
Definition nasl_debug.c:82
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:169
const char * nasl_get_function_name()
Definition nasl_debug.c:76
void nasl_perror(lex_ctxt *lexic, char *msg,...)
Definition nasl_debug.c:105
const char * nasl_get_filename(const char *function)
Definition nasl_debug.c:54
void free_func(nasl_func *f)
Definition nasl_func.c:266
tree_cell * nasl_func_call(lex_ctxt *lexic, const nasl_func *f, tree_cell *arg_list)
Definition nasl_func.c:95
#define TRACE_BUF_SZ
tree_cell * decl_nasl_func(lex_ctxt *lexic, tree_cell *decl_node, int lint_mode)
Definition nasl_func.c:66
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
nasl_func * insert_nasl_func(lex_ctxt *lexic, const char *fname, tree_cell *decl_node, int lint_mode)
Definition nasl_func.c:41
nasl_func * get_func_ref_by_name(lex_ctxt *ctxt, const char *name)
Definition nasl_func.c:82
tree_cell * nasl_return(lex_ctxt *ctxt, tree_cell *retv)
Definition nasl_func.c:236
struct st_nasl_func nasl_func
nasl_func * func_is_internal(const char *)
Definition nasl_init.c:554
const char * name
Definition nasl_init.c:439
void free_lex_ctxt(lex_ctxt *c)
lex_ctxt * init_empty_lex_ctxt()
named_nasl_var * add_named_var_to_ctxt(lex_ctxt *, const char *, tree_cell *)
Definition nasl_var.c:810
struct struct_lex_ctxt lex_ctxt
anon_nasl_var * add_numbered_var_to_ctxt(lex_ctxt *, int, tree_cell *)
Definition nasl_var.c:781
void ref_cell(tree_cell *c)
Definition nasl_tree.c:164
char * dump_cell_val(const tree_cell *c)
Definition nasl_tree.c:231
void nasl_dump_tree(const tree_cell *c)
Definition nasl_tree.c:363
int nasl_is_leaf(const tree_cell *pc)
Definition nasl_tree.c:386
void deref_cell(tree_cell *c)
Definition nasl_tree.c:178
@ REF_ARRAY
Definition nasl_tree.h:89
struct TC tree_cell
#define FAKE_CELL
Definition nasl_tree.h:110
tree_cell * copy_ref_array(const tree_cell *c1)
Definition nasl_var.c:534
struct TC * link[4]
Definition nasl_tree.h:107
union TC::@332262321161220155002104006201360276211317150140 x
char * str_val
Definition nasl_tree.h:103
short type
Definition nasl_tree.h:95
void * block
Definition nasl_func.h:17
char * func_name
Definition nasl_func.h:16
GHashTable * functions
struct script_infos * script_infos
tree_cell * ret_val
const char * oid
struct struct_lex_ctxt * up_ctxt