mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
spicy-redis: Add recursion depth to server data
This commit is contained in:
parent
292241f420
commit
90d56ce630
1 changed files with 24 additions and 12 deletions
|
@ -7,6 +7,7 @@ import spicy;
|
||||||
# Maximum size for parsing of certain fields. By restricting this we avoid
|
# Maximum size for parsing of certain fields. By restricting this we avoid
|
||||||
# exhausting main memory.
|
# exhausting main memory.
|
||||||
const MAX_SIZE = 1024 * 1024;
|
const MAX_SIZE = 1024 * 1024;
|
||||||
|
const MAX_RECURSION_DEPTH = 20;
|
||||||
|
|
||||||
public type ClientMessages = unit {
|
public type ClientMessages = unit {
|
||||||
: ClientData[];
|
: ClientData[];
|
||||||
|
@ -61,10 +62,11 @@ type BulkStringWithTy = unit {
|
||||||
|
|
||||||
public type ServerData = unit {
|
public type ServerData = unit {
|
||||||
%synchronize-after = b"\x0d\x0a";
|
%synchronize-after = b"\x0d\x0a";
|
||||||
data: Data;
|
var depth: uint8& = new uint8;
|
||||||
|
data: Data(self.depth);
|
||||||
};
|
};
|
||||||
|
|
||||||
public type Data = unit {
|
type Data = unit(depth: uint8&) {
|
||||||
%synchronize-after = b"\x0d\x0a";
|
%synchronize-after = b"\x0d\x0a";
|
||||||
ty: uint8 &convert=DataType($$);
|
ty: uint8 &convert=DataType($$);
|
||||||
switch (self.ty) {
|
switch (self.ty) {
|
||||||
|
@ -72,7 +74,7 @@ public type Data = unit {
|
||||||
DataType::SIMPLE_ERROR -> simple_error: SimpleString(True);
|
DataType::SIMPLE_ERROR -> simple_error: SimpleString(True);
|
||||||
DataType::INTEGER -> integer: Integer;
|
DataType::INTEGER -> integer: Integer;
|
||||||
DataType::BULK_STRING -> bulk_string: BulkString(False);
|
DataType::BULK_STRING -> bulk_string: BulkString(False);
|
||||||
DataType::ARRAY -> array: Array;
|
DataType::ARRAY -> array: Array(depth);
|
||||||
DataType::NULL -> null: Null_;
|
DataType::NULL -> null: Null_;
|
||||||
DataType::BOOLEAN -> boolean: Boolean;
|
DataType::BOOLEAN -> boolean: Boolean;
|
||||||
DataType::DOUBLE -> double: Double;
|
DataType::DOUBLE -> double: Double;
|
||||||
|
@ -82,12 +84,22 @@ public type Data = unit {
|
||||||
# "Some client libraries may ignore the difference between this type and the string type"
|
# "Some client libraries may ignore the difference between this type and the string type"
|
||||||
# It just includes the encoding first in the content
|
# It just includes the encoding first in the content
|
||||||
DataType::VERBATIM_STRING -> verbatim_string: BulkString(False);
|
DataType::VERBATIM_STRING -> verbatim_string: BulkString(False);
|
||||||
DataType::MAP -> map_: Map;
|
DataType::MAP -> map_: Map(depth);
|
||||||
DataType::SET -> set_: Set;
|
DataType::SET -> set_: Set(depth);
|
||||||
# "Push events are encoded similarly to arrays, differing only in their
|
# "Push events are encoded similarly to arrays, differing only in their
|
||||||
# first byte" - TODO: can probably make it more obvious, though
|
# first byte" - TODO: can probably make it more obvious, though
|
||||||
DataType::PUSH -> push: Array;
|
DataType::PUSH -> push: Array(depth);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
on %init {
|
||||||
|
depth++;
|
||||||
|
if (*depth > MAX_RECURSION_DEPTH)
|
||||||
|
throw "exceeded max recursion depth";
|
||||||
|
}
|
||||||
|
|
||||||
|
on %done {
|
||||||
|
depth--;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
type DataType = enum {
|
type DataType = enum {
|
||||||
|
@ -129,10 +141,10 @@ type BulkString = unit(is_error: bool) {
|
||||||
: skip RedisBytes;
|
: skip RedisBytes;
|
||||||
};
|
};
|
||||||
|
|
||||||
type Array = unit {
|
type Array = unit(depth: uint8&) {
|
||||||
num_elements: RedisBytes &convert=$$.to_int(10) &requires=self.num_elements <= int64(MAX_SIZE);
|
num_elements: RedisBytes &convert=$$.to_int(10) &requires=self.num_elements <= int64(MAX_SIZE);
|
||||||
# Null array is an array with elements unset. This is different from an empty array
|
# Null array is an array with elements unset. This is different from an empty array
|
||||||
elements: Data[uint64(self.num_elements)];
|
elements: Data(depth)[uint64(self.num_elements)];
|
||||||
};
|
};
|
||||||
|
|
||||||
type Null_ = unit {
|
type Null_ = unit {
|
||||||
|
@ -154,11 +166,11 @@ type BigNum = unit {
|
||||||
val: RedisBytes;
|
val: RedisBytes;
|
||||||
};
|
};
|
||||||
|
|
||||||
type Map = unit {
|
type Map = unit(depth: uint8&) {
|
||||||
var key_val_pairs: vector<tuple<Data, Data>>;
|
var key_val_pairs: vector<tuple<Data, Data>>;
|
||||||
num_elements: RedisBytes &convert=$$.to_uint(10);
|
num_elements: RedisBytes &convert=$$.to_uint(10);
|
||||||
# TODO: How can I make this into a map? Alternatively, how can I do this better?
|
# TODO: How can I make this into a map? Alternatively, how can I do this better?
|
||||||
raw_data: Data[self.num_elements * 2] {
|
raw_data: Data(depth)[self.num_elements * 2] {
|
||||||
while (local i = 0; i < self.num_elements) {
|
while (local i = 0; i < self.num_elements) {
|
||||||
self.key_val_pairs.push_back(($$[i], $$[i + 1]));
|
self.key_val_pairs.push_back(($$[i], $$[i + 1]));
|
||||||
i += 2;
|
i += 2;
|
||||||
|
@ -166,10 +178,10 @@ type Map = unit {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
type Set = unit {
|
type Set = unit(depth: uint8&) {
|
||||||
num_elements: RedisBytes &convert=$$.to_uint(10) &requires=self.num_elements <= MAX_SIZE;
|
num_elements: RedisBytes &convert=$$.to_uint(10) &requires=self.num_elements <= MAX_SIZE;
|
||||||
# TODO: This should be a set but doesn't go in the backed C++ set
|
# TODO: This should be a set but doesn't go in the backed C++ set
|
||||||
elements: Data[self.num_elements];
|
elements: Data(depth)[self.num_elements];
|
||||||
};
|
};
|
||||||
|
|
||||||
on ServerData::%done {
|
on ServerData::%done {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue