From 7c80b577f106656fb88fac60f0ff135f9b00f62f Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 27 Feb 2020 11:50:25 +0100 Subject: [PATCH] Var: fix crash when redeclaring a function with different args The following source code: function foo(foo: int) {} function foo() {} ... first produces this error: error in crash.zeek, line 1 and crash.zeek, line 2: incompatible types (function(foo:int;) : void and function() : void) ... and then crashes: Thread 1 "zeek" received signal SIGSEGV, Segmentation fault. 0x000055555617d970 in RecordType::FieldDecl (this=0x555557cbdd80, field=0) at ../src/Type.cc:735 735 return (*types)[field]; (gdb) bt #0 0x000055555617d970 in RecordType::FieldDecl (this=0x555557cbdd80, field=0) at ../src/Type.cc:735 #1 0x000055555619c0e2 in transfer_arg_defaults (args=0x555557cbf270, recv=0x555557cbdd80) at ../src/Var.cc:315 #2 0x000055555619c40c in begin_func (id=0x555557cbf070, module_name=0x5555579dd4a0 "GLOBAL", flavor=FUNC_FLAVOR_FUNCTION, is_redef=0, t=0x555557cbde00, attrs=0x0) at ../src/Var.cc:371 #3 0x0000555555f5723b in yyparse () at parse.y:1174 #4 0x0000555556038bf6 in main (argc=5, argv=0x7fffffffe658) at ../src/main.cc:646 This is because `begin_func()` checks if the old and new functions have the same type via same_type(), but continues anyway, and then transfer_arg_defaults() crashes because both `Args()` have different lengths. --- src/Var.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Var.cc b/src/Var.cc index c1d9b61022..1e9f7668ad 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -364,11 +364,11 @@ void begin_func(ID* id, const char* module_name, function_flavor flavor, { if ( ! same_type(id->Type(), t) ) id->Type()->Error("incompatible types", t); - - // If a previous declaration of the function had &default params, - // automatically transfer any that are missing (convenience so that - // implementations don't need to specify the &default expression again). - transfer_arg_defaults(id->Type()->AsFuncType()->Args(), t->Args()); + else + // If a previous declaration of the function had &default params, + // automatically transfer any that are missing (convenience so that + // implementations don't need to specify the &default expression again). + transfer_arg_defaults(id->Type()->AsFuncType()->Args(), t->Args()); } else if ( is_redef )