1 /* Copyright (c) 2008, 2017, 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 Foundation,
21   51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
22 
23 #include <my_global.h>
24 #include <my_pthread.h>
25 #include <pfs_server.h>
26 #include <pfs_instr_class.h>
27 #include <pfs_instr.h>
28 #include <pfs_global.h>
29 #include <tap.h>
30 
31 
32 #include <string.h>
33 #include <memory.h>
34 
35 /* test helpers, to inspect data */
36 bool read_nth_attr(const char *connect_attrs, uint connect_attrs_length,
37                           const CHARSET_INFO *connect_attrs_cs,
38                           uint ordinal,
39                           char *attr_name, uint max_attr_name,
40                           uint *attr_name_length,
41                           char *attr_value, uint max_attr_value,
42                           uint *attr_value_length);
43 
test_blob_parser()44 void test_blob_parser()
45 {
46   char name[100], value[4096];
47   unsigned char packet[10000], *ptr;
48   uint name_len, value_len, idx, packet_length;
49   bool result;
50   const CHARSET_INFO *cs= &my_charset_utf8_bin;
51 
52   diag("test_blob_parser");
53 
54   result= read_nth_attr("", 0, cs, 0,
55                         name, 32, &name_len, value, 1024, &value_len);
56   ok(result == false, "zero length blob");
57 
58 
59   result= read_nth_attr("\x1", 1, cs, 0,
60                         name, 32, &name_len, value, 1024, &value_len);
61   ok(result == false, "invalid key length");
62 
63 
64   result= read_nth_attr("\x2k1\x1", 4, cs, 0,
65                         name, 32, &name_len, value, 1024, &value_len);
66   ok(result == false, "invalid value length");
67 
68 
69   result= read_nth_attr("\x2k1\x2v1", 6, cs, 0,
70                         name, 32, &name_len, value, 1024, &value_len);
71   ok(result == true, "one pair return");
72   ok(name_len == 2, "one pair attr name length");
73   ok(!strncmp(name, "k1", name_len), "one pair attr name");
74   ok(value_len == 2, "one pair value length");
75   ok(!strncmp(value, "v1", value_len), "one pair value");
76 
77   result= read_nth_attr("\x2k1\x2v1", 6, cs, 1,
78                         name, 32, &name_len, value, 1024, &value_len);
79   ok(result == false, "no second arg");
80 
81   result= read_nth_attr("\x2k1\x2v1\x2k2\x2v2", 12, cs, 1,
82                         name, 32, &name_len, value, 1024, &value_len);
83   ok(result == true, "two pairs return");
84   ok(name_len == 2, "two pairs attr name length");
85   ok(!strncmp(name, "k2", name_len), "two pairs attr name");
86   ok(value_len == 2, "two pairs value length");
87   ok(!strncmp(value, "v2", value_len), "two pairs value");
88 
89   result= read_nth_attr("\x2k1\xff\x2k2\x2v2", 12, cs, 1,
90                         name, 32, &name_len, value, 1024, &value_len);
91   ok(result == false, "two pairs first value bad return");
92 
93   result= read_nth_attr("\x2k1\x2v1\x2k2\x2v2", 10, cs, 1,
94                         name, 32, &name_len, value, 1024, &value_len);
95   ok(result == false, "two pairs wrong global length");
96 
97   result= read_nth_attr("\x21z123456789z123456789z123456789z12\x2v1", 37, cs, 0,
98                         name, 32, &name_len, value, 1024, &value_len);
99   ok(result == true, "attr name overflow");
100   ok(name_len == 32, "attr name overflow length");
101   ok(!strncmp(name, "z123456789z123456789z123456789z1", name_len),
102      "attr name overflow name");
103   ok(value_len == 2, "attr name overflow value length");
104   ok(!strncmp(value, "v1", value_len), "attr name overflow value");
105 
106   packet[0]= 2;
107   packet[1]= 'k';
108   packet[2]= '1';
109   ptr= net_store_length(packet + 3, 1025);
110   for (idx= 0; idx < 1025; idx++)
111     *ptr++= '0' + (idx % 10);
112   packet_length= (uint) (ptr - packet);
113   result= read_nth_attr((char *) packet, packet_length, cs, 0,
114                         name, 32, &name_len, value, 1024, &value_len);
115   ok(result == true, "attr value overflow");
116   ok(name_len == 2, "attr value overflow length");
117   ok(!strncmp(name, "k1", name_len), "attr value overflow name");
118   ok(value_len == 1024, "attr value overflow value length");
119   for (idx= 0; idx < 1024; idx++)
120   {
121     if (value[idx] != (char) ('0' + (idx % 10)))
122       break;
123   }
124   ok (idx == 1024, "attr value overflow value");
125 
126   result= read_nth_attr("\x21z123456789z123456789z123456789z12\x2v1\x2k2\x2v2",
127                         43, cs, 1,
128                         name, 32, &name_len, value, 1024, &value_len);
129   ok(result == true, "prev attr name overflow");
130   ok(name_len == 2, "prev attr name overflow length");
131   ok(!strncmp(name, "k2", name_len),
132      "prev attr name overflow name");
133   ok(value_len == 2, "prev attr name overflow value length");
134   ok(!strncmp(value, "v2", value_len), "prev attr name overflow value");
135 
136 
137   packet[1]= 'k';
138   packet[2]= '1';
139   packet[3]= 2;
140   packet[4]= 'v';
141   packet[5]= '1';
142 
143   for(idx= 251; idx < 256; idx++)
144   {
145     packet[0]= idx;
146     result= read_nth_attr((char *) packet, 6, cs, 0,
147                           name, 32, &name_len, value, 1024, &value_len);
148     ok(result == false, "invalid string length %d", idx);
149   }
150 
151   memset(packet, 0, sizeof(packet));
152   for (idx=0; idx < 1660 /* *6 = 9960 */; idx++)
153     memcpy(packet + idx * 6, "\x2k1\x2v1", 6);
154   result= read_nth_attr((char *) packet, 8192, cs, 1364,
155                         name, 32, &name_len, value, 1024, &value_len);
156   ok(result == true, "last valid attribute %d", 1364);
157   result= read_nth_attr((char *) packet, 8192, cs, 1365,
158                         name, 32, &name_len, value, 1024, &value_len);
159   ok(result == false, "first attribute that's cut %d", 1365);
160 }
161 
test_multibyte_lengths()162 void test_multibyte_lengths()
163 {
164   char name[100], value[4096];
165   uint name_len, value_len;
166   bool result;
167   const CHARSET_INFO *cs= &my_charset_utf8_bin;
168 
169   unsigned char var_len_packet[] = {
170     252, 2, 0, 'k', '1',
171     253, 2, 0, 0, 'v', '1',
172     254, 2, 0, 0, 0, 0, 0, 0, 0, 'k', '2',
173     254, 2, 0, 0, 0, 0, 0, 0, 0, 'v', '2'
174   };
175 
176   result= read_nth_attr((char *) var_len_packet, sizeof(var_len_packet), cs, 0,
177                         name, 32, &name_len, value, 1024, &value_len);
178   ok(result == true, "multibyte lengths return");
179   ok(name_len == 2, "multibyte lengths name length");
180   ok(!strncmp(name, "k1", name_len), "multibyte lengths attr name");
181   ok(value_len == 2, "multibyte lengths value length");
182   ok(!strncmp(value, "v1", value_len), "multibyte lengths value");
183 
184   result= read_nth_attr((char *) var_len_packet, sizeof(var_len_packet), cs, 1,
185                         name, 32, &name_len, value, 1024, &value_len);
186   ok(result == true, "multibyte lengths second attr return");
187   ok(name_len == 2, "multibyte lengths second attr name length");
188   ok(!strncmp(name, "k2", name_len), "multibyte lengths second attr attr name");
189   ok(value_len == 2, "multibyte lengths value length");
190   ok(!strncmp(value, "v2", value_len), "multibyte lengths second attr value");
191 }
192 
193 
test_utf8_parser()194 void test_utf8_parser()
195 {
196   /* utf8 max byte length per character is 6 */
197   char name[33 * 6], value[1024 * 6], packet[1500 * 6], *ptr;
198   uint name_len, value_len;
199   bool result;
200   const CHARSET_INFO *cs= &my_charset_utf8_bin;
201 
202   /* note : this is encoded in utf-8 */
203   const char *attr1= "Георги";
204   const char *val1= "Кодинов";
205   const char *attr2= "Пловдив";
206   const char *val2= "България";
207 
208   ptr= packet;
209   *ptr++= strlen(attr1);
210   memcpy(ptr, attr1, strlen(attr1));
211   ptr+= strlen(attr1);
212   *ptr++= strlen(val1);
213   memcpy(ptr, val1, strlen(val1));
214   ptr+= strlen(val1);
215 
216   *ptr++= strlen(attr2);
217   memcpy(ptr, attr2, strlen(attr2));
218   ptr+= strlen(attr2);
219   *ptr++= strlen(val2);
220   memcpy(ptr, val2, strlen(val2));
221   ptr+= strlen(val2);
222 
223   diag("test_utf8_parser attr pair #1");
224 
225   result= read_nth_attr((char *) packet, ptr - packet, cs, 0,
226                         name, sizeof(name), &name_len,
227                         value, sizeof(value), &value_len);
228   ok(result == true, "return");
229   ok(name_len == strlen(attr1), "name length");
230   ok(!strncmp(name, attr1, name_len), "attr name");
231   ok(value_len == strlen(val1), "value length");
232   ok(!strncmp(value, val1, value_len), "value");
233 
234   diag("test_utf8_parser attr pair #2");
235   result= read_nth_attr((char *) packet, ptr - packet, cs, 1,
236                         name, sizeof(name), &name_len,
237                         value, sizeof(value), &value_len);
238   ok(result == true, "return");
239   ok(name_len == strlen(attr2), "name length");
240   ok(!strncmp(name, attr2, name_len), "attr name");
241   ok(value_len == strlen(val2), "value length");
242   ok(!strncmp(value, val2, value_len), "value");
243 }
244 
245 
test_utf8_parser_bad_encoding()246 void test_utf8_parser_bad_encoding()
247 {
248   /* utf8 max byte length per character is 3*/
249   char name[33 * 3], value[1024 * 3], packet[1500 * 3], *ptr;
250   uint name_len, value_len;
251   bool result;
252   const CHARSET_INFO *cs= &my_charset_utf8_bin;
253 
254   /* note : this is encoded in utf-8 */
255   const char *attr= "Георги";
256   const char *val= "Кодинов";
257 
258   ptr= packet;
259   *ptr++= strlen(attr);
260   memcpy(ptr, attr, strlen(attr));
261   ptr[0]= 0xFA; // invalid UTF-8 char
262   ptr+= strlen(attr);
263   *ptr++= strlen(val);
264   memcpy(ptr, val, strlen(val));
265   ptr+= strlen(val);
266 
267   diag("test_utf8_parser_bad_encoding");
268 
269   result= read_nth_attr((char *) packet, ptr - packet, cs, 0,
270                         name, sizeof(name), &name_len,
271                         value, sizeof(value), &value_len);
272   ok(result == false, "return");
273 }
274 
275 const CHARSET_INFO *cs_cp1251;
276 
test_cp1251_parser()277 void test_cp1251_parser()
278 {
279   /* utf8 max byte length per character is 3*/
280   char name[33 * 3], value[1024 * 3], packet[1500 * 3], *ptr;
281   uint name_len, value_len;
282   bool result;
283 
284   /* note : this is Георги in windows-1251 */
285   const char *attr1= "\xc3\xe5\xee\xf0\xe3\xe8";
286   /* note : this is Кодинов in windows-1251 */
287   const char *val1= "\xca\xee\xe4\xe8\xed\xee\xe2";
288   /* note : this is Пловдив in windows-1251 */
289   const char *attr2= "\xcf\xeb\xee\xe2\xe4\xe8\xe2";
290   /* note : this is България in windows-1251 */
291   const char *val2= "\xc1\xfa\xeb\xe3\xe0\xf0\xe8\xff";
292 
293   ptr= packet;
294   *ptr++= strlen(attr1);
295   memcpy(ptr, attr1, strlen(attr1));
296   ptr+= strlen(attr1);
297   *ptr++= strlen(val1);
298   memcpy(ptr, val1, strlen(val1));
299   ptr+= strlen(val1);
300 
301   *ptr++= strlen(attr2);
302   memcpy(ptr, attr2, strlen(attr2));
303   ptr+= strlen(attr2);
304   *ptr++= strlen(val2);
305   memcpy(ptr, val2, strlen(val2));
306   ptr+= strlen(val2);
307 
308   diag("test_cp1251_parser attr pair #1");
309 
310   result= read_nth_attr((char *) packet, ptr - packet, cs_cp1251, 0,
311                         name, sizeof(name), &name_len,
312                         value, sizeof(value), &value_len);
313   ok(result == true, "return");
314   /* need to compare to the UTF-8 equivalents */
315   ok(name_len == strlen("Георги"), "name length");
316   ok(!strncmp(name, "Георги", name_len), "attr name");
317   ok(value_len == strlen("Кодинов"), "value length");
318   ok(!strncmp(value, "Кодинов", value_len), "value");
319 
320   diag("test_cp1251_parser attr pair #2");
321   result= read_nth_attr((char *) packet, ptr - packet, cs_cp1251, 1,
322                         name, sizeof(name), &name_len,
323                         value, sizeof(value), &value_len);
324   ok(result == true, "return");
325   /* need to compare to the UTF-8 equivalents */
326   ok(name_len == strlen("Пловдив"), "name length");
327   ok(!strncmp(name, "Пловдив", name_len), "attr name");
328   ok(value_len == strlen("България"), "value length");
329   ok(!strncmp(value, "България", value_len), "value");
330 }
331 
332 
do_all_tests()333 void do_all_tests()
334 {
335   test_blob_parser();
336   test_multibyte_lengths();
337   test_utf8_parser();
338   test_utf8_parser_bad_encoding();
339   test_cp1251_parser();
340 }
341 
main(int,char **)342 int main(int, char **)
343 {
344   MY_INIT("pfs_connect_attr-t");
345 
346   cs_cp1251= get_charset_by_csname("cp1251", MY_CS_PRIMARY, MYF(0));
347   if (!cs_cp1251)
348     diag("skipping the cp1251 tests : missing character set");
349   plan(59 + (cs_cp1251 ? 10 : 0));
350   do_all_tests();
351   return (exit_status());
352 }
353