codecs.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. #include "codecs.h"
  2. #include "common.h"
  3. #include "register.h"
  4. #include <util/stream/null.h>
  5. #include <util/string/join.h>
  6. #include <util/system/align.h>
  7. #include <util/system/unaligned_mem.h>
  8. #include <util/generic/hash.h>
  9. #include <util/generic/deque.h>
  10. #include <util/generic/buffer.h>
  11. #include <util/generic/array_ref.h>
  12. #include <util/generic/singleton.h>
  13. #include <util/generic/algorithm.h>
  14. #include <util/generic/mem_copy.h>
  15. using namespace NBlockCodecs;
  16. namespace {
  17. struct TCodecFactory {
  18. inline TCodecFactory() {
  19. Add(&Null);
  20. }
  21. inline const ICodec* Find(const TStringBuf& name) const {
  22. auto it = Registry.find(name);
  23. if (it == Registry.end()) {
  24. ythrow TNotFound() << "can not found " << name << " codec";
  25. }
  26. return it->second;
  27. }
  28. inline void ListCodecs(TCodecList& lst) const {
  29. for (const auto& it : Registry) {
  30. lst.push_back(it.first);
  31. }
  32. Sort(lst.begin(), lst.end());
  33. }
  34. inline void Add(ICodec* codec) {
  35. Registry[codec->Name()] = codec;
  36. }
  37. inline void Add(TCodecPtr codec) {
  38. Codecs.push_back(std::move(codec));
  39. Add(Codecs.back().Get());
  40. }
  41. inline void Alias(TStringBuf from, TStringBuf to) {
  42. Tmp.emplace_back(from);
  43. Registry[Tmp.back()] = Registry[to];
  44. }
  45. TDeque<TString> Tmp;
  46. TNullCodec Null;
  47. TVector<TCodecPtr> Codecs;
  48. typedef THashMap<TStringBuf, ICodec*> TRegistry;
  49. TRegistry Registry;
  50. // SEARCH-8344: Global decompressed size limiter (to prevent remote DoS)
  51. size_t MaxPossibleDecompressedLength = Max<size_t>();
  52. };
  53. }
  54. const ICodec* NBlockCodecs::Codec(const TStringBuf& name) {
  55. return Singleton<TCodecFactory>()->Find(name);
  56. }
  57. TCodecList NBlockCodecs::ListAllCodecs() {
  58. TCodecList ret;
  59. Singleton<TCodecFactory>()->ListCodecs(ret);
  60. return ret;
  61. }
  62. TString NBlockCodecs::ListAllCodecsAsString() {
  63. return JoinSeq(TStringBuf(","), ListAllCodecs());
  64. }
  65. void NBlockCodecs::RegisterCodec(TCodecPtr codec) {
  66. Singleton<TCodecFactory>()->Add(std::move(codec));
  67. }
  68. void NBlockCodecs::RegisterAlias(TStringBuf from, TStringBuf to) {
  69. Singleton<TCodecFactory>()->Alias(from, to);
  70. }
  71. void NBlockCodecs::SetMaxPossibleDecompressedLength(size_t maxPossibleDecompressedLength) {
  72. Singleton<TCodecFactory>()->MaxPossibleDecompressedLength = maxPossibleDecompressedLength;
  73. }
  74. size_t NBlockCodecs::GetMaxPossibleDecompressedLength() {
  75. return Singleton<TCodecFactory>()->MaxPossibleDecompressedLength;
  76. }
  77. size_t ICodec::GetDecompressedLength(const TData& in) const {
  78. const size_t len = DecompressedLength(in);
  79. Y_ENSURE(
  80. len <= NBlockCodecs::GetMaxPossibleDecompressedLength(),
  81. "Attempt to decompress the block that is larger than maximum possible decompressed length, "
  82. "see SEARCH-8344 for details. "
  83. );
  84. return len;
  85. }
  86. void ICodec::Encode(const TData& in, TBuffer& out) const {
  87. const size_t maxLen = MaxCompressedLength(in);
  88. out.Reserve(maxLen);
  89. out.Resize(Compress(in, out.Data()));
  90. }
  91. void ICodec::Decode(const TData& in, TBuffer& out) const {
  92. const size_t len = GetDecompressedLength(in);
  93. out.Reserve(len);
  94. out.Resize(Decompress(in, out.Data()));
  95. }
  96. void ICodec::Encode(const TData& in, TString& out) const {
  97. const size_t maxLen = MaxCompressedLength(in);
  98. out.ReserveAndResize(maxLen);
  99. size_t actualLen = Compress(in, out.begin());
  100. Y_ASSERT(actualLen <= maxLen);
  101. out.resize(actualLen);
  102. }
  103. void ICodec::Decode(const TData& in, TString& out) const {
  104. const size_t maxLen = GetDecompressedLength(in);
  105. out.ReserveAndResize(maxLen);
  106. size_t actualLen = Decompress(in, out.begin());
  107. Y_ASSERT(actualLen <= maxLen);
  108. out.resize(actualLen);
  109. }
  110. ICodec::~ICodec() = default;