OpenVAS Scanner 23.40.3
lint.c File Reference
#include "lint.h"
#include "exec.h"
#include "nasl.h"
#include "nasl_debug.h"
#include "nasl_func.h"
#include "nasl_global_ctxt.h"
#include "nasl_init.h"
#include "nasl_lex_ctxt.h"
#include "nasl_tree.h"
#include "nasl_var.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
Include dependency graph for lint.c:

Go to the source code of this file.

Data Structures

struct  st_func_info
 Define struct to store information about a called function. More...

Macros

#define G_LOG_DOMAIN   "lib nasl"
 GLib logging domain.

Typedefs

typedef struct st_func_info func_info
 Define struct to store information about a called function.

Functions

static void init_errors_cnt ()
static void inc_errors_cnt ()
static int get_errors_cnt ()
static void free_list_func (func_info *data)
 Free a func_info structure.
static void add_predef_varname (GSList **defined_var)
 Add keywords to the varnames list.
static gint list_cmp1 (gconstpointer lelem, gconstpointer data)
 This function is called by g_slist_find_custom.
static gint reverse_search (GSList **def_func_tree, GSList *finfo)
 Check if an undefined called function is needed or not. This is the case in which the function is called from a nested and defined function but never called.
static gint list_cmp (gconstpointer lelem, gconstpointer data)
 This function is called by g_slist_find_custom.
static void check_called_files (gpointer key, gpointer value, GSList **unusedfiles)
 This function is called by g_hash_table_foreach to check if an include file was used or not. If the file is not used, it is added to a list.
static void print_uncall_files (gpointer filename, gpointer lexic)
 It shows a msg for unused included files.
static tree_cellnasl_lint_def (lex_ctxt *lexic, tree_cell *st, int lint_mode, GHashTable **include_files, GHashTable **func_fnames_tab, gchar *err_fname, GSList **called_funcs, GSList **def_func_tree)
 Loads all defined functions. Also, It constructs a tree of called functions to help recognize a not defined function which is never called (nested functions).
static char * get_argument_by_name (tree_cell *st, char *name)
 Checks if a given Arguments is within a given Argument List.
static tree_cellvalidate_script_xref (lex_ctxt *lexic, tree_cell *st)
 Validates parameters of a script_xref function call.
static tree_cellvalidate_function (lex_ctxt *lexic, tree_cell *st)
 Validate functions.
static int is_deffunc_used (const char *funcname, const char *filename, GSList *def_func_tree)
 Returns 1 if the function is at least used once by another caller than filename otherwise 0.
void nasl_lint_feature_flags (int flag)
static tree_cellnasl_lint_call (lex_ctxt *lexic, tree_cell *st, GHashTable **include_files, GHashTable **func_fnames_tab, gchar *err_fname, GSList **called_funcs, GSList **def_func_tree)
 Check if a called function was defined.
static tree_cellnasl_lint_defvar (lex_ctxt *lexic, tree_cell *st, GHashTable **include_files, GHashTable **func_fnames_tab, gchar *err_fname, GSList **defined_var, GSList **called_funcs)
 Consider all cases in which a variable is set, and add it to a list. If a variable is read, it checks if it was previously added to the list.
static tree_cellmake_call_func_list (lex_ctxt *lexic, tree_cell *st, GSList **called_funcs)
 Make a list of all called functions.
static tree_cellcheck_description_block_xref (lex_ctxt *lexic, tree_cell *st)
 Sanity check of the script_xref parameters in the description block.
static tree_cellcheck_description_block (lex_ctxt *lexic, tree_cell *st)
 Sanity check of the description block.
static tree_cellfind_description_block (lex_ctxt *lexic, tree_cell *st)
 Sanity check of the description block.
tree_cellnasl_lint (lex_ctxt *lexic, tree_cell *st)
 Search for errors in a nasl script.

Variables

char * nasl_name
int errors_cnt
int features = 0

Macro Definition Documentation

◆ G_LOG_DOMAIN

#define G_LOG_DOMAIN   "lib nasl"

GLib logging domain.

Definition at line 27 of file lint.c.

Typedef Documentation

◆ func_info

typedef struct st_func_info func_info

Define struct to store information about a called function.

Function Documentation

◆ add_predef_varname()

void add_predef_varname ( GSList ** defined_var)
static

Add keywords to the varnames list.

Parameters
[in,out]defined_varList with all defined variables

Definition at line 81 of file lint.c.

82{
83 int i;
84 gchar *keywords[] = {"ACT_UNKNOWN", "description", "NULL", "SCRIPT_NAME",
85 "COMMAND_LINE", "_FCT_ANON_ARGS", NULL};
86
87 for (i = 0; keywords[i] != NULL; i++)
88 *defined_var = g_slist_prepend (*defined_var, keywords[i]);
89 add_nasl_library (defined_var);
90}
void add_nasl_library(GSList **list)
Add "built-in" variables to a list.
Definition nasl_init.c:583

References add_nasl_library().

Referenced by nasl_lint().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_called_files()

void check_called_files ( gpointer key,
gpointer value,
GSList ** unusedfiles )
static

This function is called by g_hash_table_foreach to check if an include file was used or not. If the file is not used, it is added to a list.

Parameters
[in]keyElement key of GHashTable.
[in]valueElement value for a key of GHashTable.
[in]unusedfilesList with unused .inc files.

Definition at line 169 of file lint.c.

170{
171 if (key != NULL)
172 // only check for includes not for main file
173 if (nasl_get_include_order ((const char *) key) > 0
174 && g_strcmp0 (value, "YES") != 0)
175 *unusedfiles = g_slist_prepend (*unusedfiles, key);
176}
int nasl_get_include_order(const char *)

References nasl_get_include_order().

Referenced by nasl_lint().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_description_block()

tree_cell * check_description_block ( lex_ctxt * lexic,
tree_cell * st )
static

Sanity check of the description block.

Returns
FAKE_CELL if success, NULL otherwise.

Definition at line 749 of file lint.c.

750{
751 int i;
752 tree_cell *ret = FAKE_CELL;
753
754 if (st->type == NODE_FUN_CALL)
755 if (!g_strcmp0 (st->x.str_val, "script_xref"))
756 if ((ret = check_description_block_xref (lexic, st)) == NULL)
757 return NULL;
758
759 for (i = 0; i < 4; i++)
760 if (st->link[i] != NULL && st->link[i] != FAKE_CELL)
761 if ((ret = check_description_block (lexic, st->link[i])) == NULL)
762 return NULL;
763
764 return ret;
765}
static tree_cell * check_description_block_xref(lex_ctxt *lexic, tree_cell *st)
Sanity check of the script_xref parameters in the description block.
Definition lint.c:718
static tree_cell * check_description_block(lex_ctxt *lexic, tree_cell *st)
Sanity check of the description block.
Definition lint.c:749
@ NODE_FUN_CALL
Definition nasl_tree.h:22
struct TC tree_cell
#define FAKE_CELL
Definition nasl_tree.h:110
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

References check_description_block(), check_description_block_xref(), FAKE_CELL, TC::link, NODE_FUN_CALL, TC::str_val, TC::type, and TC::x.

Referenced by check_description_block(), and nasl_lint().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_description_block_xref()

tree_cell * check_description_block_xref ( lex_ctxt * lexic,
tree_cell * st )
static

Sanity check of the script_xref parameters in the description block.

Definition at line 718 of file lint.c.

719{
720 int i;
721 tree_cell *ret = FAKE_CELL;
722
723 switch (st->type)
724 {
725 case CONST_STR:
726 if (g_strrstr (st->x.str_val, ", ") != NULL)
727 {
728 g_message ("%s: An error in script_xrefs function was found. "
729 "Spaces after a comma are not allow in xrefs names "
730 "or values: '%s'",
731 nasl_get_filename (st->x.str_val), st->x.str_val);
732 return NULL;
733 }
734 /* fallthrough */
735 default:
736 for (i = 0; i < 4; i++)
737 if (st->link[i] != NULL && st->link[i] != FAKE_CELL)
738 if ((ret = check_description_block_xref (lexic, st->link[i])) == NULL)
739 return NULL;
740 }
741 return ret;
742}
const char * nasl_get_filename(const char *function)
Definition nasl_debug.c:54
@ CONST_STR
Definition nasl_tree.h:80

References check_description_block_xref(), CONST_STR, FAKE_CELL, TC::link, nasl_get_filename(), TC::str_val, TC::type, and TC::x.

Referenced by check_description_block(), and check_description_block_xref().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_description_block()

tree_cell * find_description_block ( lex_ctxt * lexic,
tree_cell * st )
static

Sanity check of the description block.

Returns
pointer to the description block tree cell.

Definition at line 773 of file lint.c.

774{
775 int i;
776 tree_cell *ret = FAKE_CELL;
777 tree_cell *st_aux = NULL;
778
779 if (st && st->type == NODE_IF_ELSE)
780 {
781 for (i = 0; i < 4; i++)
782 if (st->link[i] != NULL && st->link[i] != FAKE_CELL)
783 {
784 st_aux = st->link[i];
785 if (st_aux->type == NODE_VAR
786 && !g_strcmp0 (st_aux->x.str_val, "description"))
787 return st;
788 }
789 }
790 else
791 for (i = 0; i < 4; i++)
792 {
793 if (st->link[i] != NULL && st->link[i] != FAKE_CELL)
794 if ((ret = find_description_block (lexic, st->link[i])) == NULL)
795 return NULL;
796 return ret;
797 }
798 return NULL;
799}
static tree_cell * find_description_block(lex_ctxt *lexic, tree_cell *st)
Sanity check of the description block.
Definition lint.c:773
@ NODE_VAR
Definition nasl_tree.h:31
@ NODE_IF_ELSE
Definition nasl_tree.h:14

References FAKE_CELL, find_description_block(), TC::link, NODE_IF_ELSE, NODE_VAR, TC::str_val, TC::type, and TC::x.

Referenced by find_description_block(), and nasl_lint().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_list_func()

void free_list_func ( func_info * data)
static

Free a func_info structure.

Parameters
[in]defined_varList with all defined variables

Definition at line 66 of file lint.c.

67{
68 g_free (data->func_name);
69 g_free (data->caller_func);
70 g_free (data->caller_file);
71 memset (data, '\0', sizeof (func_info));
72}
struct st_func_info func_info
Define struct to store information about a called function.
gchar * caller_file
Definition lint.c:36
gchar * func_name
Definition lint.c:34
gchar * caller_func
Definition lint.c:35

References st_func_info::caller_file, st_func_info::caller_func, and st_func_info::func_name.

Referenced by nasl_lint().

Here is the caller graph for this function:

◆ get_argument_by_name()

char * get_argument_by_name ( tree_cell * st,
char * name )
static

Checks if a given Arguments is within a given Argument List.

Parameters
stArgument List, should be of Type NODE_ARG
nameName of the Argument to search for
Returns
char* Value of the given Argument name

Definition at line 317 of file lint.c.

318{
319 if (st == NULL)
320 return NULL;
321
322 if (st->type != NODE_ARG)
323 return NULL;
324
325 tree_cell *cp;
326 for (cp = st; cp != NULL; cp = cp->link[1])
327 {
328 if (!g_strcmp0 (cp->x.str_val, name))
329 return cp->link[0]->x.str_val;
330 }
331
332 return NULL;
333}
const char * name
Definition nasl_init.c:440
@ NODE_ARG
Definition nasl_tree.h:24

References TC::link, name, NODE_ARG, TC::str_val, TC::type, and TC::x.

Referenced by validate_script_xref().

Here is the caller graph for this function:

◆ get_errors_cnt()

int get_errors_cnt ( )
static

Definition at line 54 of file lint.c.

55{
56 return errors_cnt;
57}
int errors_cnt
Definition lint.c:41

References errors_cnt.

Referenced by nasl_lint().

Here is the caller graph for this function:

◆ inc_errors_cnt()

void inc_errors_cnt ( )
static

Definition at line 48 of file lint.c.

49{
50 errors_cnt++;
51 return;
52}

References errors_cnt.

Referenced by nasl_lint(), nasl_lint_defvar(), and print_uncall_files().

Here is the caller graph for this function:

◆ init_errors_cnt()

void init_errors_cnt ( )
static

Definition at line 43 of file lint.c.

44{
45 errors_cnt = 0;
46}

References errors_cnt.

Referenced by nasl_lint().

Here is the caller graph for this function:

◆ is_deffunc_used()

int is_deffunc_used ( const char * funcname,
const char * filename,
GSList * def_func_tree )
static

Returns 1 if the function is at least used once by another caller than filename otherwise 0.

Definition at line 405 of file lint.c.

407{
408 func_info *element;
409 GSList *current = def_func_tree;
410
411 if (current == NULL)
412 return 0;
413
414 do
415 {
416 element = current->data;
417 if (g_strcmp0 (element->func_name, funcname) == 0
418 && g_strcmp0 (element->caller_file, filename) != 0)
419 return 1;
420 current = current->next;
421 }
422 while (current != NULL && current->next != NULL);
423 return 0;
424}

References st_func_info::caller_file, and st_func_info::func_name.

Referenced by nasl_lint_call().

Here is the caller graph for this function:

◆ list_cmp()

gint list_cmp ( gconstpointer lelem,
gconstpointer data )
static

This function is called by g_slist_find_custom.

Parameters
[in]lelemElement of GSList.
[in]datastr to be found in the list.
Returns
0 on success, non 0 otherwise.

Definition at line 151 of file lint.c.

152{
153 if (data)
154 return (g_strcmp0 (lelem, data));
155 return -1;
156}

Referenced by nasl_lint_call(), nasl_lint_def(), and nasl_lint_defvar().

Here is the caller graph for this function:

◆ list_cmp1()

gint list_cmp1 ( gconstpointer lelem,
gconstpointer data )
static

This function is called by g_slist_find_custom.

Parameters
[in]lelemElement of GSList.
[in]datafunc_info structure to be found.
Returns
0 on success, non 0 otherwise.

Definition at line 101 of file lint.c.

102{
103 if (data)
104 {
105 gchar *lala = g_strdup (((func_info *) lelem)->func_name);
106 return (g_strcmp0 (lala, data));
107 }
108 return -1;
109}

Referenced by nasl_lint_call(), and reverse_search().

Here is the caller graph for this function:

◆ make_call_func_list()

tree_cell * make_call_func_list ( lex_ctxt * lexic,
tree_cell * st,
GSList ** called_funcs )
static

Make a list of all called functions.

Definition at line 687 of file lint.c.

688{
689 int i;
690 tree_cell *ret = FAKE_CELL;
691 nasl_func *pf = NULL;
692
693 switch (st->type)
694 {
695 case NODE_FUN_CALL:
696 pf = get_func_ref_by_name (lexic, st->x.str_val);
697 if (st->x.str_val && !pf)
698 {
699 *called_funcs =
700 g_slist_prepend (*called_funcs, g_strdup (st->x.str_val));
701 }
702 /* fallthrough */
703
704 default:
705 for (i = 0; i < 4; i++)
706 if (st->link[i] != NULL && st->link[i] != FAKE_CELL)
707 if ((ret = make_call_func_list (lexic, st->link[i], called_funcs))
708 == NULL)
709 return NULL;
710 return ret;
711 }
712}
static tree_cell * make_call_func_list(lex_ctxt *lexic, tree_cell *st, GSList **called_funcs)
Make a list of all called functions.
Definition lint.c:687
nasl_func * get_func_ref_by_name(lex_ctxt *ctxt, const char *name)
Definition nasl_func.c:82
struct st_nasl_func nasl_func

References FAKE_CELL, get_func_ref_by_name(), TC::link, make_call_func_list(), NODE_FUN_CALL, TC::str_val, TC::type, and TC::x.

Referenced by make_call_func_list(), and nasl_lint().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ nasl_lint()

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

Search for errors in a nasl script.

Parameters
[in]lexicnasl context.
[in]ststructure tree of a nasl script.
Returns
FAKE_CELL if no error was found, otherwise NULL or tree_cell which has number of errors as x.i_val.

Definition at line 811 of file lint.c.

812{
813 lex_ctxt *lexic_aux;
814 tree_cell *ret = FAKE_CELL;
815 int lint_mode = 1;
816 GHashTable *include_files = NULL;
817 GHashTable *func_fnames_tab = NULL;
818 GSList *unusedfiles = NULL;
819 GSList *called_funcs = NULL;
820 GSList *def_func_tree = NULL;
821 gchar *err_fname = NULL;
822 tree_cell *desc_block = FAKE_CELL;
824
825 nasl_name = g_strdup (nasl_get_filename (st->x.str_val));
826 include_files =
827 g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
828 func_fnames_tab =
829 g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
830
831 lexic_aux = init_empty_lex_ctxt ();
832 lexic_aux->script_infos = lexic->script_infos;
833 lexic_aux->oid = lexic->oid;
834
835 /* Check description block sanity. */
836 desc_block = find_description_block (lexic_aux, st);
837 if (desc_block != NULL && desc_block != FAKE_CELL)
838 {
839 /* FAKE_CELL if success, NULL otherwise which counts as error */
840 if (check_description_block (lexic_aux, desc_block) == NULL)
841 {
843 }
844 }
845 /* Make a list of all called functions */
846 make_call_func_list (lexic_aux, st, &called_funcs);
847
848 /* Loads all defined functions. */
849 if (nasl_lint_def (lexic_aux, st, lint_mode, &include_files, &func_fnames_tab,
850 err_fname, &called_funcs, &def_func_tree)
851 == NULL)
852 {
854 }
855 /* Check if a called function was defined. */
856
857 if (nasl_lint_call (lexic_aux, st, &include_files, &func_fnames_tab,
858 err_fname, &called_funcs, &def_func_tree)
859 == NULL)
860 {
862 }
863
864 /* Check if the included files are used or not. */
865 g_hash_table_foreach (include_files, (GHFunc) check_called_files,
866 &unusedfiles);
867 if (unusedfiles != NULL)
868 g_slist_foreach (unusedfiles, (GFunc) print_uncall_files, lexic_aux);
869 if ((g_slist_length (unusedfiles)) > 0)
870 {
872 }
873
874 /* Now check that each function was loaded just once. */
875 lint_mode = 0;
876 if (nasl_lint_def (lexic, st, lint_mode, &include_files, &func_fnames_tab,
877 err_fname, &called_funcs, &def_func_tree)
878 == NULL)
879 {
881 }
882
883 /* Check if a variable was declared. */
884 GSList *defined_var = NULL;
885 add_predef_varname (&defined_var);
886 ret = nasl_lint_defvar (lexic_aux, st, &include_files, &func_fnames_tab,
887 err_fname, &defined_var, &called_funcs);
888 g_slist_free (defined_var);
889 defined_var = NULL;
890
891 g_slist_free (called_funcs);
892 called_funcs = NULL;
893 g_slist_free_full (def_func_tree, (GDestroyNotify) free_list_func);
894 def_func_tree = NULL;
895 g_hash_table_destroy (include_files);
896 include_files = NULL;
897 g_hash_table_destroy (func_fnames_tab);
898 func_fnames_tab = NULL;
899 g_free (err_fname);
900 g_slist_free (unusedfiles);
901 unusedfiles = NULL;
902 free_lex_ctxt (lexic_aux);
903
904 if (get_errors_cnt () > 0)
905 {
907 ret->x.i_val = get_errors_cnt ();
908 }
909
910 return ret;
911}
static tree_cell * nasl_lint_def(lex_ctxt *lexic, tree_cell *st, int lint_mode, GHashTable **include_files, GHashTable **func_fnames_tab, gchar *err_fname, GSList **called_funcs, GSList **def_func_tree)
Loads all defined functions. Also, It constructs a tree of called functions to help recognize a not d...
Definition lint.c:203
static void inc_errors_cnt()
Definition lint.c:48
static void init_errors_cnt()
Definition lint.c:43
static int get_errors_cnt()
Definition lint.c:54
static void print_uncall_files(gpointer filename, gpointer lexic)
It shows a msg for unused included files.
Definition lint.c:186
static void free_list_func(func_info *data)
Free a func_info structure.
Definition lint.c:66
char * nasl_name
Definition lint.c:39
static void add_predef_varname(GSList **defined_var)
Add keywords to the varnames list.
Definition lint.c:81
static tree_cell * nasl_lint_call(lex_ctxt *lexic, tree_cell *st, GHashTable **include_files, GHashTable **func_fnames_tab, gchar *err_fname, GSList **called_funcs, GSList **def_func_tree)
Check if a called function was defined.
Definition lint.c:438
static void check_called_files(gpointer key, gpointer value, GSList **unusedfiles)
This function is called by g_hash_table_foreach to check if an include file was used or not....
Definition lint.c:169
static tree_cell * nasl_lint_defvar(lex_ctxt *lexic, tree_cell *st, GHashTable **include_files, GHashTable **func_fnames_tab, gchar *err_fname, GSList **defined_var, GSList **called_funcs)
Consider all cases in which a variable is set, and add it to a list. If a variable is read,...
Definition lint.c:557
void free_lex_ctxt(lex_ctxt *c)
lex_ctxt * init_empty_lex_ctxt()
struct struct_lex_ctxt lex_ctxt
tree_cell * alloc_typed_cell(int typ)
Definition nasl_tree.c:25
long int i_val
Definition nasl_tree.h:104
struct script_infos * script_infos
const char * oid

References add_predef_varname(), alloc_typed_cell(), check_called_files(), check_description_block(), FAKE_CELL, find_description_block(), free_lex_ctxt(), free_list_func(), get_errors_cnt(), TC::i_val, inc_errors_cnt(), init_empty_lex_ctxt(), init_errors_cnt(), make_call_func_list(), nasl_get_filename(), nasl_lint_call(), nasl_lint_def(), nasl_lint_defvar(), nasl_name, NODE_VAR, struct_lex_ctxt::oid, print_uncall_files(), struct_lex_ctxt::script_infos, TC::str_val, and TC::x.

Referenced by exec_nasl_script().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ nasl_lint_call()

tree_cell * nasl_lint_call ( lex_ctxt * lexic,
tree_cell * st,
GHashTable ** include_files,
GHashTable ** func_fnames_tab,
gchar * err_fname,
GSList ** called_funcs,
GSList ** def_func_tree )
static

Check if a called function was defined.

This checks if a defined function is called. If it is never called it does not go deeper.

Definition at line 438 of file lint.c.

441{
442 int i;
443 tree_cell *ret = FAKE_CELL;
444 nasl_func *pf;
445 char *incname = NULL;
446 int f_inc_ord, c_inc_order, rc = 0;
447 static int defined_flag = 0;
448
452 if (st->type == NODE_FUN_DEF)
453 {
454 if (!g_slist_find_custom (*called_funcs, st->x.str_val,
455 (GCompareFunc) list_cmp))
456 {
457 return FAKE_CELL;
458 }
459 }
460
461 switch (st->type)
462 {
463 case CONST_DATA:
464 case CONST_STR:
465 if (st->x.str_val != NULL && defined_flag == 1)
466 {
467 decl_nasl_func (lexic, st, 1);
468 defined_flag = 0;
469 }
470 return FAKE_CELL;
471
472 case NODE_FUN_CALL:
473 pf = get_func_ref_by_name (lexic, st->x.str_val);
474
475 if (pf == NULL)
476 {
477 incname = g_hash_table_lookup (*func_fnames_tab, st->x.str_val);
478
479 nasl_set_filename (incname ? incname : "unknown");
480 lexic->line_nb = st->line_nb;
481
482 GSList *called_f_aux;
483 called_f_aux = g_slist_find_custom (*def_func_tree, st->x.str_val,
484 (GCompareFunc) list_cmp1);
485 if (called_f_aux != NULL)
486 {
487 if (reverse_search (def_func_tree, called_f_aux))
488 {
489 nasl_perror (lexic, "Undefined function '%s'\n",
490 st->x.str_val);
491 return NULL;
492 }
493 }
494 }
495 else
496 {
497 // only check functions that are not internal
499 && func_is_internal (st->x.str_val) == NULL)
500 {
501 // get incname verify include order when not 0
502 incname = (char *) nasl_get_filename (st->x.str_val);
503 if (incname != NULL)
504 {
505 f_inc_ord = nasl_get_include_order (incname);
506 c_inc_order = nasl_get_include_order (st->name);
507 // if caller definition is not the main file but included
508 // before the function definition warn about an include error
509 if (c_inc_order > 0 && c_inc_order < f_inc_ord)
510 {
512 lexic, "%s must be included after %s (usage of %s).",
513 st->name, incname, st->x.str_val);
514 rc = -1;
515 }
516 }
517 }
518 // Check if function parameters are right
519 if (validate_function (lexic, st) == NULL)
520 return NULL;
521 }
522 if (*include_files && st->x.str_val)
523 {
524 if (g_hash_table_lookup (*include_files,
526 {
527 incname = g_strdup (nasl_get_filename (st->x.str_val));
528 if (is_deffunc_used (st->x.str_val, incname, *def_func_tree))
529 {
530 g_hash_table_replace (*include_files, incname,
531 g_strdup ("YES"));
532 }
533 }
534 }
535 if (g_strcmp0 (st->x.str_val, "defined_func") == 0)
536 defined_flag = 1;
537 /* fallthrough */
538
539 default:
540 for (i = 0; i < 4; i++)
541 if (st->link[i] != NULL && st->link[i] != FAKE_CELL)
542 if ((ret = nasl_lint_call (lexic, st->link[i], include_files,
543 func_fnames_tab, err_fname, called_funcs,
544 def_func_tree))
545 == NULL)
546 return NULL;
547 return rc == 0 ? ret : NULL;
548 }
549}
static gint reverse_search(GSList **def_func_tree, GSList *finfo)
Check if an undefined called function is needed or not. This is the case in which the function is cal...
Definition lint.c:118
static tree_cell * validate_function(lex_ctxt *lexic, tree_cell *st)
Validate functions.
Definition lint.c:386
static gint list_cmp(gconstpointer lelem, gconstpointer data)
This function is called by g_slist_find_custom.
Definition lint.c:151
static int is_deffunc_used(const char *funcname, const char *filename, GSList *def_func_tree)
Returns 1 if the function is at least used once by another caller than filename otherwise 0.
Definition lint.c:405
int features
Definition lint.c:426
static gint list_cmp1(gconstpointer lelem, gconstpointer data)
This function is called by g_slist_find_custom.
Definition lint.c:101
@ NLFF_STRICT_INCLUDES
Definition lint.h:16
void nasl_set_filename(const char *filename)
Definition nasl_debug.c:82
void nasl_perror(lex_ctxt *lexic, char *msg,...)
Definition nasl_debug.c:105
tree_cell * decl_nasl_func(lex_ctxt *lexic, tree_cell *decl_node, int lint_mode)
Definition nasl_func.c:66
nasl_func * func_is_internal(const char *)
Definition nasl_init.c:555
@ CONST_DATA
Definition nasl_tree.h:82
@ NODE_FUN_DEF
Definition nasl_tree.h:21
char * name
Definition nasl_tree.h:97
short line_nb
Definition nasl_tree.h:96

References CONST_DATA, CONST_STR, decl_nasl_func(), FAKE_CELL, features, func_is_internal(), get_func_ref_by_name(), is_deffunc_used(), struct_lex_ctxt::line_nb, TC::line_nb, TC::link, list_cmp(), list_cmp1(), TC::name, nasl_get_filename(), nasl_get_include_order(), nasl_lint_call(), nasl_perror(), nasl_set_filename(), NLFF_STRICT_INCLUDES, NODE_FUN_CALL, NODE_FUN_DEF, reverse_search(), TC::str_val, TC::type, validate_function(), and TC::x.

Referenced by nasl_lint(), and nasl_lint_call().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ nasl_lint_def()

tree_cell * nasl_lint_def ( lex_ctxt * lexic,
tree_cell * st,
int lint_mode,
GHashTable ** include_files,
GHashTable ** func_fnames_tab,
gchar * err_fname,
GSList ** called_funcs,
GSList ** def_func_tree )
static

Loads all defined functions. Also, It constructs a tree of called functions to help recognize a not defined function which is never called (nested functions).

Definition at line 203 of file lint.c.

206{
207 int i;
208 tree_cell *ret = FAKE_CELL;
209 char *incname = NULL;
210 gchar *tmp_filename = NULL;
211 nasl_func *pf;
212 static gchar *current_fun_def = NULL;
213
214 if (st->type == NODE_FUN_CALL)
215 {
216 pf = get_func_ref_by_name (lexic, st->x.str_val);
217 if (pf == NULL)
218 {
219 g_hash_table_insert (*func_fnames_tab, g_strdup (st->x.str_val),
220 g_strdup (err_fname));
221 }
222
223 /* Save in a list the name of the called function, the file where it
224 is called from, and the function where it is called from. This will
225 help to know if a called function is really needed, or it was just
226 called by another defined function which is never called. */
227 func_info *finfo = g_malloc0 (sizeof (func_info));
228 finfo->func_name = g_strdup (st->x.str_val);
229 finfo->caller_file = g_strdup (err_fname ? err_fname : nasl_name);
230 finfo->caller_func = g_strdup (current_fun_def);
231 *def_func_tree = g_slist_prepend (*def_func_tree, finfo);
232 /* Check if function parameters are used multiple times. Only check
233 * this if we are in lint mode 1 to not check it multiple times. */
234 if (lint_mode == 1)
235 {
236 GSList *func_params = NULL;
237 int linenum = st->line_nb;
238 tree_cell *args = st->link[0];
239 for (; args != NULL; args = args->link[1])
240 {
241 if (args->x.str_val)
242 {
243 /* Check if param was already used */
244 if (!g_slist_find_custom (func_params, args->x.str_val,
245 (GCompareFunc) list_cmp))
246 func_params =
247 g_slist_prepend (func_params, args->x.str_val);
248 else
249 {
250 g_message ("%s: Error at or near line %d. "
251 "Parameter \"%s\" passed to function \"%s\" "
252 "was provided multiple times.",
253 finfo->caller_file, linenum, args->x.str_val,
254 finfo->func_name);
255 g_slist_free (func_params);
256 return NULL;
257 }
258 }
259 }
260 g_slist_free (func_params);
261 }
262 }
263
264 switch (st->type)
265 {
266 case NODE_FUN_DEF:
267 /* with lint_mode = 0 check if this function was declared twice*/
268 if (lint_mode == 0)
269 {
270 if (decl_nasl_func (lexic, st, lint_mode) == NULL)
271 ret = NULL;
272 return ret;
273 }
274 /* Check if it was already added */
275 if (!g_slist_find_custom (*called_funcs, st->x.str_val,
276 (GCompareFunc) list_cmp))
277 {
278 return FAKE_CELL;
279 }
280
281 /* x.str_val = function name, [0] = argdecl, [1] = block */
282 decl_nasl_func (lexic, st, lint_mode);
283 current_fun_def = g_strdup (st->x.str_val);
284 incname = g_strdup (nasl_get_filename (st->x.str_val));
285 g_hash_table_replace (*include_files, incname, g_strdup ("NO"));
286 tmp_filename = g_strdup (nasl_get_filename (NULL));
287 err_fname = g_strdup (incname);
288 /* fallthrough */
289
290 default:
291 for (i = 0; i < 4; i++)
292 if (st->link[i] != NULL && st->link[i] != FAKE_CELL)
293 if ((ret = nasl_lint_def (lexic, st->link[i], lint_mode,
294 include_files, func_fnames_tab, err_fname,
295 called_funcs, def_func_tree))
296 == NULL)
297 return NULL;
298
299 if (st->type == NODE_FUN_DEF)
300 {
301 if (tmp_filename)
302 nasl_set_filename (tmp_filename);
303 g_free (tmp_filename);
304 }
305 return ret;
306 }
307}

References st_func_info::caller_file, st_func_info::caller_func, decl_nasl_func(), FAKE_CELL, st_func_info::func_name, get_func_ref_by_name(), TC::line_nb, TC::link, list_cmp(), nasl_get_filename(), nasl_lint_def(), nasl_name, nasl_set_filename(), NODE_FUN_CALL, NODE_FUN_DEF, TC::str_val, TC::type, and TC::x.

Referenced by nasl_lint(), and nasl_lint_def().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ nasl_lint_defvar()

tree_cell * nasl_lint_defvar ( lex_ctxt * lexic,
tree_cell * st,
GHashTable ** include_files,
GHashTable ** func_fnames_tab,
gchar * err_fname,
GSList ** defined_var,
GSList ** called_funcs )
static

Consider all cases in which a variable is set, and add it to a list. If a variable is read, it checks if it was previously added to the list.

This checks if a defined function is called. If it is never called it does not go deeper.

It is a local variable and it is added in special list, which will be cleaned at the end of the function.

Leaving the function definition, the local variables list is cleaned.

Definition at line 557 of file lint.c.

560{
561 int i;
562 tree_cell *ret = FAKE_CELL;
563 static int defined_fn_mode = 0;
564 static int defined_var_mode = 0;
565 static int def_glob_var = 0;
566 static GSList *local_var_list = NULL;
567
571 if (st->type == NODE_FUN_DEF)
572 {
573 if (!g_slist_find_custom (*called_funcs, st->x.str_val,
574 (GCompareFunc) list_cmp))
575 {
576 return FAKE_CELL;
577 }
578 }
579
580 if ((defined_fn_mode == 1 || def_glob_var) && st->type != NODE_DECL)
581 {
582 defined_fn_mode = 0;
583 def_glob_var = 0;
584 }
585
586 /* A variable will be defined, then set the mode variable. */
587 if ((st->type == NODE_AFF || st->type == EXPR_NOT || st->type == EXPR_INCR
588 || st->type == NODE_PLUS_EQ)
589 && defined_var_mode == 0)
590 defined_var_mode = 1;
591 else if ((st->type == NODE_FUN_DEF || st->type == NODE_LOCAL
592 || st->type == NODE_FUN_CALL)
593 && defined_fn_mode == 0)
594 {
595 defined_fn_mode = 1;
596 defined_var_mode = 0;
597 }
598
599 else if (st->type == NODE_GLOBAL)
600 def_glob_var = 1;
601
602 /* The variable is being defined. Therefore is save into the
603 * global list only if was not previously added in local list.
604 */
605 else if ((st->type == NODE_VAR || st->type == NODE_ARRAY_EL)
606 && (defined_var_mode == 1 || defined_fn_mode == 1))
607 {
608 if (st->x.str_val != NULL)
609 {
610 if (!g_slist_find_custom (local_var_list, st->x.str_val,
611 (GCompareFunc) list_cmp))
612 *defined_var = g_slist_prepend (*defined_var, st->x.str_val);
613 defined_var_mode = 0;
614 }
615 }
619 else if (st->type == NODE_DECL && st->x.str_val != NULL)
620 {
621 if (defined_fn_mode == 1)
622 {
623 local_var_list = g_slist_prepend (local_var_list, st->x.str_val);
624 }
625 if (def_glob_var == 1)
626 {
627 *defined_var = g_slist_prepend (*defined_var, st->x.str_val);
628 }
629 }
630 /* Special case foreach. */
631 else if (st->type == NODE_FOREACH)
632 {
633 // Hacky way of checking if we are in a function definition by checking
634 // if local_var_list is non empty. Otherwise all variables declared in a
635 // foreach call are considered file scope which leads to false negatives.
636 if (st->x.str_val != NULL && local_var_list != NULL)
637 {
638 local_var_list = g_slist_prepend (local_var_list, st->x.str_val);
639 }
640 else if (st->x.str_val != NULL)
641 {
642 *defined_var = g_slist_prepend (*defined_var, st->x.str_val);
643 }
644 }
645
646 // The variable is used. It checks if the variable was defined
647 // Also check for NODE_ARRAY_EL to catch use of undeclared array.
648 // E.g "if(foo[0]) {}" and foo was not declared previously.
649 else if ((st->type == NODE_VAR || st->type == NODE_ARRAY_EL)
650 && defined_var_mode == 0)
651 {
652 if (!g_slist_find_custom (*defined_var, st->x.str_val,
653 (GCompareFunc) list_cmp)
654 && !g_slist_find_custom (local_var_list, st->x.str_val,
655 (GCompareFunc) list_cmp))
656 {
657 lexic->line_nb = st->line_nb;
658 nasl_perror (lexic, "The variable %s was not declared",
659 st->x.str_val);
661 }
662 }
663
664 for (i = 0; i < 4; i++)
665 if (st->link[i] != NULL && st->link[i] != FAKE_CELL)
666 if ((ret = nasl_lint_defvar (lexic, st->link[i], include_files,
667 func_fnames_tab, err_fname, defined_var,
668 called_funcs))
669 == NULL)
670 return NULL;
671
675 if (st->type == NODE_FUN_DEF)
676 {
677 g_slist_free (local_var_list);
678 local_var_list = NULL;
679 }
680
681 return ret;
682}
@ NODE_ARRAY_EL
Definition nasl_tree.h:29
@ NODE_PLUS_EQ
Definition nasl_tree.h:35
@ NODE_LOCAL
Definition nasl_tree.h:32
@ NODE_AFF
Definition nasl_tree.h:30
@ NODE_FOREACH
Definition nasl_tree.h:18
@ EXPR_NOT
Definition nasl_tree.h:47
@ NODE_DECL
Definition nasl_tree.h:23
@ EXPR_INCR
Definition nasl_tree.h:61
@ NODE_GLOBAL
Definition nasl_tree.h:33

References EXPR_INCR, EXPR_NOT, FAKE_CELL, inc_errors_cnt(), struct_lex_ctxt::line_nb, TC::line_nb, TC::link, list_cmp(), nasl_lint_defvar(), nasl_perror(), NODE_AFF, NODE_ARRAY_EL, NODE_DECL, NODE_FOREACH, NODE_FUN_CALL, NODE_FUN_DEF, NODE_GLOBAL, NODE_LOCAL, NODE_PLUS_EQ, NODE_VAR, TC::str_val, TC::type, and TC::x.

Referenced by nasl_lint(), and nasl_lint_defvar().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ nasl_lint_feature_flags()

void nasl_lint_feature_flags ( int flag)

Definition at line 429 of file lint.c.

430{
431 features = flag;
432}

References features.

◆ print_uncall_files()

void print_uncall_files ( gpointer filename,
gpointer lexic )
static

It shows a msg for unused included files.

Parameters
[in]filenameFilename of the not used inc file.
[in]lexicnasl context.

Definition at line 186 of file lint.c.

187{
188 if (filename != NULL)
189 {
190 nasl_perror (lexic, "The included file '%s' is never used.",
191 (char *) filename);
193 lexic = NULL;
194 }
195}

References inc_errors_cnt(), and nasl_perror().

Referenced by nasl_lint().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ reverse_search()

gint reverse_search ( GSList ** def_func_tree,
GSList * finfo )
static

Check if an undefined called function is needed or not. This is the case in which the function is called from a nested and defined function but never called.

Returns
1 if the function is needed, 0 otherwise.

Definition at line 118 of file lint.c.

119{
120 func_info *fdata = finfo->data;
121 GSList *finfo_aux;
122
123 // The file name is the original file to be tested. It is not an include.
124 if (!g_strcmp0 (fdata->caller_file, nasl_name)
125 && !g_str_has_suffix (nasl_name, ".inc"))
126 return 1;
127
128 // The function is it self.
129 if (!g_strcmp0 (fdata->func_name, fdata->caller_func))
130 return 0;
131
132 // I go up in the tree of called and defined functions.
133 if ((finfo_aux = g_slist_find_custom (*def_func_tree, fdata->caller_func,
134 (GCompareFunc) list_cmp1))
135 != NULL)
136 if (reverse_search (def_func_tree, finfo_aux))
137 return 1;
138
139 return 0;
140}

References st_func_info::caller_file, st_func_info::caller_func, st_func_info::func_name, list_cmp1(), nasl_name, and reverse_search().

Referenced by nasl_lint_call(), and reverse_search().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ validate_function()

tree_cell * validate_function ( lex_ctxt * lexic,
tree_cell * st )
static

Validate functions.

Parameters
lexic
st
Returns
tree_cell * NULL if it is invalid, FAKE_CELL if it is valid

Definition at line 386 of file lint.c.

387{
388 lexic->line_nb = st->line_nb;
389 if (st != NULL)
390 {
391 if (!g_strcmp0 (st->x.str_val, "script_xref"))
392 return validate_script_xref (lexic, st->link[0]);
393 }
394 else
395 return NULL;
396
397 return FAKE_CELL;
398}
static tree_cell * validate_script_xref(lex_ctxt *lexic, tree_cell *st)
Validates parameters of a script_xref function call.
Definition lint.c:343

References FAKE_CELL, struct_lex_ctxt::line_nb, TC::line_nb, TC::link, TC::str_val, validate_script_xref(), and TC::x.

Referenced by nasl_lint_call().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ validate_script_xref()

tree_cell * validate_script_xref ( lex_ctxt * lexic,
tree_cell * st )
static

Validates parameters of a script_xref function call.

Parameters
lexic
stFunction Parameters should be of type NODE_ARG
Returns
tree_cell*

Definition at line 343 of file lint.c.

344{
345 char *name = get_argument_by_name (st, "name");
346 char *value = get_argument_by_name (st, "value");
347 char *csv = get_argument_by_name (st, "csv");
348
349 if (((value == NULL) && (csv == NULL)) || name == NULL)
350 {
351 nasl_perror (lexic,
352 "script_xref() syntax error - should be"
353 " script_xref(name:<name>, value:<value>) or"
354 " script_xref(name:<name>, value:<value>, csv:<CSVs>) or"
355 " script_xref(name:<name>, csv:<CSVs>)\n");
356 if (name == NULL)
357 {
358 nasl_perror (lexic, " <name> is empty\n");
359 }
360 else
361 {
362 nasl_perror (lexic, " <name> is %s\n", name);
363 }
364 if ((value == NULL) && (csv == NULL))
365 {
366 nasl_perror (lexic, " <value> and <csv> is empty)\n");
367 }
368 else
369 {
370 nasl_perror (lexic, " <value> is %s\n)", value);
371 nasl_perror (lexic, " <csv> is %s\n)", csv);
372 }
373 return NULL;
374 }
375 return FAKE_CELL;
376}
static char * get_argument_by_name(tree_cell *st, char *name)
Checks if a given Arguments is within a given Argument List.
Definition lint.c:317

References FAKE_CELL, get_argument_by_name(), name, and nasl_perror().

Referenced by validate_function().

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ errors_cnt

int errors_cnt

Definition at line 41 of file lint.c.

Referenced by get_errors_cnt(), inc_errors_cnt(), and init_errors_cnt().

◆ features

int features = 0

Definition at line 426 of file lint.c.

Referenced by nasl_lint_call(), and nasl_lint_feature_flags().

◆ nasl_name

char* nasl_name

Definition at line 39 of file lint.c.

Referenced by nasl_lint(), nasl_lint_def(), and reverse_search().