OpenVAS Scanner  22.7.9
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. More...
 

Typedefs

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

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. More...
 
static void add_predef_varname (GSList **defined_var)
 Add keywords to the varnames list. More...
 
static gint list_cmp1 (gconstpointer lelem, gconstpointer data)
 This function is called by g_slist_find_custom. More...
 
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. More...
 
static gint list_cmp (gconstpointer lelem, gconstpointer data)
 This function is called by g_slist_find_custom. More...
 
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. More...
 
static void print_uncall_files (gpointer filename, gpointer lexic)
 It shows a msg for unused included files. More...
 
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). More...
 
static char * get_argument_by_name (tree_cell *st, char *name)
 Checks if a given Arguments is within a given Argument List. More...
 
static tree_cellvalidate_script_xref (lex_ctxt *lexic, tree_cell *st)
 Validates parameters of a script_xref function call. More...
 
static tree_cellvalidate_function (lex_ctxt *lexic, tree_cell *st)
 Validate functions. More...
 
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. More...
 
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. More...
 
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. More...
 
static tree_cellmake_call_func_list (lex_ctxt *lexic, tree_cell *st, GSList **called_funcs)
 Make a list of all called functions. More...
 
static tree_cellcheck_description_block_xref (lex_ctxt *lexic, tree_cell *st)
 Sanity check of the script_xref parameters in the description block. More...
 
static tree_cellcheck_description_block (lex_ctxt *lexic, tree_cell *st)
 Sanity check of the description block. More...
 
static tree_cellfind_description_block (lex_ctxt *lexic, tree_cell *st)
 Sanity check of the description block. More...
 
tree_cellnasl_lint (lex_ctxt *lexic, tree_cell *st)
 Search for errors in a nasl script. More...
 

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()

static 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 }

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()

static 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 }

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()

static 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 }

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

Referenced by nasl_lint().

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

◆ check_description_block_xref()

static 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 }

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

Referenced by check_description_block().

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

◆ find_description_block()

static 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 }

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

Referenced by nasl_lint().

Here is the caller graph for this function:

◆ free_list_func()

static 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 }

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()

static 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 }

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()

static int get_errors_cnt ( )
static

Definition at line 54 of file lint.c.

55 {
56  return errors_cnt;
57 }

References errors_cnt.

Referenced by nasl_lint().

Here is the caller graph for this function:

◆ inc_errors_cnt()

static 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()

static 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()

static 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()

static 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()

static 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()

static 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 }

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

Referenced by 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;
823  init_errors_cnt ();
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  {
842  inc_errors_cnt ();
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  {
853  inc_errors_cnt ();
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  {
861  inc_errors_cnt ();
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  {
871  inc_errors_cnt ();
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  {
880  inc_errors_cnt ();
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  {
906  ret = alloc_typed_cell (NODE_VAR);
907  ret->x.i_val = get_errors_cnt ();
908  }
909 
910  return ret;
911 }

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()

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 
)
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  {
511  nasl_perror (
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,
525  nasl_get_filename (st->x.str_val)))
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 }

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_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().

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

◆ nasl_lint_def()

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 
)
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_name, nasl_set_filename(), NODE_FUN_CALL, NODE_FUN_DEF, TC::str_val, TC::type, and TC::x.

Referenced by nasl_lint().

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

◆ nasl_lint_defvar()

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 
)
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);
660  inc_errors_cnt ();
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 }

References EXPR_INCR, EXPR_NOT, FAKE_CELL, inc_errors_cnt(), struct_lex_ctxt::line_nb, TC::line_nb, TC::link, list_cmp(), 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().

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()

static 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);
192  inc_errors_cnt ();
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()

static 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(), and nasl_name.

Referenced by nasl_lint_call().

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

◆ validate_function()

static 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 }

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()

static 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 }

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().

NODE_LOCAL
@ NODE_LOCAL
Definition: nasl_tree.h:32
get_func_ref_by_name
nasl_func * get_func_ref_by_name(lex_ctxt *ctxt, const char *name)
Definition: nasl_func.c:82
get_argument_by_name
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
CONST_DATA
@ CONST_DATA
Definition: nasl_tree.h:82
struct_lex_ctxt::line_nb
int line_nb
Definition: nasl_lex_ctxt.h:33
free_list_func
static void free_list_func(func_info *data)
Free a func_info structure.
Definition: lint.c:66
reverse_search
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
NODE_DECL
@ NODE_DECL
Definition: nasl_tree.h:23
TC::str_val
char * str_val
Definition: nasl_tree.h:103
NODE_GLOBAL
@ NODE_GLOBAL
Definition: nasl_tree.h:33
TC::name
char * name
Definition: nasl_tree.h:97
NODE_AFF
@ NODE_AFF
Definition: nasl_tree.h:30
CONST_STR
@ CONST_STR
Definition: nasl_tree.h:80
st_func_info::caller_func
gchar * caller_func
Definition: lint.c:35
NODE_ARRAY_EL
@ NODE_ARRAY_EL
Definition: nasl_tree.h:29
TC::x
union TC::@5 x
st_nasl_func
Definition: nasl_func.h:15
FAKE_CELL
#define FAKE_CELL
Definition: nasl_tree.h:110
st_func_info::caller_file
gchar * caller_file
Definition: lint.c:36
nasl_lint_def
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
NODE_FUN_DEF
@ NODE_FUN_DEF
Definition: nasl_tree.h:21
make_call_func_list
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
name
const char * name
Definition: nasl_init.c:411
nasl_get_include_order
int nasl_get_include_order(const char *)
Definition: nasl_grammar.tab.c:2815
add_predef_varname
static void add_predef_varname(GSList **defined_var)
Add keywords to the varnames list.
Definition: lint.c:81
validate_script_xref
static tree_cell * validate_script_xref(lex_ctxt *lexic, tree_cell *st)
Validates parameters of a script_xref function call.
Definition: lint.c:343
NODE_FUN_CALL
@ NODE_FUN_CALL
Definition: nasl_tree.h:22
NODE_FOREACH
@ NODE_FOREACH
Definition: nasl_tree.h:18
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
init_errors_cnt
static void init_errors_cnt()
Definition: lint.c:43
NODE_VAR
@ NODE_VAR
Definition: nasl_tree.h:31
func_is_internal
nasl_func * func_is_internal(const char *)
Definition: nasl_init.c:526
print_uncall_files
static void print_uncall_files(gpointer filename, gpointer lexic)
It shows a msg for unused included files.
Definition: lint.c:186
st_func_info
Define struct to store information about a called function.
Definition: lint.c:33
TC::line_nb
short line_nb
Definition: nasl_tree.h:96
get_errors_cnt
static int get_errors_cnt()
Definition: lint.c:54
EXPR_NOT
@ EXPR_NOT
Definition: nasl_tree.h:47
struct_lex_ctxt::oid
const char * oid
Definition: nasl_lex_ctxt.h:31
check_description_block_xref
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
free_lex_ctxt
void free_lex_ctxt(lex_ctxt *c)
Definition: nasl_lex_ctxt.c:43
add_nasl_library
void add_nasl_library(GSList **list)
Add "built-in" variables to a list.
Definition: nasl_init.c:554
is_deffunc_used
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
struct_lex_ctxt::script_infos
struct script_infos * script_infos
Definition: nasl_lex_ctxt.h:30
NLFF_STRICT_INCLUDES
@ NLFF_STRICT_INCLUDES
Definition: lint.h:16
list_cmp1
static gint list_cmp1(gconstpointer lelem, gconstpointer data)
This function is called by g_slist_find_custom.
Definition: lint.c:101
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
find_description_block
static tree_cell * find_description_block(lex_ctxt *lexic, tree_cell *st)
Sanity check of the description block.
Definition: lint.c:773
errors_cnt
int errors_cnt
Definition: lint.c:41
st_func_info::func_name
gchar * func_name
Definition: lint.c:34
EXPR_INCR
@ EXPR_INCR
Definition: nasl_tree.h:61
NODE_IF_ELSE
@ NODE_IF_ELSE
Definition: nasl_tree.h:14
inc_errors_cnt
static void inc_errors_cnt()
Definition: lint.c:48
nasl_lint_call
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
validate_function
static tree_cell * validate_function(lex_ctxt *lexic, tree_cell *st)
Validate functions.
Definition: lint.c:386
nasl_get_filename
const char * nasl_get_filename(const char *function)
Definition: nasl_debug.c:60
nasl_set_filename
void nasl_set_filename(const char *filename)
Definition: nasl_debug.c:88
features
int features
Definition: lint.c:426
NODE_PLUS_EQ
@ NODE_PLUS_EQ
Definition: nasl_tree.h:35
list_cmp
static gint list_cmp(gconstpointer lelem, gconstpointer data)
This function is called by g_slist_find_custom.
Definition: lint.c:151
alloc_typed_cell
tree_cell * alloc_typed_cell(int typ)
Definition: nasl_tree.c:28
check_called_files
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
nasl_lint_defvar
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
init_empty_lex_ctxt
lex_ctxt * init_empty_lex_ctxt()
Definition: nasl_lex_ctxt.c:20
NODE_ARG
@ NODE_ARG
Definition: nasl_tree.h:24
check_description_block
static tree_cell * check_description_block(lex_ctxt *lexic, tree_cell *st)
Sanity check of the description block.
Definition: lint.c:749
nasl_name
char * nasl_name
Definition: lint.c:39
TC::i_val
long int i_val
Definition: nasl_tree.h:104