1 /* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23 #include "event_reader.h"
24 #include <string>
25 #include "mysql_com.h" // net_field_length_ll, net_field_length_size
26
27 namespace binary_log {
28
set_error(const char * error)29 void Event_reader::set_error(const char *error) {
30 BAPI_ASSERT(error != nullptr);
31 BAPI_PRINT("debug", ("Event_reader::set_error(%s)", error));
32 m_error = error;
33 }
34
set_length(unsigned long long length)35 void Event_reader::set_length(unsigned long long length) {
36 PRINT_READER_STATUS("Event_reader::set_length");
37 if (length < m_length) {
38 BAPI_PRINT("debug", ("Event_reader::set_length(%llu)", length));
39 set_error("Buffer length cannot shrink");
40 } else {
41 m_limit = m_length = length;
42 }
43 }
44
shrink_limit(unsigned long long bytes)45 void Event_reader::shrink_limit(unsigned long long bytes) {
46 PRINT_READER_STATUS("Event_reader::shrink_limit");
47 if (bytes > m_limit || position() > m_limit - bytes) {
48 BAPI_PRINT("debug", ("Event_reader::shrink_limit(%llu)", bytes));
49 set_error("Unable to shrink buffer limit");
50 } else
51 m_limit = m_limit - bytes;
52 }
53
ptr(unsigned long long length)54 const char *Event_reader::ptr(unsigned long long length) {
55 PRINT_READER_STATUS("Event_reader::ptr");
56 BAPI_PRINT("debug", ("Event_reader::ptr(%llu)", length));
57 if (!can_read(length)) {
58 set_error("Cannot point to out of buffer bounds");
59 return nullptr;
60 }
61 const char *ret_ptr = m_ptr;
62 m_ptr = m_ptr + length;
63 return ret_ptr;
64 }
65
go_to(unsigned long long position)66 const char *Event_reader::go_to(unsigned long long position) {
67 PRINT_READER_STATUS("Event_reader::go_to");
68 if (position >= m_limit) {
69 BAPI_PRINT("debug", ("Event_reader::go_to(%llu)", position));
70 set_error("Cannot point to out of buffer bounds");
71 return nullptr;
72 }
73 m_ptr = m_buffer + position;
74 return m_ptr;
75 }
76
alloc_and_memcpy(unsigned char ** destination,size_t length,int flags)77 void Event_reader::alloc_and_memcpy(unsigned char **destination, size_t length,
78 int flags) {
79 PRINT_READER_STATUS("Event_reader::alloc_and_memcpy");
80 if (!can_read(length)) {
81 BAPI_PRINT("debug", ("Event_reader::alloc_and_copy(%zu)", length));
82 set_error("Cannot read from out of buffer bounds");
83 return;
84 }
85 BAPI_ASSERT(*destination == nullptr);
86 *destination = static_cast<unsigned char *>(bapi_malloc(length, flags));
87 if (!*destination) {
88 BAPI_PRINT("debug", ("Event_reader::alloc_and_copy(%zu)", length));
89 set_error("Out of memory");
90 return;
91 }
92 ::memcpy(*destination, m_ptr, length);
93 m_ptr = m_ptr + length;
94 }
95
alloc_and_strncpy(char ** destination,size_t length,int flags)96 void Event_reader::alloc_and_strncpy(char **destination, size_t length,
97 int flags) {
98 PRINT_READER_STATUS("Event_reader::alloc_and_strncpy");
99 if (!can_read(length)) {
100 BAPI_PRINT("debug", ("Event_reader::alloc_and_strncpy(%zu)", length));
101 set_error("Cannot read from out of buffer bounds");
102 return;
103 }
104 BAPI_ASSERT(*destination == nullptr);
105 *destination = static_cast<char *>(bapi_malloc(length + 1, flags));
106 if (!*destination) {
107 BAPI_PRINT("debug", ("Event_reader::alloc_and_strncpy(%zu)", length));
108 set_error("Out of memory");
109 return;
110 }
111 strncpy(*destination, m_ptr, length);
112 (*destination)[length] = '\0';
113 m_ptr = m_ptr + length;
114 }
115
read_str_at_most_255_bytes(const char ** destination,uint8_t * lenght)116 void Event_reader::read_str_at_most_255_bytes(const char **destination,
117 uint8_t *lenght) {
118 PRINT_READER_STATUS("Event_reader::read_str_at_most_255_bytes");
119 if (!can_read(sizeof(uint8_t))) {
120 set_error("Cannot read from out of buffer bounds");
121 return;
122 }
123 ::memcpy(lenght, m_ptr, sizeof(uint8_t));
124 m_ptr = m_ptr + sizeof(uint8_t);
125
126 BAPI_PRINT("debug",
127 ("Event_reader::read_str_at_most_255_bytes(%u)", *lenght));
128 if (!can_read(*lenght)) {
129 set_error("Cannot read from out of buffer bounds");
130 return;
131 }
132 *destination = m_ptr;
133 m_ptr = m_ptr + *lenght;
134 }
135
net_field_length_ll()136 uint64_t Event_reader::net_field_length_ll() {
137 PRINT_READER_STATUS("Event_reader::net_field_length_ll");
138 if (!can_read(sizeof(uint8_t))) {
139 set_error("Cannot read from out of buffer bounds");
140 return 0;
141 }
142 // It is safe to read the first byte of the transaction_length
143 unsigned char *ptr_length;
144 ptr_length = reinterpret_cast<unsigned char *>(const_cast<char *>(m_ptr));
145 unsigned int length_size = net_field_length_size(ptr_length);
146 BAPI_PRINT("debug", ("Event_reader::read_net_field_length_ll(): "
147 "expect to read length with %u byte(s)",
148 length_size));
149 if (!can_read(length_size)) {
150 set_error("Cannot read from out of buffer bounds");
151 return 0;
152 }
153 // It is safe to read the full transaction_length from the buffer
154 uint64_t value = ::net_field_length_ll(&ptr_length);
155 m_ptr = m_ptr + length_size;
156 return value;
157 }
158
read_data_set(uint32_t set_len,std::list<const char * > * set)159 void Event_reader::read_data_set(uint32_t set_len,
160 std::list<const char *> *set) {
161 PRINT_READER_STATUS("Event_reader::read_data_set");
162 uint16_t len = 0;
163 for (uint32_t i = 0; i < set_len; i++) {
164 len = read_and_letoh<uint16_t>();
165 if (m_error) break;
166 const char *hash = strndup<const char *>(len);
167 if (m_error) break;
168 set->push_back(hash);
169 }
170 }
171
read_data_map(uint32_t map_len,std::map<std::string,std::string> * map)172 void Event_reader::read_data_map(uint32_t map_len,
173 std::map<std::string, std::string> *map) {
174 PRINT_READER_STATUS("Event_reader::read_data_map");
175 BAPI_ASSERT(map->empty());
176 for (uint32_t i = 0; i < map_len; i++) {
177 uint16_t key_len = read_and_letoh<uint16_t>();
178 if (m_error) break;
179 if (!can_read(key_len)) {
180 set_error("Cannot read from out of buffer bounds");
181 break;
182 }
183 std::string key(m_ptr, key_len);
184 m_ptr += key_len;
185
186 uint32_t value_len = read_and_letoh<uint32_t>();
187 if (m_error) break;
188 if (!can_read(value_len)) {
189 set_error("Cannot read from out of buffer bounds");
190 break;
191 }
192 std::string value(m_ptr, value_len);
193 m_ptr += value_len;
194
195 (*map)[key] = value;
196 }
197 }
198
strncpyz(char * destination,size_t max_length,size_t dest_length)199 void Event_reader::strncpyz(char *destination, size_t max_length,
200 size_t dest_length) {
201 PRINT_READER_STATUS("Event_reader::strncpyz");
202 if (!can_read(max_length)) {
203 BAPI_PRINT("debug",
204 ("Event_reader::strncpy(%zu, %zu)", max_length, dest_length));
205 set_error("Cannot read from out of buffer bounds");
206 return;
207 }
208 strncpy(destination, m_ptr, max_length);
209 destination[dest_length - 1] = 0;
210 m_ptr = m_ptr + strlen(destination) + 1;
211 }
212
assign(std::vector<uint8_t> * vector,size_t length)213 void Event_reader::assign(std::vector<uint8_t> *vector, size_t length) {
214 PRINT_READER_STATUS("Event_reader::assign");
215 BAPI_ASSERT(vector->empty());
216 if (!can_read(length)) {
217 set_error("Cannot read from out of buffer bounds");
218 return;
219 }
220 try {
221 vector->assign(m_ptr, m_ptr + length);
222 } catch (const std::bad_alloc &e) {
223 vector->clear();
224 set_error("std::bad_alloc");
225 }
226 BAPI_ASSERT(vector->size() == length);
227 m_ptr = m_ptr + length;
228 }
229 } // end namespace binary_log
230