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