Skip to content

Commit

Permalink
[audit] decode redundant compact encoding (#28)
Browse files Browse the repository at this point in the history
Signed-off-by: turuslan <turuslan.devbox@gmail.com>
  • Loading branch information
turuslan authored Oct 16, 2024
1 parent 3b0960c commit e1a3c7a
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 2 deletions.
3 changes: 2 additions & 1 deletion include/scale/scale_error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ namespace scale {
UNEXPECTED_VALUE, ///< unexpected value
TOO_MANY_ITEMS, ///< too many items, cannot address them in memory
WRONG_TYPE_INDEX, ///< wrong type index, cannot decode variant
INVALID_ENUM_VALUE ///< enum value which doesn't belong to the enum
INVALID_ENUM_VALUE, ///< enum value which doesn't belong to the enum
REDUNDANT_COMPACT_ENCODING, ///< redundant bytes in compact encoding
};

} // namespace scale
Expand Down
14 changes: 13 additions & 1 deletion src/scale_decoder_stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ namespace scale {
number = (static_cast<size_t>((first_byte)&0b11111100u)
+ static_cast<size_t>(second_byte) * 256u)
>> 2u;
if ((number >> 6) == 0) {
raise(DecodeError::REDUNDANT_COMPACT_ENCODING);
}
break;
}

Expand All @@ -44,6 +47,9 @@ namespace scale {
multiplier = multiplier << 8u;
}
number = number >> 2u;
if ((number >> 14) == 0) {
raise(DecodeError::REDUNDANT_COMPACT_ENCODING);
}
break;
}

Expand All @@ -61,7 +67,13 @@ namespace scale {
value += (stream.nextByte()) * multiplier;
multiplier *= 256u;
}

if (value.is_zero()) {
raise(DecodeError::REDUNDANT_COMPACT_ENCODING);
}
auto bits = msb(value) + 1;
if (bits <= 30 or (bits + 7) / 8 < bytes_count) {
raise(DecodeError::REDUNDANT_COMPACT_ENCODING);
}
return value; // special case
}

Expand Down
2 changes: 2 additions & 0 deletions src/scale_error.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ OUTCOME_CPP_DEFINE_CATEGORY(scale, DecodeError, e) {
return "SCALE decode: wrong type index, cannot decode variant";
case DecodeError::INVALID_ENUM_VALUE:
return "SCALE decode: decoded enum value does not belong to the enum";
case DecodeError::REDUNDANT_COMPACT_ENCODING:
return "SCALE decode: redundant bytes in compact encoding";
}
return "unknown SCALE DecodeError";
}
18 changes: 18 additions & 0 deletions test/scale_compact_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,21 @@ TEST(Scale, compactDecodeBigIntegerError) {
auto bytes = ByteArray{255, 255, 255, 255};
EXPECT_EC(decode<CompactInteger>(bytes), scale::DecodeError::NOT_ENOUGH_DATA);
}

/**
* @given redundant bytes in compact encoding
* @when decode compact
* @then error
*/
struct RedundantCompactTest : ::testing::TestWithParam<ByteArray> {};
TEST_P(RedundantCompactTest, DecodeError) {
EXPECT_EC(scale::decode<CompactInteger>(GetParam()),
scale::DecodeError::REDUNDANT_COMPACT_ENCODING);
}
INSTANTIATE_TEST_SUITE_P(
RedundantCompactTestCases,
RedundantCompactTest,
::testing::Values(ByteArray{0b100000'01, 0},
ByteArray{0b000000'10, 0b10000000, 0, 0},
ByteArray{0b000000'11, 0, 0, 0, 0b00'100000},
ByteArray{0b000001'11, 0, 0, 0, 0b01'000000, 0}));

0 comments on commit e1a3c7a

Please sign in to comment.