codecs.cpp 4.0 KB

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