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