mirror of
https://github.com/shadowsocks/shadowsocks-libev.git
synced 2026-10-28 19:53:46 +00:00
Do not memcpy from an empty span in the stream decoder
An empty read before the IV arrived passed a null source to memcpy, which UBSan reports (and the ASan CI job turns into a failure).
This commit is contained in:
@@ -217,7 +217,9 @@ Result<StreamTcpDecryptor::Step> StreamTcpDecryptor::decrypt(std::span<const std
|
||||
if (!ready_) {
|
||||
std::size_t want = key_.spec.iv_len - iv_have_;
|
||||
std::size_t take = std::min(want, in.size());
|
||||
std::memcpy(iv_.data() + iv_have_, in.data(), take);
|
||||
if (take != 0) { // an empty span may have a null data()
|
||||
std::memcpy(iv_.data() + iv_have_, in.data(), take);
|
||||
}
|
||||
iv_have_ += take;
|
||||
step.consumed += take;
|
||||
in = in.subspan(take);
|
||||
|
||||
@@ -179,6 +179,9 @@ void replay(const sc::StreamKey &key)
|
||||
std::uint8_t out[16];
|
||||
sc::StreamTcpDecryptor first, second;
|
||||
SS_CHECK(first.init(key, seen.filter()) && second.init(key, seen.filter()));
|
||||
// An empty read before the IV arrives is a no-op.
|
||||
auto none = first.decrypt(std::span<const std::uint8_t>(), out);
|
||||
SS_CHECK(none && none->consumed == 0 && none->produced == 0 && !first.iv_received());
|
||||
// The IV alone is enough to register it.
|
||||
auto step = first.decrypt(std::span<const std::uint8_t>(wire.data(), key.spec.iv_len), out);
|
||||
SS_CHECK(step && step->produced == 0 && first.iv_received());
|
||||
|
||||
Reference in New Issue
Block a user