static tree_cell*
affect_to_anon_var(anon_nasl_var* v1, tree_cell* rval)
{
  anon_nasl_var	*v2 = NULL, v0;
  nasl_array	*a = NULL;
  int		t1, t2;
  void		*p;


  t1 = v1->var_type;

  if (rval == NULL || rval == FAKE_CELL)
    {
#if NASL_DEBUG > 1
      nasl_perror(NULL, "nasl_affect: affecting NULL or FAKE cell undefines variable %s %s\n", get_var_name(v1), get_line_nb(rval));
#endif
      clear_anon_var(v1);
      if(nasl_trace_enabled())nasl_trace(NULL, "NASL> %s <- undef\n", get_var_name(v1));
      return NULL;
    }

  switch (rval->type)
    {
    case CONST_INT:
      t2 = VAR2_INT;
      break;
    case CONST_STR:
      t2 = VAR2_STRING;
      break;
    case CONST_DATA:
      t2 = VAR2_DATA;
      break;

    case REF_VAR:
      v2 = rval->x.ref_val;
      if (v2 == v1)
	{
#if NASL_DEBUG > 1
	  nasl_perror(NULL, "Copying variable %s to itself is useless and dangerous!\n", get_var_name(v1));
#endif
	  return FAKE_CELL;
	}
      t2 = v2->var_type;
      if (t2 == VAR2_ARRAY)
	a = &v2->v.v_arr;	/* ? */
      break;

    case REF_ARRAY:
    case DYN_ARRAY:
      a = rval->x.ref_val;
      t2 = VAR2_ARRAY;
      if (v1->var_type == VAR2_ARRAY && &v1->v.v_arr == a)
	{
#if NASL_DEBUG > 1
	  nasl_perror(NULL, "Copying array %s to itself is useless and dangerous!\n", get_var_name(v1));
#endif
	  return FAKE_CELL;
	}
      break;

    default:
      nasl_perror(NULL, "Cannot affect rvalue 0x%x to variable\n", rval->type);
      return NULL;
    }

  /*
   * Bug #146: when executing 
   *    x = 'abc'; x = x;  or   x = make_list(...); x = x[0];
   * the rvalue will be freed before it is copied to the lvalue
   */
  v0 = *v1;

  if (t1 != VAR2_UNDEF && t2 == VAR2_UNDEF)
    {
#if NASL_DEBUG > 0
      nasl_perror(NULL, "Warning: Undefining defined variable %s %s\n",
		  get_var_name(v1), get_line_nb(rval));
#endif
    }
  else if (t1 == VAR2_ARRAY && t2 != VAR2_ARRAY)
    {
#if NASL_DEBUG > 1
      nasl_perror(NULL, 
		  "Warning: affecting non array (0x%x) to array variable %s\n",
		  t2, get_line_nb(rval));
#endif
    }
  else if ((t1 == VAR2_INT || t1 == VAR2_STRING || t1 == VAR2_DATA) &&
	   t2 == VAR2_ARRAY)
    {
#if NASL_DEBUG > 1
      nasl_perror(NULL ,"Warning: affecting array to atomic variable (0x%x) %s\n",  t2, get_line_nb(rval));
#endif
    }

  /* Bug #146: this fake clear is necessary if we copy an array*/
  memset(v1, 0, sizeof(*v1));
  /* Bug #146: no risk with the type, we already copied it */
  v1->var_type = t2;

  if (rval->type != REF_VAR && rval->type != REF_ARRAY && rval->type != DYN_ARRAY)
    switch (t2)
      {
      case VAR2_INT:
	v1->v.v_int = rval->x.i_val;
	break;
      case VAR2_STRING:
      case VAR2_DATA:
        if( rval->x.str_val == NULL )
	  {
	    v1->v.v_str.s_val = NULL;
	    v1->v.v_str.s_siz = 0;
	  }
	else
	  {
	    p = emalloc(rval->size+1);
	    memcpy(p, rval->x.str_val, rval->size+1);
	    v1->v.v_str.s_siz = rval->size;
	    v1->v.v_str.s_val = p;
	  }
	break;
      }
  else				/* REF_xxx */
    switch(t2)
      {
      case VAR2_INT:
	v1->v.v_int = v2->v.v_int;
	break;
      case VAR2_STRING:
      case VAR2_DATA:
        if(v2->v.v_str.s_val == NULL)
	  {
	    v1->v.v_str.s_val = NULL;
	    v1->v.v_str.s_siz = 0;
	  }
	else
	  {
	    p = emalloc(v2->v.v_str.s_siz);
	    memcpy(p, v2->v.v_str.s_val, v2->v.v_str.s_siz);
	    v1->v.v_str.s_siz = v2->v.v_str.s_siz;
	    v1->v.v_str.s_val = p;
	  }
	break;
      case VAR2_ARRAY:
	copy_array(&v1->v.v_arr, a);
	if (v0.var_type == VAR2_ARRAY)
	  bzero(&v0, sizeof(v0));	/* So that we don't clear the variable twice */
	break;
      }

  if (nasl_trace_fp != NULL)
    switch(t2)
      {
      case VAR2_INT:
	nasl_trace(NULL, "NASL> %s <- %d\n", get_var_name(v1), v1->v.v_int);
	break;
      case VAR2_STRING:
      case VAR2_DATA:
	nasl_trace(NULL, "NASL> %s <- \"%s\"\n", get_var_name(v1), v1->v.v_str.s_val);
	break;
      case VAR2_ARRAY:
	nasl_trace(NULL, "NASL> %s <- (VAR2_ARRAY)\n", get_var_name(v1));
	break;
      default:
	nasl_trace(NULL, "NASL> %s <- (Type 0x%x)\n", get_var_name(v1), t2);
	break;
      }

  clear_anon_var(&v0);
  return FAKE_CELL;
}
tree_cell*
nasl_read_var_ref(lex_ctxt* lexic, tree_cell* tc)
{
  tree_cell	*ret;
  anon_nasl_var	*v;

  if (tc == NULL || tc == FAKE_CELL)
    {
      nasl_perror(lexic, "nasl_read_var_ref: cannot read NULL or FAKE cell\n");
      return NULL;
    }
  if (tc->type != REF_VAR)
    {
      nasl_perror(lexic, "nasl_read_var_ref: argument (type=%d) is not REF_VAR %s\n", tc->type, get_line_nb(tc));
      return NULL;
    }

  v = tc->x.ref_val;
  if (v == NULL)
    {
      nasl_perror(lexic, "nasl_read_var_ref: NULL variable in REF_VAR\n");
      return NULL;
    }

  ret = alloc_tree_cell(tc->line_nb, NULL);

  switch (v->var_type)
    {
    case VAR2_INT:
      ret->type = CONST_INT;
      ret->x.i_val = v->v.v_int;
      if(nasl_trace_enabled())nasl_trace(lexic, "NASL> %s -> %d\n", get_var_name(v), ret->x.i_val);
      return ret;

    case VAR2_STRING:
      ret->type = CONST_STR;
      /* Fix bad string length */
      if (v->v.v_str.s_siz <= 0 && v->v.v_str.s_val[0] != '\0')
	{
	  v->v.v_str.s_siz = strlen(v->v.v_str.s_val);
	  nasl_perror(lexic, "nasl_read_var_ref: Bad string length fixed\n");
	}
      /* Go on next case */
    case VAR2_DATA:
      ret->type = v->var_type == VAR2_STRING ? CONST_STR : CONST_DATA;
      if(v->v.v_str.s_val == NULL)
      {
       ret->x.str_val = NULL;
       ret->size = 0;
      }
      else
      {
       ret->x.str_val = emalloc(v->v.v_str.s_siz);
       memcpy(ret->x.str_val, v->v.v_str.s_val, v->v.v_str.s_siz);
       ret->size = v->v.v_str.s_siz;
      }
      if(nasl_trace_enabled())nasl_trace(lexic, "NASL> %s -> \"%s\"\n", get_var_name(v), ret->x.str_val);
      return ret;

    case VAR2_ARRAY:
      ret->type = REF_ARRAY;
      ret->x.ref_val = &v->v.v_arr;
      return ret;

    case VAR2_UNDEF:
#if NASL_DEBUG > 0
      name = get_var_name(v);
      if (strcmp(name, "NULL") != 0) /* special case */
	nasl_perror(lexic, "nasl_read_var_ref: variable %s is undefined %s\n",
		    name, get_line_nb(tc));
#endif
      if(nasl_trace_enabled())nasl_trace(lexic, "NASL> %s -> undef\n", get_var_name(v), v->var_type);
      break;

    default:
      nasl_perror(lexic, "nasl_read_var_ref: unhandled variable type %d\n",
	      v->var_type);
      if(nasl_trace_enabled())nasl_trace(lexic, "NASL> %s -> ???? (Var type %d)\n", get_var_name(v), v->var_type);
      break;
    }
  deref_cell(ret);
  return NULL;
}
Beispiel #3
0
tree_cell*
nasl_func_call(lex_ctxt* lexic, const nasl_func* f, tree_cell* arg_list)
{
#if 0
  return FAKE_CELL;
#else
  int		nb_u = 0, nb_n = 0, nb_a = 0;
  tree_cell	*pc = NULL, *pc2 = NULL, *retc = NULL;
  lex_ctxt	*lexic2 = NULL;
  char		*trace_buf = NULL;
  int		trace_buf_len = 0, tn;
#define TRACE_BUF_SZ	255

#if 0
  nasl_dump_tree(arg_list);
#endif

  /* 1. Create a new context */
  lexic2 = init_empty_lex_ctxt();
  lexic2->script_infos = lexic->script_infos;
  lexic2->authenticated = lexic->authenticated;
  lexic2->recv_timeout = lexic->recv_timeout;
  lexic2->fct_ctxt = 1;

  if (nasl_trace_fp != NULL)
    {
      trace_buf = emalloc(TRACE_BUF_SZ);
      tn = 
	snprintf(trace_buf, TRACE_BUF_SZ, "Call %s(", f->func_name);
      if (tn > 0) trace_buf_len += tn;
    }

  if (! (f->flags & FUNC_FLAG_COMPAT))
    {
      for (pc = arg_list; pc != NULL; pc = pc->link[1])
	if (pc->x.str_val == NULL)
	  nb_u ++;
	else
	  {
	    size_t num = f->nb_named_args;
	    if (lfind(&pc->x.str_val, f->args_names, &num, sizeof(char*), stringcompare) != NULL)
	      nb_n ++;
	  }
  
      if (nb_n + nb_u > f->nb_unnamed_args + f->nb_named_args)
	nasl_perror(lexic,
		"Too many args for function '%s' [%dN+%dU > %dN+%dU]\n",
		f->func_name, nb_n, nb_u, f->nb_unnamed_args, f->nb_named_args);
      /*
       * I should look exactly how unnamed arguments works... 
       * Or maybe I should remove this feature?
       */

      for (nb_u = 0, pc = arg_list; pc != NULL; pc = pc->link[1])
	{
#if 0
	  pc2 = pc->link[0];
	  ref_cell(pc2);
	  do
	    {
	      pc22 = nasl_exec(lexic, pc2);
	      deref_cell(pc2);
	      pc2 = pc22;
	    }
	  while (! nasl_is_leaf(pc2));
#else
	  pc2 = cell2atom(lexic, pc->link[0]);
#endif
	  if (pc->x.str_val == NULL)
	    {
	      /* 2. Add unnamed (numbered) variables for unnamed args */
	      if (add_numbered_var_to_ctxt(lexic2, nb_u, pc2) == NULL)
		goto error;
	      nb_u ++;
	      if (nasl_trace_fp != NULL && trace_buf_len < TRACE_BUF_SZ)
		{
		  tn =
		    snprintf(trace_buf + trace_buf_len, 
			     TRACE_BUF_SZ - trace_buf_len,
			     "%s%d: %s",
			     nb_a > 0 ? ", " : "", nb_u, 
			     dump_cell_val(pc2));
		  if (tn > 0) trace_buf_len += tn;
		}
	      nb_a ++;
	    }
	  else
	    {
	      /* 3. and add named variables for named args */
	      if (add_named_var_to_ctxt(lexic2, pc->x.str_val, pc2) == NULL)
		goto error;
	      if (nasl_trace_fp != NULL && trace_buf_len < TRACE_BUF_SZ)
		{
		  tn =
		    snprintf(trace_buf + trace_buf_len,
			     TRACE_BUF_SZ - trace_buf_len,
			     "%s%s: %s",
			     nb_a > 0 ? ", " : "", pc->x.str_val,
			     dump_cell_val(pc2));
		  if (tn > 0) trace_buf_len += tn;
		}
	      nb_a ++;
	    }
	  deref_cell(pc2);
	}

      if (nasl_trace_fp != NULL)
	{
	  if (trace_buf_len < TRACE_BUF_SZ)
	    nasl_trace(lexic, "NASL> %s)\n", trace_buf);
	  else
	    nasl_trace(lexic, "NASL> %s ...)\n", trace_buf);
	  trace_buf_len = 0;
	  efree(&trace_buf);
	}

      /* 4. Chain new context to old (lexic) */
      lexic2->up_ctxt = lexic;
      /* 5. Execute */
      if (f->flags & FUNC_FLAG_INTERNAL)
	{
	  tree_cell*	(*pf2)(lex_ctxt*) = f->block;
	  retc = pf2(lexic2);
	}
      else
	{
	  retc = nasl_exec(lexic2, f->block);
	  deref_cell(retc);
	  retc = FAKE_CELL;
	}

      if ((retc == NULL || retc == FAKE_CELL) &&
	  (lexic2->ret_val != NULL && lexic2->ret_val != FAKE_CELL))
	{
#if 0
	  nasl_perror(lexic, "nasl_func_call: nasl_exec(%s) returns NULL or FAKE value, but context disagrees. Fixing...\n", f->func_name);
	  nasl_dump_tree(retc);
#endif
	  retc = lexic2->ret_val;
	  ref_cell(retc);
	}

        if(nasl_trace_enabled())nasl_trace(lexic, "NASL> Return %s: %s\n", f->func_name,
		  dump_cell_val(retc));
#if 1
      if (! nasl_is_leaf(retc))
	{
	  nasl_perror(lexic, "nasl_func_call: return value from %s is not atomic!\n", f->func_name);
	  nasl_dump_tree(retc);
	}
#endif

      free_lex_ctxt(lexic2); lexic2 = NULL;
      return retc;
    }


 error:
  free_lex_ctxt(lexic2);
  return NULL;
#endif
}