zeek/testing/btest/language/sizeof.zeek
Evan Typanski d3dd8a155d Fix port/enum values SizeOf not being a count
Really, they both should be count. But, they were getting provided as an
integer. Port is easy since it is backed by an unsigned value. Enums
*should* be unsigned, but aren't. This doesn't address that, it just
takes the other name for this operator (absolute value) and makes the
enum value positive if it's negative.

This fixes a case where using the size of operator on enum/port values
in certain contexts (like the default parameter of a struct) would cause
an internal error.
2024-09-17 10:55:45 -04:00

143 lines
4.3 KiB
Text

# @TEST-EXEC: zeek -b %INPUT >output
# @TEST-EXEC: btest-diff output
# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff .stderr
# Demo policy for the sizeof operator "|x|".
# ------------------------------------------
#
# This script creates various types and values and shows the result of the
# sizeof operator on these values.
#
# For any types not covered in this script, the sizeof operator's semantics
# are not defined and its application returns a count of 0. At the moment
# the only type where this should happen is string patterns.
type example_enum: enum { ENUM1, ENUM2, ENUM3 };
type example_record: record {
i: int &optional;
j: 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 a6: addr = [::1];
global b: bool = T;
global c: count = 10;
global d: double = -1.23;
global f: file = open("sizeof_demo.log");
global i: int = -10;
global iv: interval = -5sec;
global p: port = 80/tcp;
global r: example_record = [ $i = +10 ];
global si: set[int];
global s: string = "Hello";
global sn: subnet = 192.168.0.0/24;
global t: table[string] of string;
global ti: time = current_time();
global v: vector of string;
global with_enum: example_record_with_enum;
global with_port: example_record_with_port;
# Additional initialization
#
print f, "12345678901234567890";
add si[1];
add si[10];
add si[100];
t["foo"] = "Hello";
t["bar"] = "World";
v[0] = "Hello";
v[4] = "World";
# Print out the sizes of the various vals:
#-----------------------------------------
# Size of addr: returns number of bits required to represent the address
# which is 32 for IPv4 or 128 for IPv6
print fmt("IPv4 Address %s: %d", a, |a|);
print fmt("IPv6 Address %s: %d", a6, |a6|);
# Size of boolean: returns 1 or 0.
print fmt("Boolean %s: %d", b, |b|);
# Size of count: identity.
print fmt("Count %s: %d", c, |c|);
# Integer literals that lack a "+" or "-" modifier are of the unsigned "count"
# type, so this wraps to a very large number. It may be more intuitive if it
# were to coerce to a signed integer, but it can also be more favorable to
# simply have consistent behavior across arbitrary arithmetic expressions even
# if that may result in occasional, unintended overflow/wrapping.
print fmt("Expr: %d", |5 - 9|);
# Same arithmetic on signed integers is likely what's originally intended.
print fmt("Signed Expr: %d", |+5 - +9|);
# Size of double: returns absolute value.
print fmt("Double %s: %f", d, |d|);
# Size of enum: returns numeric value of enum constant.
print fmt("Enum %s: %d", ENUM3, |ENUM3|);
# Within a record, enum sizeof should still be ok
print fmt("Enum in record: %d %d", with_enum$e, |with_enum$e|);
# Size of file: returns current file size.
# Note that this is a double so that file sizes >> 4GB
# can be expressed.
print fmt("File %f", |f|);
# Size of function: returns number of arguments.
print fmt("Function add_interface: %d", |add_interface|);
# Size of integer: returns absolute value.
print fmt("Integer %s: %d", i, |i|);
# Size of interval: returns double representation of the interval
print fmt("Interval %s: %f", iv, |iv|);
# Size of port: returns port number as a count.
print fmt("Port %s: %d", p, |p|);
# Within a record, port sizeof should still be ok
print fmt("Port in record: %d %d", with_port$p, |with_port$p|);
# Size of record: returns number of fields (assigned + unassigned)
print fmt("Record %s: %d", r, |r|);
# Size of set: returns number of elements in set.
# Don't print the set, as its order depends on the seeding of the hash
# function, and it's not worth the trouble to normalize it.
print fmt("Set: %d", |si|);
# Size of string: returns string length.
print fmt("String '%s': %d", s, |s|);
# Size of subnet: returns size of net as a double
# (so that 2^32 can be expressed too).
print fmt("Subnet %s: %f", sn, |sn|);
# Size of table: returns number of elements in table
print fmt("Table %d", |t|);
# Size of time: returns double representation of the time
# print fmt("Time %s: %f", ti, |ti|);
# Size of vector: returns largest assigned index.
# Note that this is not the number of assigned values.
# The following prints "5":
#
print fmt("Vector %s: %d", v, |v|);
close(f);