Skip to content

Commit

Permalink
Add: openvas-nasl-lint informs about include error on function calls
Browse files Browse the repository at this point in the history
When linting a `main.nasl` as

```
include ("2.inc");
include ("1.inc");

hello();
```

Based on `2.inc`:

```
function hello() {
    hi();
    display("hello");
}
```

Based on `1.inc`:

```
function hi() {
    display("hi");
}
```

`openvas-nasl-lint --strict-includes main.nasl` will identify the include order:

```
lib  nasl-Message: 13:33:42.763: [1166407](main.nasl:0) 2.inc must be included after 1.inc (usage of hi).
lib  nasl-Message: 13:33:42.763: [1166407](main.nasl:2) The included file '2.inc' is never used.
lib  nasl-Message: 13:33:42.764: [1166407](main.nasl:2) The included file '1.inc' is never used.
4 errors while processing main.nasl.
1 scripts with one or more errors found
```

Currently strict-includes are not a default when running
openvas-nasl-lint since there are circumstances where it is currently
legal to have unorderd includes.

This may change in the future.
  • Loading branch information
nichtsfrei committed May 24, 2022
1 parent 92f7b98 commit 6e3a09f
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 6 deletions.
47 changes: 41 additions & 6 deletions nasl/lint.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "nasl_tree.h"
#include "nasl_var.h"

#include <stdio.h>
#include <string.h>
#include <unistd.h>

Expand Down Expand Up @@ -436,6 +437,14 @@ is_deffunc_used (const char *funcname, const char *filename,
return 0;
}

int features = 0;

void
nasl_lint_feature_flags (int flag)
{
features = flag;
}

/**
* @brief Check if a called function was defined.
*/
Expand All @@ -448,6 +457,7 @@ nasl_lint_call (lex_ctxt *lexic, tree_cell *st, GHashTable **include_files,
tree_cell *ret = FAKE_CELL;
nasl_func *pf;
char *incname = NULL;
int f_inc_ord, c_inc_order, rc = 0;
static int defined_flag = 0;

/** This checks if a defined function is called. If it is never called
Expand Down Expand Up @@ -475,6 +485,7 @@ nasl_lint_call (lex_ctxt *lexic, tree_cell *st, GHashTable **include_files,

case NODE_FUN_CALL:
pf = get_func_ref_by_name (lexic, st->x.str_val);

if (pf == NULL)
{
incname = g_hash_table_lookup (*func_fnames_tab, st->x.str_val);
Expand All @@ -486,14 +497,38 @@ nasl_lint_call (lex_ctxt *lexic, tree_cell *st, GHashTable **include_files,
called_f_aux = g_slist_find_custom (*def_func_tree, st->x.str_val,
(GCompareFunc) list_cmp1);
if (called_f_aux != NULL)
if (reverse_search (def_func_tree, called_f_aux))
{
nasl_perror (lexic, "Undefined function '%s'\n", st->x.str_val);
return NULL;
}
{
if (reverse_search (def_func_tree, called_f_aux))
{
nasl_perror (lexic, "Undefined function '%s'\n",
st->x.str_val);
return NULL;
}
}
}
else
{
// only check functions that are not internal
if ((features & NLFF_STRICT_INCLUDES)
&& func_is_internal (st->x.str_val) == NULL)
{
// get incname verify include order when not 0
incname = (char *) nasl_get_filename (st->x.str_val);
if (incname != NULL)
{
f_inc_ord = nasl_get_include_order (incname);
c_inc_order = nasl_get_include_order (st->name);
// if caller definition is not the main file but included
// before the function definition warn about an include error
if (c_inc_order > 0 && c_inc_order < f_inc_ord)
{
nasl_perror (
lexic, "%s must be included after %s (usage of %s).",
st->name, incname, st->x.str_val);
rc = -1;
}
}
}
// Check if function parameters are right
if (validate_function (lexic, st) == NULL)
return NULL;
Expand Down Expand Up @@ -523,7 +558,7 @@ nasl_lint_call (lex_ctxt *lexic, tree_cell *st, GHashTable **include_files,
def_func_tree))
== NULL)
return NULL;
return ret;
return rc == 0 ? ret : NULL;
}
}

Expand Down
9 changes: 9 additions & 0 deletions nasl/lint.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@

#include "nasl_lex_ctxt.h"

enum nasl_lint_feature_flags
{
NLFF_NONE = 0,
NLFF_STRICT_INCLUDES = 1
};

void
nasl_lint_feature_flags (int flags);

tree_cell *
nasl_lint (lex_ctxt *lexic, tree_cell *st);

Expand Down
8 changes: 8 additions & 0 deletions nasl/nasl-lint.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
* @brief Source of the NASL linter of OpenVAS.
*/

#include "lint.h"
#include "nasl.h" /* exec_nasl_script */

#include <gio/gio.h> /* g_file_... */
Expand Down Expand Up @@ -165,13 +166,16 @@ main (int argc, char **argv)
{
int mode = 0;
int err = 0;
int fflag = 0;
static gboolean debug = FALSE;
static gchar *include_dir = NULL;
static gchar *nvt_file_list = NULL;
static unsigned char strict_includes = 0;
static const gchar **nvt_files = NULL;
struct script_infos *script_infos = g_malloc0 (sizeof (struct script_infos));
GError *error = NULL;
GOptionContext *option_context;

static GOptionEntry entries[] = {
{"debug", 'd', 0, G_OPTION_ARG_NONE, &debug, "Output debug log messages.",
NULL},
Expand All @@ -181,6 +185,8 @@ main (int argc, char **argv)
"Search for includes in <dir>", "<dir>"},
{G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &nvt_files,
"Absolute path to one or more nasl scripts", "NASL_FILE..."},
{"strict-includes", 0, 0, G_OPTION_ARG_NONE, &strict_includes,
"Enables check for strict include order.", NULL},
{NULL, 0, 0, 0, NULL, NULL, NULL}};

option_context =
Expand All @@ -191,6 +197,8 @@ main (int argc, char **argv)
g_error ("%s\n\n", error->message);
}
g_option_context_free (option_context);
fflag |= strict_includes;
nasl_lint_feature_flags (fflag);

mode |= NASL_COMMAND_LINE;
/* signing mode */
Expand Down
3 changes: 3 additions & 0 deletions nasl/nasl_debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ nasl_get_filename (const char *);
void
nasl_set_function_name (const char *);

int
nasl_get_include_order (const char *);

const char *
nasl_get_function_name (void);
#endif
4 changes: 4 additions & 0 deletions nasl/nasl_global_ctxt.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,21 @@
#define _NASL_CTX_H

/* for FILE */
#include "nasl_tree.h"

#include <gvm/util/kb.h>
#include <stdio.h>

typedef struct
{
int line_nb;
char *name;
int always_signed; /**< If set disable signature check during scans and feed
upload. */
int exec_descr; /**< Tell grammar that is a feed upload process or a running a
scan process. */
int index;
unsigned int include_order;
tree_cell *tree;
char *buffer;
kb_t kb;
Expand Down
39 changes: 39 additions & 0 deletions nasl/nasl_grammar.y
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#define YYLEX_ERRC err_c

#define LNB (((naslctxt*)parm)->line_nb)
#define LN (((naslctxt*)parm)->name)
#define ERRC err_c

#include <ctype.h> /* for isalpha */
Expand All @@ -53,6 +54,7 @@
static char *parse_buffer = NULL;

static int parse_len = 0;
static int include_order = 0;

static void naslerror(naslctxt *, int *, const char *);

Expand Down Expand Up @@ -181,6 +183,7 @@ func_decl: FUNCTION identifier '(' arg_decl ')' block
{
nasl_set_function_filename ($2);
$$ = alloc_typed_cell (NODE_FUN_DEF);
$$->name = LN;
$$->line_nb = LNB;
$$->x.str_val = $2;
$$->link[0] = $4;
Expand All @@ -191,12 +194,14 @@ arg_decl: { $$ = NULL; } | arg_decl_1 { $$ = $1; };
arg_decl_1: identifier
{
$$ = alloc_typed_cell (NODE_DECL);
$$->name = LN;
$$->line_nb = LNB;
$$->x.str_val = $1;
}
| identifier ',' arg_decl_1
{
$$ = alloc_typed_cell (NODE_DECL);
$$->name = LN;
$$->line_nb = LNB;
$$->x.str_val = $1;
$$->link[0] = $3;
Expand All @@ -212,6 +217,7 @@ instr_list: instr
else
{
$$ = alloc_typed_cell (NODE_INSTR_L);
$$->name = LN;
$$->line_nb = LNB;
$$->link[0] = $1;
$$->link[1] = $2;
Expand All @@ -228,10 +234,12 @@ simple_instr : aff | post_pre_incr | rep
| func_call | ret | inc | loc | glob
| BREAK {
$$ = alloc_typed_cell (NODE_BREAK);
$$->name = LN;
$$->line_nb = LNB;
}
| CONTINUE {
$$ = alloc_typed_cell (NODE_CONTINUE);
$$->name = LN;
$$->line_nb = LNB;
}
| /* nop */ { $$ = NULL; };
Expand All @@ -240,25 +248,29 @@ simple_instr : aff | post_pre_incr | rep
ret: RETURN expr
{
$$ = alloc_typed_cell (NODE_RETURN);
$$->name = LN;
$$->line_nb = LNB;
$$->link[0] = $2;
} |
RETURN
{
$$ = alloc_typed_cell (NODE_RETURN);
$$->name = LN;
$$->line_nb = LNB;
} ;

/* If block */
if_block: IF '(' expr ')' instr
{
$$ = alloc_typed_cell (NODE_IF_ELSE);
$$->name = LN;
$$->line_nb = LNB;
$$->link[0] = $3; $$->link[1] = $5;
}
| IF '(' expr ')' instr ELSE instr
{
$$ = alloc_typed_cell (NODE_IF_ELSE);
$$->name = LN;
$$->line_nb = LNB;
$$->link[0] = $3; $$->link[1] = $5; $$->link[2] = $7;
};
Expand All @@ -268,6 +280,7 @@ loop : for_loop | while_loop | repeat_loop | foreach_loop ;
for_loop : FOR '(' aff_func ';' expr ';' aff_func ')' instr
{
$$ = alloc_typed_cell (NODE_FOR);
$$->name = LN;
$$->line_nb = LNB;
$$->link[0] = $3;
$$->link[1] = $5;
Expand All @@ -278,13 +291,15 @@ for_loop : FOR '(' aff_func ';' expr ';' aff_func ')' instr
while_loop : WHILE '(' expr ')' instr
{
$$ = alloc_typed_cell (NODE_WHILE);
$$->name = LN;
$$->line_nb = LNB;
$$->link[0] = $3;
$$->link[1] = $5;
} ;
repeat_loop : REPEAT instr UNTIL expr ';'
{
$$ = alloc_typed_cell (NODE_REPEAT_UNTIL);
$$->name = LN;
$$->line_nb = LNB;
$$->link[0] = $2;
$$->link[1] = $4;
Expand All @@ -293,6 +308,7 @@ repeat_loop : REPEAT instr UNTIL expr ';'
foreach_loop : FOREACH identifier '(' expr ')' instr
{
$$ = alloc_typed_cell (NODE_FOREACH);
$$->name = LN;
$$->line_nb = LNB;
$$->x.str_val = $2;
$$->link[0] = $4;
Expand All @@ -306,6 +322,7 @@ aff_func: aff | post_pre_incr | func_call | /*nop */ { $$ = NULL; };
rep: func_call REP expr
{
$$ = alloc_typed_cell (NODE_REPEATED);
$$->name = LN;
$$->line_nb = LNB;
$$->link[0] = $1;
$$->link[1] = $3;
Expand Down Expand Up @@ -347,6 +364,10 @@ inc: INCLUDE '(' string ')'
{
if (!naslparse (&subctx, err_c))
{
// set the name of tree to the filename for further
// identification of origin (e.g. whos is calling a func).
subctx.tree->name = $3;
subctx.tree->include_order = include_order;
$$ = subctx.tree;
g_hash_table_insert (includes_hash, $3, $$);
ref_cell ($$);
Expand All @@ -373,6 +394,7 @@ inc: INCLUDE '(' string ')'
func_call: identifier '(' arg_list ')'
{
$$ = alloc_typed_cell (NODE_FUN_CALL);
$$->name = LN;
$$->line_nb = LNB;
$$->x.str_val = $1;
$$->link[0] = $3;
Expand All @@ -388,12 +410,14 @@ arg_list_1: arg | arg ',' arg_list_1
arg : expr
{
$$ = alloc_typed_cell (NODE_ARG);
$$->name = LN;
$$->line_nb = LNB;
$$->link[0] = $1;
}
| identifier ':' expr
{
$$ = alloc_typed_cell (NODE_ARG);
$$->name = LN;
$$->line_nb = LNB;
$$->x.str_val = $1;
$$->link[0] = $3;
Expand Down Expand Up @@ -726,6 +750,8 @@ init_nasl_ctx(naslctxt* pc, const char* name)
if (! inc_dirs) add_nasl_inc_dir("");

pc->line_nb = 1;
pc->name = (char *) name;
pc->include_order = include_order++;
pc->tree = NULL;
if (!parse_len)
{
Expand Down Expand Up @@ -843,6 +869,19 @@ nasl_clean_inc (void)
includes_hash = NULL;
}

int
nasl_get_include_order(const char* c)
{
tree_cell *ctx;
if (!includes_hash)
return -2;

if ((ctx = g_hash_table_lookup (includes_hash, c))) {
return ctx->include_order;
}
return -1;
}

enum lex_state {
ST_START = 0,
ST_SPACE,
Expand Down
2 changes: 2 additions & 0 deletions nasl/nasl_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,10 @@ typedef struct TC
{
short type;
short line_nb;
char *name;
short ref_count; /* Cell is freed when count reaches zero */
int size;
int include_order;
union
{
char *str_val;
Expand Down

0 comments on commit 6e3a09f

Please sign in to comment.