Coverage Report

Created: 2024-09-19 09:45

/proc/self/cwd/source/common/grpc/codec.cc
Line
Count
Source (jump to first uncovered line)
1
#include "source/common/grpc/codec.h"
2
3
#include <array>
4
#include <cstdint>
5
#include <memory>
6
#include <vector>
7
8
#include "source/common/buffer/buffer_impl.h"
9
10
#include "absl/container/fixed_array.h"
11
12
namespace Envoy {
13
namespace Grpc {
14
15
1.12k
Encoder::Encoder() = default;
16
17
1.12k
void Encoder::newFrame(uint8_t flags, uint64_t length, std::array<uint8_t, 5>& output) {
18
1.12k
  output[0] = flags;
19
1.12k
  absl::big_endian::Store32(&output[1], length);
20
1.12k
}
21
22
0
void Encoder::prependFrameHeader(uint8_t flags, Buffer::Instance& buffer) {
23
0
  prependFrameHeader(flags, buffer, buffer.length());
24
0
}
25
26
1
void Encoder::prependFrameHeader(uint8_t flags, Buffer::Instance& buffer, uint32_t message_length) {
27
  // Compute the size of the payload and construct the length prefix.
28
1
  std::array<uint8_t, Grpc::GRPC_FRAME_HEADER_SIZE> frame;
29
1
  Grpc::Encoder().newFrame(flags, message_length, frame);
30
1
  Buffer::OwnedImpl frame_buffer(frame.data(), frame.size());
31
1
  buffer.prepend(frame_buffer);
32
1
}
33
34
16.9k
absl::Status Decoder::decode(Buffer::Instance& input, std::vector<Frame>& output) {
35
  // Make sure those flags are set to initial state.
36
16.9k
  decoding_error_ = false;
37
16.9k
  is_frame_oversized_ = false;
38
16.9k
  output_ = &output;
39
16.9k
  inspect(input);
40
16.9k
  output_ = nullptr;
41
42
16.9k
  if (decoding_error_) {
43
634
    return absl::InternalError("Grpc decoding error");
44
634
  }
45
46
16.2k
  if (is_frame_oversized_) {
47
0
    return absl::ResourceExhaustedError("Grpc frame length exceeds limit");
48
0
  }
49
50
16.2k
  input.drain(input.length());
51
16.2k
  return absl::OkStatus();
52
16.2k
}
53
54
50.9k
bool Decoder::frameStart(uint8_t flags) {
55
  // Unsupported flags.
56
50.9k
  if (flags & ~GRPC_FH_COMPRESSED) {
57
634
    decoding_error_ = true;
58
634
    return false;
59
634
  }
60
50.3k
  frame_.flags_ = flags;
61
50.3k
  return true;
62
50.9k
}
63
64
49.6k
void Decoder::frameDataStart() {
65
49.6k
  frame_.length_ = length_;
66
49.6k
  frame_.data_ = std::make_unique<Buffer::OwnedImpl>();
67
49.6k
}
68
69
10.5k
void Decoder::frameData(uint8_t* mem, uint64_t length) { frame_.data_->add(mem, length); }
70
71
48.8k
void Decoder::frameDataEnd() {
72
48.8k
  output_->push_back(std::move(frame_));
73
48.8k
  frame_.flags_ = 0;
74
48.8k
  frame_.length_ = 0;
75
48.8k
  frame_.data_ = nullptr;
76
48.8k
}
77
78
17.2k
uint64_t FrameInspector::inspect(const Buffer::Instance& data) {
79
17.2k
  uint64_t delta = 0;
80
17.2k
  for (const Buffer::RawSlice& slice : data.getRawSlices()) {
81
14.0k
    uint8_t* mem = reinterpret_cast<uint8_t*>(slice.mem_);
82
14.0k
    uint8_t* end = mem + slice.len_;
83
275k
    while (mem < end) {
84
261k
      uint8_t c = *mem;
85
261k
      switch (state_) {
86
50.9k
      case State::FhFlag:
87
50.9k
        if (!frameStart(c)) {
88
634
          return delta;
89
634
        }
90
50.3k
        count_ += 1;
91
50.3k
        delta += 1;
92
50.3k
        state_ = State::FhLen0;
93
50.3k
        mem++;
94
50.3k
        break;
95
50.1k
      case State::FhLen0:
96
50.1k
        length_as_bytes_[0] = c;
97
50.1k
        state_ = State::FhLen1;
98
50.1k
        mem++;
99
50.1k
        break;
100
50.1k
      case State::FhLen1:
101
50.1k
        length_as_bytes_[1] = c;
102
50.1k
        state_ = State::FhLen2;
103
50.1k
        mem++;
104
50.1k
        break;
105
50.1k
      case State::FhLen2:
106
50.1k
        length_as_bytes_[2] = c;
107
50.1k
        state_ = State::FhLen3;
108
50.1k
        mem++;
109
50.1k
        break;
110
49.6k
      case State::FhLen3:
111
49.6k
        length_as_bytes_[3] = c;
112
49.6k
        length_ = absl::big_endian::Load32(length_as_bytes_);
113
        // Compares the frame length against maximum length when `max_frame_length_` is configured,
114
49.6k
        if (max_frame_length_ != 0 && length_ > max_frame_length_) {
115
          // Set the flag to indicate the over-limit error and return.
116
0
          is_frame_oversized_ = true;
117
0
          return delta;
118
0
        }
119
49.6k
        frameDataStart();
120
49.6k
        if (length_ == 0) {
121
44.3k
          frameDataEnd();
122
44.3k
          state_ = State::FhFlag;
123
44.3k
        } else {
124
5.36k
          state_ = State::Data;
125
5.36k
        }
126
49.6k
        mem++;
127
49.6k
        break;
128
10.5k
      case State::Data:
129
10.5k
        uint64_t remain_in_buffer = end - mem;
130
10.5k
        if (remain_in_buffer <= length_) {
131
8.36k
          frameData(mem, remain_in_buffer);
132
8.36k
          mem += remain_in_buffer;
133
8.36k
          length_ -= remain_in_buffer;
134
8.36k
        } else {
135
2.18k
          frameData(mem, length_);
136
2.18k
          mem += length_;
137
2.18k
          length_ = 0;
138
2.18k
        }
139
10.5k
        if (length_ == 0) {
140
4.60k
          frameDataEnd();
141
4.60k
          state_ = State::FhFlag;
142
4.60k
        }
143
10.5k
        break;
144
261k
      }
145
261k
    }
146
14.0k
  }
147
16.5k
  return delta;
148
17.2k
}
149
150
} // namespace Grpc
151
} // namespace Envoy