Using an overload that takes a va_list argument potentially causes
accidental misuse on platforms (e.g. 32-bit) where va_list is
implemented as a type that may collide with commonly-used argument
types.
For example:
char* c = copy_string("hi");
fmt("%s", (const char*)c);
fmt("%s", c);
The first fmt() call correctly goes through fmt(const char*, ...) first,
but the second mistakenly goes through fmt(const char*, va_list) first
because variadic function overloads have lower priority during overload
resolution and va_list on a 32-bit system happens to be defined as a
pointer type that can match with "char*" but not "const char*".
* MaxKellermann/includes:
broker: include cleanup
file_analysis: include cleanup
file_analysis/Analyzer: eliminate duplicate constructor
probabilistic/Topk: include cleanup
digest: eliminate the "Reporter.h" include
Val: eliminate the "RE.h" include
Val: eliminate the "BroString.h" include
Val: eliminate the "CompHash.h" include
Val: forward-declare class PDict, reduce includes
Val: eliminate the "Scope.h" include
* origin/topic/timw/dict-unit-tests:
Reset the number of entries in a dict when calling Clear()
Code cleanup in Dict.h
Add unit testing for the public Dictionary API
* origin/topic/timw/clang-tidy:
fixup! Use string_view for a couple of Dbg methods
Add a couple of missing #includes that clang-tidy complains about (clang-diagnostic-error)
Fix missing namespace that was causing a build error
Remove unnecessary const from return value (readability-const-return-type)
Give real variable names to SegmentProfiler objects when defining them (bugprone-unused-raii)
Mark a few clang-tidy findings as false-positive
Use std::move in a few places instead of copying a pass-by-value argument (performance-unnecessary-value-param)
Use const-references in lots of places (preformance-unnecessary-value-param)
Use string_view for a couple of Dbg methods
Use const references over copying variables (performance-unnecessary-copy-initialization, performance-for-range-copy)
Use single-character version of string find() (performance-faster-string-find)
Move constructors/operators should be marked noexcept to avoid the compiler picking the copy constructor instead (performance-noexcept-move-constructor)
The reason behind this one is that without a real variable name, the profile objects are immediately desctructed and the profiling only happens for the small window when they were valid. If the intention is to profile the method where they were defined, this doesn't actually happen.
An attacker can make Zeek crash by posting the KEX packet twice, which
will result in an assertion failure in binpac::datastring::init():
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1 0x00007ffff5196535 in __GI_abort () at abort.c:79
#2 0x00007ffff519640f in __assert_fail_base (fmt=0x7ffff52f86e0 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0x1d33530 "!data_",
file=0x1d33537 "aux/binpac/lib/binpac_bytestring.h", line=108, function=<optimized out>) at assert.c:92
#3 0x00007ffff51a3b92 in __GI___assert_fail (assertion=0x1d33530 "!data_", file=0x1d33537 "aux/binpac/lib/binpac_bytestring.h",
line=108, function=0x1d3356c "void binpac::datastring<unsigned char>::init(const T *, int) [T = unsigned char]") at assert.c:101
#4 0x0000000000c1e970 in binpac::datastring<unsigned char>::init (this=0x608000d609d0, begin=0x603001bdd1d0 "diffie-hellman-group16-sha512", length=29)
at aux/binpac/lib/binpac_bytestring.h:108
#5 0x0000000000e9ab60 in binpac::SSH::SSH_Conn::update_kex (this=0x608000d609a0, algs=..., orig=true) at src/analyzer/protocol/ssh/ssh_pac.cc:205
#6 0x0000000000ea0d06 in binpac::SSH::SSH2_KEXINIT::Parse (this=0x60b000734680,
t_begin_of_data=0x621000004753 "\200\275\a%\223\023Y8\204t\235\363!\031I.", t_end_of_data=0x621000004b85 "ޭ\276", <incomplete sequence \357>,
t_context=0x603001bdcc90, t_byteorder=0) at src/analyzer/protocol/ssh/ssh_pac.cc:1598
#7 0x0000000000e9f8f4 in binpac::SSH::SSH2_Message::Parse (this=0x608000d60ea0,
t_begin_of_data=0x621000004753 "\200\275\a%\223\023Y8\204t\235\363!\031I.", t_end_of_data=0x621000004b85 "ޭ\276", <incomplete sequence \357>,
t_context=0x603001bdcc90, t_byteorder=0) at src/analyzer/protocol/ssh/ssh_pac.cc:1326
#8 0x0000000000e9d7e1 in binpac::SSH::SSH2_Key_Exchange::Parse (this=0x604001779850,
t_begin_of_data=0x621000004751 "\006\024\200\275\a%\223\023Y8\204t\235\363!\031I.", t_end_of_data=0x621000004b85 "ޭ\276", <incomplete sequence \357>,
t_context=0x603001bdcc90, t_byteorder=0) at src/analyzer/protocol/ssh/ssh_pac.cc:1210
#9 0x0000000000e9c981 in binpac::SSH::SSH_Key_Exchange::ParseBuffer (this=0x603001bdccc0, t_flow_buffer=0x608000d60a20, t_context=0x603001bdcc90,
t_byteorder=0) at src/analyzer/protocol/ssh/ssh_pac.cc:628
#10 0x0000000000e9c26c in binpac::SSH::SSH_PDU::ParseBuffer (this=0x604001779810, t_flow_buffer=0x608000d60a20, t_context=0x603001bdcc90)
at src/analyzer/protocol/ssh/ssh_pac.cc:446
#11 0x0000000000ea6f04 in binpac::SSH::SSH_Flow::NewData (this=0x604001774690, t_begin_of_data=0x62100000474d "",
t_end_of_data=0x621000004b85 "ޭ\276", <incomplete sequence \357>) at src/analyzer/protocol/ssh/ssh_pac.cc:3071
#12 0x0000000000e9a38f in binpac::SSH::SSH_Conn::NewData (this=0x608000d609a0, is_orig=true, begin=0x62100000474d "",
end=0x621000004b85 "ޭ\276", <incomplete sequence \357>) at src/analyzer/protocol/ssh/ssh_pac.cc:63
#13 0x0000000000e98335 in analyzer::SSH::SSH_Analyzer::DeliverStream (this=0x7fffffffdd40, len=1080, data=0x62100000474d "", orig=true)
at src/analyzer/protocol/ssh/SSH.cc:68
With assertions turned off, this would "only" be a memory leak.
This commit fixes the vulnerability by freeing and clearing the
`binpac::datastring` before assigning a new value.