• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "logging/rtc_event_log/encoder/blob_encoding.h"
12 
13 #include <cstdint>
14 
15 #include "logging/rtc_event_log/encoder/var_int.h"
16 #include "rtc_base/checks.h"
17 #include "rtc_base/logging.h"
18 
19 namespace webrtc {
20 
EncodeBlobs(const std::vector<std::string> & blobs)21 std::string EncodeBlobs(const std::vector<std::string>& blobs) {
22   RTC_DCHECK(!blobs.empty());
23 
24   size_t result_length_bound = kMaxVarIntLengthBytes * blobs.size();
25   for (const auto& blob : blobs) {
26     // Providing an input so long that it would cause a wrap-around is an error.
27     RTC_DCHECK_GE(result_length_bound + blob.length(), result_length_bound);
28     result_length_bound += blob.length();
29   }
30 
31   std::string result;
32   result.reserve(result_length_bound);
33 
34   // First, encode all of the lengths.
35   for (absl::string_view blob : blobs) {
36     result += EncodeVarInt(blob.length());
37   }
38 
39   // Second, encode the actual blobs.
40   for (absl::string_view blob : blobs) {
41     result.append(blob.data(), blob.length());
42   }
43 
44   RTC_DCHECK_LE(result.size(), result_length_bound);
45   return result;
46 }
47 
DecodeBlobs(absl::string_view encoded_blobs,size_t num_of_blobs)48 std::vector<absl::string_view> DecodeBlobs(absl::string_view encoded_blobs,
49                                            size_t num_of_blobs) {
50   if (encoded_blobs.empty()) {
51     RTC_LOG(LS_WARNING) << "Corrupt input; empty input.";
52     return std::vector<absl::string_view>();
53   }
54 
55   if (num_of_blobs == 0u) {
56     RTC_LOG(LS_WARNING)
57         << "Corrupt input; number of blobs must be greater than 0.";
58     return std::vector<absl::string_view>();
59   }
60 
61   size_t read_idx = 0;
62 
63   // Read the lengths of all blobs.
64   std::vector<uint64_t> lengths(num_of_blobs);
65   for (size_t i = 0; i < num_of_blobs; ++i) {
66     if (read_idx >= encoded_blobs.length()) {
67       RTC_DCHECK_EQ(read_idx, encoded_blobs.length());
68       RTC_LOG(LS_WARNING) << "Corrupt input; excessive number of blobs.";
69       return std::vector<absl::string_view>();
70     }
71 
72     const size_t read_bytes =
73         DecodeVarInt(encoded_blobs.substr(read_idx), &lengths[i]);
74     if (read_bytes == 0) {
75       RTC_LOG(LS_WARNING) << "Corrupt input; varint decoding failed.";
76       return std::vector<absl::string_view>();
77     }
78 
79     read_idx += read_bytes;
80 
81     // Note: It might be that read_idx == encoded_blobs.length(), if this
82     // is the last iteration, and all of the blobs are the empty string.
83     RTC_DCHECK_LE(read_idx, encoded_blobs.length());
84   }
85 
86   // Read the blobs themselves.
87   std::vector<absl::string_view> blobs(num_of_blobs);
88   for (size_t i = 0; i < num_of_blobs; ++i) {
89     if (read_idx + lengths[i] < read_idx) {  // Wrap-around detection.
90       RTC_LOG(LS_WARNING) << "Corrupt input; unreasonably large blob sequence.";
91       return std::vector<absl::string_view>();
92     }
93 
94     if (read_idx + lengths[i] > encoded_blobs.length()) {
95       RTC_LOG(LS_WARNING) << "Corrupt input; blob sizes exceed input size.";
96       return std::vector<absl::string_view>();
97     }
98 
99     blobs[i] = encoded_blobs.substr(read_idx, lengths[i]);
100     read_idx += lengths[i];
101   }
102 
103   if (read_idx != encoded_blobs.length()) {
104     RTC_LOG(LS_WARNING) << "Corrupt input; unrecognized trailer.";
105     return std::vector<absl::string_view>();
106   }
107 
108   return blobs;
109 }
110 
111 }  // namespace webrtc
112