Skip to content

Commit

Permalink
Consider max container depth
Browse files Browse the repository at this point in the history
  • Loading branch information
temeddix committed Oct 7, 2024
1 parent 6dd6ef3 commit b2de40b
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 35 deletions.
9 changes: 8 additions & 1 deletion serde-generate/runtime/dart/bcs/bcs_deserializer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,15 @@ part of bcs;
// Maximum length allowed for sequences (vectors, bytes, strings) and maps.
const maxSequenceLength = (1 << 31) - 1;

// Maximum number of nested structs and enum variants.
const maxContainerDepth = 500;

class BcsDeserializer extends BinaryDeserializer {
BcsDeserializer(Uint8List input) : super(input);
BcsDeserializer(Uint8List input)
: super(
input: input,
containerDepthBudget: maxContainerDepth,
);

int deserializeUleb128AsUint32() {
var value = 0;
Expand Down
5 changes: 5 additions & 0 deletions serde-generate/runtime/dart/bcs/bcs_serializer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
part of bcs;

class BcsSerializer extends BinarySerializer {
BcsSerializer()
: super(
containerDepthBudget: maxContainerDepth,
);

void serializeUint32AsUleb128(int value) {
while (((value & 0xFFFFFFFF) >> 7) != 0) {
output.add((value & 0x7f) | 0x80);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@

part of bincode;

// Maximum number of nested structs and enum variants.
const maxContainerDepth = (1 << 31) - 1;

class BincodeDeserializer extends BinaryDeserializer {
BincodeDeserializer(Uint8List input) : super(input);
BincodeDeserializer(Uint8List input)
: super(input: input, containerDepthBudget: maxContainerDepth);

@override
int deserializeLength() {
Expand Down
5 changes: 5 additions & 0 deletions serde-generate/runtime/dart/bincode/bincode_serializer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
part of bincode;

class BincodeSerializer extends BinarySerializer {
BincodeSerializer()
: super(
containerDepthBudget: maxContainerDepth,
);

@override
void serializeLength(int value) {
serializeUint64(Uint64(BigInt.from(value)));
Expand Down
17 changes: 16 additions & 1 deletion serde-generate/runtime/dart/serde/binary_deserializer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@
part of serde;

abstract class BinaryDeserializer {
BinaryDeserializer(Uint8List input) : input = ByteData.view(input.buffer);
BinaryDeserializer({
required Uint8List input,
required this.containerDepthBudget,
}) : input = ByteData.view(input.buffer);

@protected
final ByteData input;
int _offset = 0;
int containerDepthBudget;

int get offset {
return _offset;
Expand Down Expand Up @@ -154,4 +158,15 @@ abstract class BinaryDeserializer {
return number.toUnsigned(byteLength * 8);
}
}

void increaseContainerDepth() {
if (containerDepthBudget == 0) {
throw Exception('exceeded maximum container depth');
}
containerDepthBudget -= 1;
}

void decreaseContainerDepth() {
containerDepthBudget += 1;
}
}
16 changes: 16 additions & 0 deletions serde-generate/runtime/dart/serde/binary_serializer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
part of serde;

abstract class BinarySerializer {
BinarySerializer({
required this.containerDepthBudget,
});

int containerDepthBudget;
final List<int> output = List<int>.empty(growable: true);

Uint8List get bytes {
Expand Down Expand Up @@ -137,4 +142,15 @@ abstract class BinarySerializer {
serializeUint64(Uint64(value.low));
serializeUint64(Uint64(value.high));
}

void increaseContainerDepth() {
if (containerDepthBudget == 0) {
throw Exception('exceeded maximum container depth');
}
containerDepthBudget -= 1;
}

void decreaseContainerDepth() {
containerDepthBudget += 1;
}
}
56 changes: 24 additions & 32 deletions serde-generate/src/dart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -670,53 +670,43 @@ return obj;
}

if self.generator.config.serialization {
// a struct (UnitStruct) with zero fields
if variant_index.is_none() && fields.is_empty() {
writeln!(
self.out,
"\n{}.deserialize(BinaryDeserializer deserializer);",
self.quote_qualified_name(name)
)?;
// Deserialize (struct) or Load (variant)
} else if variant_index.is_none() {
writeln!(
self.out,
"\n{}.deserialize(BinaryDeserializer deserializer) :",
self.quote_qualified_name(name)
)?;
} else if !fields.is_empty() {
if variant_index.is_none() {
writeln!(
self.out,
"\n{}.load(BinaryDeserializer deserializer) :",
"\nstatic {} deserialize(BinaryDeserializer deserializer) {{",
self.quote_qualified_name(name)
)?;
} else {
writeln!(
self.out,
"\n{}.load(BinaryDeserializer deserializer);",
"\nstatic {} load(BinaryDeserializer deserializer) {{",
self.quote_qualified_name(name)
)?;
}

self.out.indent();
for (index, field) in fields.iter().enumerate() {
if index == field_count - 1 {
writeln!(
self.out,
"{} = {};",
self.quote_field(&field.name.to_mixed_case()),
self.quote_deserialize(&field.value)
)?;
} else {
writeln!(
self.out,
"{} = {},",
self.quote_field(&field.name.to_mixed_case()),
self.quote_deserialize(&field.value)
)?;
}
writeln!(self.out, "deserializer.increaseContainerDepth();")?;
writeln!(
self.out,
"final instance = {}(",
self.quote_qualified_name(name)
)?;
self.out.indent();
for field in fields {
writeln!(
self.out,
"{}: {},",
self.quote_field(&field.name.to_mixed_case()),
self.quote_deserialize(&field.value)
)?;
}
self.out.unindent();
writeln!(self.out, ");")?;
writeln!(self.out, "deserializer.decreaseContainerDepth();")?;
writeln!(self.out, "return instance;")?;
self.out.unindent();
writeln!(self.out, "}}")?;

if variant_index.is_none() {
for encoding in &self.generator.config.encodings {
Expand Down Expand Up @@ -780,6 +770,7 @@ return obj;
if self.generator.config.serialization {
writeln!(self.out, "\nvoid serialize(BinarySerializer serializer) {{",)?;
self.out.indent();
writeln!(self.out, "serializer.increaseContainerDepth();")?;
if let Some(index) = variant_index {
writeln!(self.out, "serializer.serializeVariantIndex({});", index)?;
}
Expand All @@ -793,6 +784,7 @@ return obj;
)
)?;
}
writeln!(self.out, "serializer.decreaseContainerDepth();")?;
self.out.unindent();
writeln!(self.out, "}}")?;

Expand Down

0 comments on commit b2de40b

Please sign in to comment.