mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Fix |...|
operator for inner ports/enums
The `|...|` (sizeof) operator applies to ports/enums. That has returned a count, but it causes an internal error when used as an inner value in a record. This fixes that internal error for ports by just making the sizeof operator return a count. Enums could technically be negative before this change, but that is rejected at parse time. It seems reasonable to modify the enum value to only be non-negative, which makes the sizeof operator easier since it can just return a count. Changing that to return an int would potentially break scripts that use the sizeof operator and assign it to a count. This could technically break code that internally sets the enum value to a negative value, but I don't think that's a very likely use.
This commit is contained in:
parent
ba91de59b0
commit
a26d2dd56c
9 changed files with 37 additions and 10 deletions
4
NEWS
4
NEWS
|
@ -25,6 +25,10 @@ Breaking Changes
|
||||||
are not affected by this change, so we keep backwards compatibility with
|
are not affected by this change, so we keep backwards compatibility with
|
||||||
existing log writers.
|
existing log writers.
|
||||||
|
|
||||||
|
* Enum values can no longer be negative even if created internally. This is
|
||||||
|
enforced at parse time for scripts, but not internally. With this change, the
|
||||||
|
``|...|`` operator for enums will properly return a count in all instances.
|
||||||
|
|
||||||
New Functionality
|
New Functionality
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
|
|
@ -1542,6 +1542,12 @@ void EnumType::CheckAndAddName(const string& module_name, const char* name, zeek
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( val < 0 ) {
|
||||||
|
reporter->Error("enumerator value cannot be negative");
|
||||||
|
SetError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto fullname = detail::make_full_var_name(module_name.c_str(), name);
|
auto fullname = detail::make_full_var_name(module_name.c_str(), name);
|
||||||
auto id = id::find(fullname);
|
auto id = id::find(fullname);
|
||||||
|
|
||||||
|
|
|
@ -594,7 +594,7 @@ void IntervalVal::ValDescribe(ODesc* d) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ValPtr PortVal::SizeVal() const { return val_mgr->Int(uint_val); }
|
ValPtr PortVal::SizeVal() const { return val_mgr->Count(uint_val); }
|
||||||
|
|
||||||
uint32_t PortVal::Mask(uint32_t port_num, TransportProto port_type) {
|
uint32_t PortVal::Mask(uint32_t port_num, TransportProto port_type) {
|
||||||
// Note, for ICMP one-way connections:
|
// Note, for ICMP one-way connections:
|
||||||
|
@ -3133,10 +3133,10 @@ unsigned int RecordVal::ComputeFootprint(std::unordered_set<const Val*>* analyze
|
||||||
return fp;
|
return fp;
|
||||||
}
|
}
|
||||||
|
|
||||||
ValPtr EnumVal::SizeVal() const { return val_mgr->Int(AsInt()); }
|
ValPtr EnumVal::SizeVal() const { return val_mgr->Count(AsCount()); }
|
||||||
|
|
||||||
void EnumVal::ValDescribe(ODesc* d) const {
|
void EnumVal::ValDescribe(ODesc* d) const {
|
||||||
const char* ename = type->AsEnumType()->Lookup(int_val);
|
const char* ename = type->AsEnumType()->Lookup(uint_val);
|
||||||
|
|
||||||
if ( ! ename )
|
if ( ! ename )
|
||||||
ename = "<undefined>";
|
ename = "<undefined>";
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
#include <sys/types.h> // for u_char
|
#include <sys/types.h> // for u_char
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <list>
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -1497,7 +1496,7 @@ private:
|
||||||
const std::vector<bool>& is_managed;
|
const std::vector<bool>& is_managed;
|
||||||
};
|
};
|
||||||
|
|
||||||
class EnumVal final : public detail::IntValImplementation {
|
class EnumVal final : public detail::UnsignedValImplementation {
|
||||||
public:
|
public:
|
||||||
ValPtr SizeVal() const override;
|
ValPtr SizeVal() const override;
|
||||||
|
|
||||||
|
@ -1505,12 +1504,12 @@ protected:
|
||||||
friend class Val;
|
friend class Val;
|
||||||
friend class EnumType;
|
friend class EnumType;
|
||||||
|
|
||||||
friend EnumValPtr make_enum__CPP(TypePtr t, zeek_int_t i);
|
friend EnumValPtr make_enum__CPP(TypePtr t, zeek_uint_t i);
|
||||||
|
|
||||||
template<class T, class... Ts>
|
template<class T, class... Ts>
|
||||||
friend IntrusivePtr<T> make_intrusive(Ts&&... args);
|
friend IntrusivePtr<T> make_intrusive(Ts&&... args);
|
||||||
|
|
||||||
EnumVal(EnumTypePtr t, zeek_int_t i) : detail::IntValImplementation(std::move(t), i) {}
|
EnumVal(EnumTypePtr t, zeek_uint_t i) : detail::UnsignedValImplementation(std::move(t), i) {}
|
||||||
|
|
||||||
void ValDescribe(ODesc* d) const override;
|
void ValDescribe(ODesc* d) const override;
|
||||||
ValPtr DoClone(CloneState* state) override;
|
ValPtr DoClone(CloneState* state) override;
|
||||||
|
|
|
@ -223,7 +223,7 @@ EnumTypePtr get_enum_type__CPP(const string& enum_type_name) {
|
||||||
return make_intrusive<EnumType>(enum_type_name);
|
return make_intrusive<EnumType>(enum_type_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
EnumValPtr make_enum__CPP(TypePtr t, zeek_int_t i) {
|
EnumValPtr make_enum__CPP(TypePtr t, zeek_uint_t i) {
|
||||||
auto et = cast_intrusive<EnumType>(std::move(t));
|
auto et = cast_intrusive<EnumType>(std::move(t));
|
||||||
return make_intrusive<EnumVal>(et, i);
|
return make_intrusive<EnumVal>(et, i);
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,7 +95,7 @@ extern EnumTypePtr get_enum_type__CPP(const std::string& enum_type_name);
|
||||||
|
|
||||||
// Returns an enum value corresponding to the given low-level value 'i'
|
// Returns an enum value corresponding to the given low-level value 'i'
|
||||||
// in the context of the given enum type 't'.
|
// in the context of the given enum type 't'.
|
||||||
extern EnumValPtr make_enum__CPP(TypePtr t, zeek_int_t i);
|
extern EnumValPtr make_enum__CPP(TypePtr t, zeek_uint_t i);
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace zeek
|
} // namespace zeek
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
expression warning in <...>/sizeof.zeek, line 73: count underflow (5 - 9)
|
expression warning in <...>/sizeof.zeek, line 83: count underflow (5 - 9)
|
||||||
|
|
|
@ -7,11 +7,13 @@ Expr: 18446744073709551612
|
||||||
Signed Expr: 4
|
Signed Expr: 4
|
||||||
Double -1.23: 1.230000
|
Double -1.23: 1.230000
|
||||||
Enum ENUM3: 2
|
Enum ENUM3: 2
|
||||||
|
Enum in record: 2
|
||||||
File 21.000000
|
File 21.000000
|
||||||
Function add_interface: 2
|
Function add_interface: 2
|
||||||
Integer -10: 10
|
Integer -10: 10
|
||||||
Interval -5.0 secs: 5.000000
|
Interval -5.0 secs: 5.000000
|
||||||
Port 80/tcp: 65616
|
Port 80/tcp: 65616
|
||||||
|
Port in record: 65616
|
||||||
Record [i=10, j=<uninitialized>, k=<uninitialized>]: 3
|
Record [i=10, j=<uninitialized>, k=<uninitialized>]: 3
|
||||||
Set: 3
|
Set: 3
|
||||||
String 'Hello': 5
|
String 'Hello': 5
|
||||||
|
|
|
@ -20,6 +20,14 @@ type example_record: record {
|
||||||
k: int &optional;
|
k: int &optional;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type example_record_with_enum: record {
|
||||||
|
e: count &default = |ENUM3|;
|
||||||
|
} &redef;
|
||||||
|
|
||||||
|
type example_record_with_port: record {
|
||||||
|
p: count &default = |80/tcp|;
|
||||||
|
} &redef;
|
||||||
|
|
||||||
global a: addr = 1.2.3.4;
|
global a: addr = 1.2.3.4;
|
||||||
global a6: addr = [::1];
|
global a6: addr = [::1];
|
||||||
global b: bool = T;
|
global b: bool = T;
|
||||||
|
@ -36,6 +44,8 @@ global sn: subnet = 192.168.0.0/24;
|
||||||
global t: table[string] of string;
|
global t: table[string] of string;
|
||||||
global ti: time = current_time();
|
global ti: time = current_time();
|
||||||
global v: vector of string;
|
global v: vector of string;
|
||||||
|
global with_enum: example_record_with_enum;
|
||||||
|
global with_port: example_record_with_port;
|
||||||
|
|
||||||
# Additional initialization
|
# Additional initialization
|
||||||
#
|
#
|
||||||
|
@ -80,6 +90,9 @@ print fmt("Double %s: %f", d, |d|);
|
||||||
# Size of enum: returns numeric value of enum constant.
|
# Size of enum: returns numeric value of enum constant.
|
||||||
print fmt("Enum %s: %d", ENUM3, |ENUM3|);
|
print fmt("Enum %s: %d", ENUM3, |ENUM3|);
|
||||||
|
|
||||||
|
# Within a record, enum sizeof should still be ok
|
||||||
|
print fmt("Enum in record: %d", |with_enum$e|);
|
||||||
|
|
||||||
# Size of file: returns current file size.
|
# Size of file: returns current file size.
|
||||||
# Note that this is a double so that file sizes >> 4GB
|
# Note that this is a double so that file sizes >> 4GB
|
||||||
# can be expressed.
|
# can be expressed.
|
||||||
|
@ -97,6 +110,9 @@ print fmt("Interval %s: %f", iv, |iv|);
|
||||||
# Size of port: returns port number as a count.
|
# Size of port: returns port number as a count.
|
||||||
print fmt("Port %s: %d", p, |p|);
|
print fmt("Port %s: %d", p, |p|);
|
||||||
|
|
||||||
|
# Within a record, port sizeof should still be ok
|
||||||
|
print fmt("Port in record: %d", |with_port$p|);
|
||||||
|
|
||||||
# Size of record: returns number of fields (assigned + unassigned)
|
# Size of record: returns number of fields (assigned + unassigned)
|
||||||
print fmt("Record %s: %d", r, |r|);
|
print fmt("Record %s: %d", r, |r|);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue