LCOV - code coverage report
Current view: top level - src - Func.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 100 267 37.5 %
Date: 2010-12-13 Functions: 10 43 23.3 %
Branches: 58 222 26.1 %

           Branch data     Line data    Source code
       1                 :            : // $Id: Func.cc 6703 2009-05-13 22:27:44Z vern $
       2                 :            : //
       3                 :            : // See the file "COPYING" in the main distribution directory for copyright.
       4                 :            : 
       5                 :            : #include "config.h"
       6                 :            : 
       7                 :            : #include <sys/types.h>
       8                 :            : #include <sys/stat.h>
       9                 :            : #ifdef TIME_WITH_SYS_TIME
      10                 :            : # include <sys/time.h>
      11                 :            : # include <time.h>
      12                 :            : #else
      13                 :            : # ifdef HAVE_SYS_TIME_H
      14                 :            : #  include <sys/time.h>
      15                 :            : # else
      16                 :            : #  include <time.h>
      17                 :            : # endif
      18                 :            : #endif
      19                 :            : #include <sys/resource.h>
      20                 :            : 
      21                 :            : #include <netinet/in.h>
      22                 :            : 
      23                 :            : #include <stdlib.h>
      24                 :            : #include <errno.h>
      25                 :            : #include <ctype.h>
      26                 :            : 
      27                 :            : #include <sys/param.h>
      28                 :            : #include <netdb.h>
      29                 :            : #include <unistd.h>
      30                 :            : #include <signal.h>
      31                 :            : 
      32                 :            : #include <algorithm>
      33                 :            : 
      34                 :            : #include "md5.h"
      35                 :            : #include "Base64.h"
      36                 :            : #include "Stmt.h"
      37                 :            : #include "Scope.h"
      38                 :            : #include "Net.h"
      39                 :            : #include "NetVar.h"
      40                 :            : #include "File.h"
      41                 :            : #include "Func.h"
      42                 :            : #include "Frame.h"
      43                 :            : #include "Var.h"
      44                 :            : #include "Login.h"
      45                 :            : #include "Sessions.h"
      46                 :            : #include "RE.h"
      47                 :            : #include "Serializer.h"
      48                 :            : #include "RemoteSerializer.h"
      49                 :            : #include "Event.h"
      50                 :            : #include "Traverse.h"
      51                 :            : 
      52                 :            : extern  RETSIGTYPE sig_handler(int signo);
      53                 :            : 
      54                 :            : const Expr* calling_expr = 0;
      55                 :            : bool did_builtin_init = false;
      56                 :            : 
      57                 :            : 
      58                 :          0 : Func::~Func()
      59                 :            :         {
      60 [ #  # ][ #  # ]:          0 :         }
                 [ #  # ]
      61                 :            : 
      62                 :            : void Func::AddBody(Stmt* /* new_body */, id_list* /* new_inits */,
      63                 :          0 :                         int /* new_frame_size */, int /* priority */)
      64                 :            :         {
      65                 :          0 :         Internal("Func::AddBody called");
      66                 :          0 :         }
      67                 :            : 
      68                 :          0 : bool Func::Serialize(SerialInfo* info) const
      69                 :            :         {
      70                 :          0 :         return SerialObj::Serialize(info);
      71                 :            :         }
      72                 :            : 
      73                 :          0 : Func* Func::Unserialize(UnserialInfo* info)
      74                 :            :         {
      75                 :          0 :         Func* f = (Func*) SerialObj::Unserialize(info, SER_FUNC);
      76                 :            : 
      77                 :            :         // For builtins, we return a reference to the (hopefully) already
      78                 :            :         // existing function.
      79   [ #  #  #  # ]:          0 :         if ( f && f->kind == BUILTIN_FUNC )
      80                 :            :                 {
      81                 :          0 :                 const char* name = ((BuiltinFunc*) f)->Name();
      82                 :          0 :                 ID* id = global_scope()->Lookup(name);
      83         [ #  # ]:          0 :                 if ( ! id )
      84                 :            :                         {
      85                 :          0 :                         info->s->Error(fmt("can't find built-in %s", name));
      86                 :          0 :                         return 0;
      87                 :            :                         }
      88                 :            : 
      89 [ #  # ][ #  # ]:          0 :                 if ( ! (id->HasVal() && id->ID_Val()->Type()->Tag() == TYPE_FUNC) )
                 [ #  # ]
      90                 :            :                         {
      91                 :          0 :                         info->s->Error(fmt("ID %s is not a built-in", name));
      92                 :          0 :                         return false;
      93                 :            :                         }
      94                 :            : 
      95                 :          0 :                 Unref(f);
      96                 :          0 :                 f = id->ID_Val()->AsFunc();
      97                 :          0 :                 Ref(f);
      98                 :            :                 }
      99                 :            : 
     100                 :          0 :         return f;
     101                 :            :         }
     102                 :            : 
     103                 :          0 : bool Func::DoSerialize(SerialInfo* info) const
     104                 :            :         {
     105 [ #  # ][ #  # ]:          0 :         DO_SERIALIZE(SER_FUNC, BroObj);
     106                 :            : 
     107         [ #  # ]:          0 :         if ( ! SERIALIZE(int(bodies.size())) )
     108                 :          0 :                 return false;
     109                 :            : 
     110         [ #  # ]:          0 :         for ( unsigned int i = 0; i < bodies.size(); ++i )
     111                 :            :                 {
     112         [ #  # ]:          0 :                 if ( ! bodies[i].stmts->Serialize(info) )
     113                 :          0 :                         return false;
     114         [ #  # ]:          0 :                 if ( ! SERIALIZE(bodies[i].priority) )
     115                 :          0 :                         return false;
     116                 :            :                 }
     117                 :            : 
     118         [ #  # ]:          0 :         if ( ! SERIALIZE(char(kind) ) )
     119                 :          0 :                 return false;
     120                 :            : 
     121                 :            :         // We don't serialize scope as only global functions are considered here
     122                 :            :         // anyway.
     123                 :          0 :         return true;
     124                 :            :         }
     125                 :            : 
     126                 :          0 : bool Func::DoUnserialize(UnserialInfo* info)
     127                 :            :         {
     128         [ #  # ]:          0 :         DO_UNSERIALIZE(BroObj);
     129                 :            : 
     130                 :            :         int len;
     131         [ #  # ]:          0 :         if ( ! UNSERIALIZE(&len) )
     132                 :          0 :                 return false;
     133                 :            : 
     134         [ #  # ]:          0 :         while ( len-- )
     135                 :            :                 {
     136                 :            :                 Body b;
     137                 :          0 :                 b.stmts = Stmt::Unserialize(info);
     138         [ #  # ]:          0 :                 if ( ! b.stmts )
     139                 :          0 :                         return false;
     140                 :            : 
     141         [ #  # ]:          0 :                 if ( ! UNSERIALIZE(&b.priority) )
     142                 :          0 :                         return false;
     143                 :            : 
     144                 :          0 :                 bodies.push_back(b);
     145                 :            :                 }
     146                 :            : 
     147                 :            :         char c;
     148         [ #  # ]:          0 :         if ( ! UNSERIALIZE(&c) )
     149                 :          0 :                 return false;
     150                 :            : 
     151                 :          0 :         kind = (Kind) c;
     152                 :          0 :         return true;
     153                 :            :         }
     154                 :            : 
     155                 :          0 : void Func::DescribeDebug(ODesc* d, const val_list* args) const
     156                 :            :         {
     157                 :          0 :         id->Describe(d);
     158                 :          0 :         RecordType* func_args = FType()->Args();
     159                 :            : 
     160         [ #  # ]:          0 :         if ( args )
     161                 :            :                 {
     162                 :          0 :                 d->Add("(");
     163                 :            : 
     164         [ #  # ]:          0 :                 for ( int i = 0; i < args->length(); ++i )
     165                 :            :                         {
     166                 :            :                         // Handle varargs case (more args than formals).
     167         [ #  # ]:          0 :                         if ( i >= func_args->NumFields() )
     168                 :            :                                 {
     169                 :          0 :                                 d->Add("vararg");
     170                 :          0 :                                 d->Add(i - func_args->NumFields());
     171                 :            :                                 }
     172                 :            :                         else
     173                 :          0 :                                 d->Add(func_args->FieldName(i));
     174                 :            : 
     175                 :          0 :                         d->Add(" = '");
     176                 :          0 :                         (*args)[i]->Describe(d);
     177                 :            : 
     178         [ #  # ]:          0 :                         if ( i < args->length() - 1 )
     179                 :          0 :                                 d->Add("', ");
     180                 :            :                         else
     181                 :          0 :                                 d->Add("'");
     182                 :            :                         }
     183                 :            : 
     184                 :          0 :                 d->Add(")");
     185                 :            :                 }
     186                 :          0 :         }
     187                 :            : 
     188                 :          0 : void Func::SetID(ID *arg_id)
     189                 :            :         {
     190                 :          0 :         id = arg_id;
     191                 :            : 
     192                 :            :         return_value =
     193                 :            :                 new ID(string(string(id->Name()) + "_returnvalue").c_str(),
     194                 :          0 :                         SCOPE_FUNCTION, false);
     195                 :          0 :         return_value->SetType(FType()->YieldType()->Ref());
     196                 :          0 :         }
     197                 :            : 
     198                 :          0 : ID* Func::GetReturnValueID() const
     199                 :            :         {
     200                 :          0 :         return return_value;
     201                 :            :         }
     202                 :            : 
     203                 :          0 : TraversalCode Func::Traverse(TraversalCallback* cb) const
     204                 :            :         {
     205                 :            :         // FIXME: Make a fake scope for builtins?
     206                 :          0 :         Scope* old_scope = cb->current_scope;
     207                 :          0 :         cb->current_scope = scope;
     208                 :            : 
     209                 :          0 :         TraversalCode tc = cb->PreFunction(this);
     210   [ #  #  #  # ]:          0 :         HANDLE_TC_STMT_PRE(tc);
     211                 :            : 
     212                 :            :         // FIXME: Traverse arguments to builtin functions, too.
     213         [ #  # ]:          0 :         if ( kind == BRO_FUNC )
     214                 :            :                 {
     215                 :          0 :                 tc = scope->Traverse(cb);
     216   [ #  #  #  # ]:          0 :                 HANDLE_TC_STMT_PRE(tc);
     217                 :            : 
     218         [ #  # ]:          0 :                 if ( GetReturnValueID() )
     219                 :            :                         {
     220                 :          0 :                         tc = GetReturnValueID()->Traverse(cb);
     221   [ #  #  #  # ]:          0 :                         HANDLE_TC_STMT_PRE(tc);
     222                 :            :                         }
     223                 :            : 
     224         [ #  # ]:          0 :                 for ( unsigned int i = 0; i < bodies.size(); ++i )
     225                 :            :                         {
     226                 :          0 :                         tc = bodies[i].stmts->Traverse(cb);
     227   [ #  #  #  # ]:          0 :                         HANDLE_TC_STMT_PRE(tc);
     228                 :            :                         }
     229                 :            :                 }
     230                 :            : 
     231                 :          0 :         tc = cb->PostFunction(this);
     232                 :            : 
     233                 :          0 :         cb->current_scope = old_scope;
     234 [ #  # ][ #  # ]:          0 :         HANDLE_TC_STMT_POST(tc);
     235                 :            :         }
     236                 :            : 
     237                 :            : BroFunc::BroFunc(ID* arg_id, Stmt* arg_body, id_list* aggr_inits,
     238                 :        948 :                 int arg_frame_size)
     239                 :        948 : : Func(BRO_FUNC)
     240                 :            :         {
     241                 :        948 :         id = arg_id;
     242                 :            :         Body b;
     243                 :        948 :         b.stmts = AddInits(arg_body, aggr_inits);
     244                 :        948 :         b.priority = 0;
     245                 :        948 :         bodies.push_back(b);
     246                 :        948 :         frame_size = arg_frame_size;
     247                 :        948 :         }
     248                 :            : 
     249                 :          0 : BroFunc::~BroFunc()
     250                 :            :         {
     251                 :          0 :         Unref(id);
     252 [ #  # ][ #  # ]:          0 :         for ( unsigned int i = 0; i < bodies.size(); ++i )
                 [ #  # ]
     253                 :          0 :                 Unref(bodies[i].stmts);
     254 [ #  # ][ #  # ]:          0 :         }
                 [ #  # ]
     255                 :            : 
     256                 :          0 : int BroFunc::IsPure() const
     257                 :            :         {
     258         [ #  # ]:          0 :         for ( unsigned int i = 0; i < bodies.size(); ++i )
     259         [ #  # ]:          0 :                 if ( ! bodies[i].stmts->IsPure() )
     260                 :          0 :                         return 0;
     261                 :            : 
     262                 :          0 :         return 1;
     263                 :            :         }
     264                 :            : 
     265                 :      94706 : Val* BroFunc::Call(val_list* args, Frame* parent) const
     266                 :            :         {
     267                 :            : #ifdef PROFILE_BRO_FUNCTIONS
     268                 :            :         DEBUG_MSG("Function: %s\n", id->Name());
     269                 :            : #endif
     270                 :      94706 :         SegmentProfiler(segment_logger, location);
     271                 :      94706 :         Frame* f = new Frame(frame_size, this, args);
     272                 :            : 
     273                 :            :         // Hand down any trigger.
     274         [ +  + ]:      94706 :         if ( parent )
     275                 :            :                 {
     276                 :      69948 :                 f->SetTrigger(parent->GetTrigger());
     277                 :      69948 :                 f->SetCall(parent->GetCall());
     278                 :            :                 }
     279                 :            : 
     280                 :      94706 :         g_frame_stack.push_back(f);     // used for backtracing
     281                 :            : 
     282         [ -  + ]:      94706 :         if ( g_trace_state.DoTrace() )
     283                 :            :                 {
     284                 :          0 :                 ODesc d;
     285                 :          0 :                 DescribeDebug(&d, args);
     286                 :            : 
     287                 :            :                 g_trace_state.LogTrace("%s called: %s\n",
     288         [ #  # ]:          0 :                         IsEvent() ? "event" : "function", d.Description());
     289                 :            :                 }
     290                 :            : 
     291         [ +  + ]:     277476 :         loop_over_list(*args, i)
     292                 :     182770 :                 f->SetElement(i, (*args)[i]);
     293                 :            : 
     294                 :            :         stmt_flow_type flow;
     295                 :            : 
     296                 :      94706 :         Val* result = 0;
     297                 :            : 
     298         [ -  + ]:      94706 :         if ( sample_logger )
     299                 :          0 :                 sample_logger->FunctionSeen(this);
     300                 :            : 
     301         [ +  + ]:     202942 :         for ( unsigned int i = 0; i < bodies.size(); ++i )
     302                 :            :                 {
     303         [ -  + ]:     108236 :                 if ( sample_logger )
     304                 :            :                         sample_logger->LocationSeen(
     305                 :          0 :                                 bodies[i].stmts->GetLocationInfo());
     306                 :            : 
     307                 :     108236 :                 Unref(result);
     308                 :     108236 :                 result = bodies[i].stmts->Exec(f, flow);
     309                 :            : 
     310         [ -  + ]:     108236 :                 if ( f->HasDelayed() )
     311                 :            :                         {
     312         [ #  # ]:          0 :                         assert(! result);
     313         [ #  # ]:          0 :                         assert(parent);
     314                 :          0 :                         parent->SetDelayed();
     315                 :          0 :                         break;
     316                 :            :                         }
     317                 :            :                 }
     318                 :            : 
     319                 :            :         // Warn if the function returns something, but we returned from
     320                 :            :         // the function without an explicit return, or without a value.
     321 [ +  + ][ +  + ]:      94706 :         if ( FType()->YieldType() && FType()->YieldType()->Tag() != TYPE_VOID &&
         [ +  - ][ -  + ]
         [ #  # ][ -  + ]
     322                 :            :              (flow != FLOW_RETURN /* we fell off the end */ ||
     323                 :            :               ! result /* explicit return with no result */) &&
     324                 :            :              ! f->HasDelayed() )
     325                 :          0 :                 warn("non-void function returns without a value:", id->Name());
     326                 :            : 
     327 [ +  + ][ -  + ]:      94706 :         if ( result && g_trace_state.DoTrace() )
                 [ -  + ]
     328                 :            :                 {
     329                 :          0 :                 ODesc d;
     330                 :          0 :                 result->Describe(&d);
     331                 :            : 
     332                 :          0 :                 g_trace_state.LogTrace("Function return: %s\n", d.Description());
     333                 :            :                 }
     334                 :            : 
     335                 :      94706 :         g_frame_stack.pop_back();
     336                 :      94706 :         Unref(f);
     337                 :            : 
     338                 :      94706 :         return result;
     339                 :            :         }
     340                 :            : 
     341                 :            : void BroFunc::AddBody(Stmt* new_body, id_list* new_inits, int new_frame_size,
     342                 :        177 :                 int priority)
     343                 :            :         {
     344         [ +  + ]:        177 :         if ( new_frame_size > frame_size )
     345                 :         37 :                 frame_size = new_frame_size;
     346                 :            : 
     347                 :        177 :         new_body = AddInits(new_body, new_inits);
     348                 :            : 
     349         [ +  + ]:        177 :         if ( ! IsEvent() )
     350                 :            :                 {
     351                 :            :                 // For functions, we replace the old body with the new one.
     352         [ -  + ]:          1 :                 assert(bodies.size() <= 1);
     353         [ +  + ]:          2 :                 for ( unsigned int i = 0; i < bodies.size(); ++i )
     354                 :          1 :                         Unref(bodies[i].stmts);
     355                 :          1 :                 bodies.clear();
     356                 :            :                 }
     357                 :            : 
     358                 :            :         Body b;
     359                 :        177 :         b.stmts = new_body;
     360                 :        177 :         b.priority = priority;
     361                 :            : 
     362                 :        177 :         bodies.push_back(b);
     363                 :        177 :         sort(bodies.begin(), bodies.end());
     364                 :        177 :         }
     365                 :            : 
     366                 :          0 : void BroFunc::Describe(ODesc* d) const
     367                 :            :         {
     368         [ #  # ]:          0 :         if ( id )
     369                 :          0 :                 id->Describe(d);
     370                 :            : 
     371                 :          0 :         d->NL();
     372                 :          0 :         d->AddCount(frame_size);
     373         [ #  # ]:          0 :         for ( unsigned int i = 0; i < bodies.size(); ++i )
     374                 :            :                 {
     375                 :          0 :                 bodies[i].stmts->AccessStats(d);
     376                 :          0 :                 bodies[i].stmts->Describe(d);
     377                 :            :                 }
     378                 :          0 :         }
     379                 :            : 
     380                 :       1125 : Stmt* BroFunc::AddInits(Stmt* body, id_list* inits)
     381                 :            :         {
     382 [ +  - ][ +  + ]:       1125 :         if ( ! inits || inits->length() == 0 )
                 [ +  + ]
     383                 :       1048 :                 return body;
     384                 :            : 
     385                 :         77 :         StmtList* stmt_series = new StmtList;
     386                 :       1202 :         stmt_series->Stmts().append(new InitStmt(inits));
     387                 :         77 :         stmt_series->Stmts().append(body);
     388                 :            : 
     389                 :         77 :         return stmt_series;
     390                 :            :         }
     391                 :            : 
     392                 :          3 : IMPLEMENT_SERIAL(BroFunc, SER_BRO_FUNC);
     393                 :            : 
     394                 :          0 : bool BroFunc::DoSerialize(SerialInfo* info) const
     395                 :            :         {
     396 [ #  # ][ #  # ]:          0 :         DO_SERIALIZE(SER_BRO_FUNC, Func);
     397 [ #  # ][ #  # ]:          0 :         return id->Serialize(info) && SERIALIZE(frame_size);
     398                 :            :         }
     399                 :            : 
     400                 :          0 : bool BroFunc::DoUnserialize(UnserialInfo* info)
     401                 :            :         {
     402         [ #  # ]:          0 :         DO_UNSERIALIZE(Func);
     403                 :          0 :         id = ID::Unserialize(info);
     404   [ #  #  #  # ]:          0 :         return id && UNSERIALIZE(&frame_size);
     405                 :            :         }
     406                 :            : 
     407                 :            : BuiltinFunc::BuiltinFunc(built_in_func arg_func, const char* arg_name,
     408                 :        738 :                         int arg_is_pure)
     409                 :        738 : : Func(BUILTIN_FUNC)
     410                 :            :         {
     411                 :        738 :         func = arg_func;
     412                 :        738 :         name = copy_string(make_full_var_name(GLOBAL_MODULE_NAME, arg_name).c_str());
     413                 :        738 :         is_pure = arg_is_pure;
     414                 :            : 
     415                 :        738 :         id = lookup_ID(name, GLOBAL_MODULE_NAME, false);
     416   [ -  +  #  # ]:        738 :         if ( ! id )
     417                 :          0 :                 internal_error("built-in function %s missing", name);
     418 [ -  + ][ #  # ]:        738 :         if ( id->HasVal() )
     419                 :          0 :                 internal_error("built-in function %s multiply defined", name);
     420                 :            : 
     421                 :        738 :         id->SetVal(new Val(this));
     422                 :        738 :         }
     423                 :            : 
     424                 :          0 : BuiltinFunc::~BuiltinFunc()
     425                 :            :         {
     426 [ #  # ][ #  # ]:          0 :         }
                 [ #  # ]
     427                 :            : 
     428                 :          0 : int BuiltinFunc::IsPure() const
     429                 :            :         {
     430                 :          0 :         return is_pure;
     431                 :            :         }
     432                 :            : 
     433                 :     130601 : Val* BuiltinFunc::Call(val_list* args, Frame* parent) const
     434                 :            :         {
     435                 :            : #ifdef PROFILE_BRO_FUNCTIONS
     436                 :            :         DEBUG_MSG("Function: %s\n", Name());
     437                 :            : #endif
     438                 :     130601 :         SegmentProfiler(segment_logger, name);
     439                 :            : 
     440         [ -  + ]:     130601 :         if ( sample_logger )
     441                 :          0 :                 sample_logger->FunctionSeen(this);
     442                 :            : 
     443         [ -  + ]:     130601 :         if ( g_trace_state.DoTrace() )
     444                 :            :                 {
     445                 :          0 :                 ODesc d;
     446                 :          0 :                 DescribeDebug(&d, args);
     447                 :            : 
     448                 :          0 :                 g_trace_state.LogTrace("\tBuiltin Function called: %s\n", d.Description());
     449                 :            :                 }
     450                 :            : 
     451                 :     130601 :         Val* result = func(parent, args);
     452         [ +  + ]:     469819 :         loop_over_list(*args, i)
     453                 :     339218 :                 Unref((*args)[i]);
     454                 :            : 
     455                 :            :         // Don't Unref() args, that's the caller's responsibility.
     456 [ +  + ][ -  + ]:     130601 :         if ( result && g_trace_state.DoTrace() )
                 [ -  + ]
     457                 :            :                 {
     458                 :          0 :                 ODesc d;
     459                 :          0 :                 result->Describe(&d);
     460                 :            : 
     461                 :          0 :                 g_trace_state.LogTrace("\tFunction return: %s\n", d.Description());
     462                 :            :                 }
     463                 :            : 
     464                 :     130601 :         return result;
     465                 :            :         }
     466                 :            : 
     467                 :          0 : void BuiltinFunc::Describe(ODesc* d) const
     468                 :            :         {
     469         [ #  # ]:          0 :         if ( id )
     470                 :          0 :         id->Describe(d);
     471                 :          0 :         d->AddCount(is_pure);
     472                 :          0 :         }
     473                 :            : 
     474                 :          3 : IMPLEMENT_SERIAL(BuiltinFunc, SER_BUILTIN_FUNC);
     475                 :            : 
     476                 :          0 : bool BuiltinFunc::DoSerialize(SerialInfo* info) const
     477                 :            :         {
     478 [ #  # ][ #  # ]:          0 :         DO_SERIALIZE(SER_BUILTIN_FUNC, Func);
     479                 :            : 
     480                 :            :         // We ignore the ID. Func::Serialize() will rebind us anyway.
     481                 :          0 :         return SERIALIZE(name);
     482                 :            :         }
     483                 :            : 
     484                 :          0 : bool BuiltinFunc::DoUnserialize(UnserialInfo* info)
     485                 :            :         {
     486         [ #  # ]:          0 :         DO_UNSERIALIZE(Func);
     487                 :          0 :         id = 0;
     488                 :          0 :         return UNSERIALIZE_STR(&name, 0);
     489                 :            :         }
     490                 :            : 
     491                 :          0 : void builtin_run_time(const char* msg, BroObj* arg)
     492                 :            :         {
     493         [ #  # ]:          0 :         if ( calling_expr )
     494                 :          0 :                 calling_expr->RunTime(msg, arg);
     495                 :            :         else
     496                 :          0 :                 run_time(msg, arg);
     497                 :          0 :         }
     498                 :            : 
     499                 :            : #include "bro.bif.func_def"
     500                 :            : #include "strings.bif.func_def"
     501                 :            : 
     502                 :          3 : void init_builtin_funcs()
     503                 :            :         {
     504                 :          3 :         ftp_port = internal_type("ftp_port")->AsRecordType();
     505                 :          3 :         bro_resources = internal_type("bro_resources")->AsRecordType();
     506                 :          3 :         matcher_stats = internal_type("matcher_stats")->AsRecordType();
     507                 :          3 :         var_sizes = internal_type("var_sizes")->AsTableType();
     508                 :          3 :         gap_info = internal_type("gap_info")->AsRecordType();
     509                 :            : 
     510                 :            : #include "bro.bif.func_init"
     511                 :            : 
     512                 :            : #include "common-rw.bif.func_init"
     513                 :            : #include "finger-rw.bif.func_init"
     514                 :            : #include "ftp-rw.bif.func_init"
     515                 :            : #include "http-rw.bif.func_init"
     516                 :            : #include "ident-rw.bif.func_init"
     517                 :            : #include "smtp-rw.bif.func_init"
     518                 :            : #include "strings.bif.func_init"
     519                 :            : #include "dns-rw.bif.func_init"
     520                 :            : 
     521                 :          3 :         did_builtin_init = true;
     522                 :          3 :         }
     523                 :            : 
     524                 :        892 : bool check_built_in_call(BuiltinFunc* f, CallExpr* call)
     525                 :            :         {
     526         [ -  + ]:        892 :         if ( f->TheFunc() != bro_fmt )
     527                 :          0 :                 return true;
     528                 :            : 
     529                 :        892 :         const expr_list& args = call->Args()->Exprs();
     530         [ -  + ]:        892 :         if ( args.length() == 0 )
     531                 :            :                 {
     532                 :            :                 // Empty calls are allowed, since you can't just
     533                 :            :                 // use "print;" to get a blank line.
     534                 :          0 :                 return true;
     535                 :            :                 }
     536                 :            : 
     537                 :        892 :         const Expr* fmt_str_arg = args[0];
     538         [ -  + ]:        892 :         if ( fmt_str_arg->Type()->Tag() != TYPE_STRING )
     539                 :            :                 {
     540                 :          0 :                 call->Error("first argument to fmt() needs to be a format string");
     541                 :          0 :                 return false;
     542                 :            :                 }
     543                 :            : 
     544                 :        892 :         Val* fmt_str_val = fmt_str_arg->Eval(0);
     545                 :            : 
     546         [ +  + ]:        892 :         if ( fmt_str_val )
     547                 :            :                 {
     548                 :        890 :                 const char* fmt_str = fmt_str_val->AsStringVal()->CheckString();
     549                 :            : 
     550                 :        890 :                 int num_fmt = 0;
     551         [ +  + ]:      16656 :                 while ( *fmt_str )
     552                 :            :                         {
     553         [ +  + ]:      15766 :                         if ( *(fmt_str++) != '%' )
     554                 :      13515 :                                 continue;
     555                 :            : 
     556         [ -  + ]:       2251 :                         if ( ! *fmt_str )
     557                 :            :                                 {
     558                 :          0 :                                 call->Error("format string ends with bare '%'");
     559                 :          0 :                                 return false;
     560                 :            :                                 }
     561                 :            : 
     562         [ +  + ]:       2251 :                         if ( *(fmt_str++) != '%' )
     563                 :            :                                 // Not a "%%" escape.
     564                 :       2245 :                                 ++num_fmt;
     565                 :            :                         }
     566                 :            : 
     567         [ -  + ]:        890 :                 if ( args.length() != num_fmt + 1 )
     568                 :            :                         {
     569                 :          0 :                         call->Error("mismatch between format string to fmt() and number of arguments passed");
     570                 :          0 :                         return false;
     571                 :            :                         }
     572                 :            :                 }
     573                 :            : 
     574                 :        892 :         return true;
     575 [ +  - ][ +  - ]:          6 :         }

Generated by: LCOV version 1.8