/* Copyright (c) 2008, 2023, Oracle and/or its affiliates.
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License , version 2 . 0 ,
as published by the Free Software Foundation .
This program is also distributed with certain software ( including
but not limited to OpenSSL ) that is licensed under separate terms ,
as designated in a particular file or component or in included license
documentation . The authors of MySQL hereby grant you an additional
permission to link the program and your derivative works with the
separately licensed software that they have included with MySQL .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License , version 2 . 0 , for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software Foundation ,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
#include <my_global.h>
#include <my_thread.h>
#include <pfs_server.h>
#include <pfs_instr_class.h>
#include <pfs_instr.h>
#include <pfs_global.h>
#include <tap.h>
#include <string.h>
#include <memory.h>
/* test helpers, to inspect data */
bool read_nth_attr(const char *connect_attrs, uint connect_attrs_length,
const CHARSET_INFO *connect_attrs_cs,
uint ordinal,
char *attr_name, uint max_attr_name,
uint *attr_name_length,
char *attr_value, uint max_attr_value,
uint *attr_value_length);
void test_blob_parser()
{
char name[100 ], value[4096 ];
unsigned char packet[10000 ], *ptr;
uint name_len, value_len, idx, packet_length;
bool result;
const CHARSET_INFO *cs= &my_charset_utf8mb3_bin;
diag("test_blob_parser" );
result= read_nth_attr("" , 0 , cs, 0 ,
name, 32 , &name_len, value, 1024 , &value_len);
ok(result == false , "zero length blob" );
result= read_nth_attr("\x1" , 1 , cs, 0 ,
name, 32 , &name_len, value, 1024 , &value_len);
ok(result == false , "invalid key length" );
result= read_nth_attr("\x2k1\x1" , 4 , cs, 0 ,
name, 32 , &name_len, value, 1024 , &value_len);
ok(result == false , "invalid value length" );
result= read_nth_attr("\x2k1\x2v1" , 6 , cs, 0 ,
name, 32 , &name_len, value, 1024 , &value_len);
ok(result == true , "one pair return" );
ok(name_len == 2 , "one pair attr name length" );
ok(!strncmp(name, "k1" , name_len), "one pair attr name" );
ok(value_len == 2 , "one pair value length" );
ok(!strncmp(value, "v1" , value_len), "one pair value" );
result= read_nth_attr("\x2k1\x2v1" , 6 , cs, 1 ,
name, 32 , &name_len, value, 1024 , &value_len);
ok(result == false , "no second arg" );
result= read_nth_attr("\x2k1\x2v1\x2k2\x2v2" , 12 , cs, 1 ,
name, 32 , &name_len, value, 1024 , &value_len);
ok(result == true , "two pairs return" );
ok(name_len == 2 , "two pairs attr name length" );
ok(!strncmp(name, "k2" , name_len), "two pairs attr name" );
ok(value_len == 2 , "two pairs value length" );
ok(!strncmp(value, "v2" , value_len), "two pairs value" );
result= read_nth_attr("\x2k1\xff\x2k2\x2v2" , 12 , cs, 1 ,
name, 32 , &name_len, value, 1024 , &value_len);
ok(result == false , "two pairs first value bad return" );
result= read_nth_attr("\x2k1\x2v1\x2k2\x2v2" , 10 , cs, 1 ,
name, 32 , &name_len, value, 1024 , &value_len);
ok(result == false , "two pairs wrong global length" );
result= read_nth_attr("\x21z123456789z123456789z123456789z12\x2v1" , 37 , cs, 0 ,
name, 32 , &name_len, value, 1024 , &value_len);
ok(result == true , "attr name overflow" );
ok(name_len == 32 , "attr name overflow length" );
ok(!strncmp(name, "z123456789z123456789z123456789z1" , name_len),
"attr name overflow name" );
ok(value_len == 2 , "attr name overflow value length" );
ok(!strncmp(value, "v1" , value_len), "attr name overflow value" );
packet[0 ]= 2 ;
packet[1 ]= 'k' ;
packet[2 ]= '1' ;
ptr= net_store_length(packet + 3 , 1025 );
for (idx= 0 ; idx < 1025 ; idx++)
*ptr++= '0' + (idx % 10 );
packet_length= (uint) (ptr - packet);
result= read_nth_attr((char *) packet, packet_length, cs, 0 ,
name, 32 , &name_len, value, 1024 , &value_len);
ok(result == true , "attr value overflow" );
ok(name_len == 2 , "attr value overflow length" );
ok(!strncmp(name, "k1" , name_len), "attr value overflow name" );
ok(value_len == 1024 , "attr value overflow value length" );
for (idx= 0 ; idx < 1024 ; idx++)
{
if (value[idx] != (char ) ('0' + (idx % 10 )))
break ;
}
ok (idx == 1024 , "attr value overflow value" );
result= read_nth_attr("\x21z123456789z123456789z123456789z12\x2v1\x2k2\x2v2" ,
43 , cs, 1 ,
name, 32 , &name_len, value, 1024 , &value_len);
ok(result == true , "prev attr name overflow" );
ok(name_len == 2 , "prev attr name overflow length" );
ok(!strncmp(name, "k2" , name_len),
"prev attr name overflow name" );
ok(value_len == 2 , "prev attr name overflow value length" );
ok(!strncmp(value, "v2" , value_len), "prev attr name overflow value" );
packet[1 ]= 'k' ;
packet[2 ]= '1' ;
packet[3 ]= 2 ;
packet[4 ]= 'v' ;
packet[5 ]= '1' ;
for (idx= 251 ; idx < 256 ; idx++)
{
packet[0 ]= idx;
result= read_nth_attr((char *) packet, 6 , cs, 0 ,
name, 32 , &name_len, value, 1024 , &value_len);
ok(result == false , "invalid string length %d" , idx);
}
memset(packet, 0 , sizeof (packet));
for (idx=0 ; idx < 1660 /* *6 = 9960 */; idx++)
memcpy(packet + idx * 6 , "\x2k1\x2v1" , 6 );
result= read_nth_attr((char *) packet, 8192 , cs, 1364 ,
name, 32 , &name_len, value, 1024 , &value_len);
ok(result == true , "last valid attribute %d" , 1364 );
result= read_nth_attr((char *) packet, 8192 , cs, 1365 ,
name, 32 , &name_len, value, 1024 , &value_len);
ok(result == false , "first attribute that's cut %d" , 1365 );
}
void test_multibyte_lengths()
{
char name[100 ], value[4096 ];
uint name_len, value_len;
bool result;
const CHARSET_INFO *cs= &my_charset_utf8mb3_bin;
unsigned char var_len_packet[] = {
252 , 2 , 0 , 'k' , '1' ,
253 , 2 , 0 , 0 , 'v' , '1' ,
254 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 'k' , '2' ,
254 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 'v' , '2'
};
result= read_nth_attr((char *) var_len_packet, sizeof (var_len_packet), cs, 0 ,
name, 32 , &name_len, value, 1024 , &value_len);
ok(result == true , "multibyte lengths return" );
ok(name_len == 2 , "multibyte lengths name length" );
ok(!strncmp(name, "k1" , name_len), "multibyte lengths attr name" );
ok(value_len == 2 , "multibyte lengths value length" );
ok(!strncmp(value, "v1" , value_len), "multibyte lengths value" );
result= read_nth_attr((char *) var_len_packet, sizeof (var_len_packet), cs, 1 ,
name, 32 , &name_len, value, 1024 , &value_len);
ok(result == true , "multibyte lengths second attr return" );
ok(name_len == 2 , "multibyte lengths second attr name length" );
ok(!strncmp(name, "k2" , name_len), "multibyte lengths second attr attr name" );
ok(value_len == 2 , "multibyte lengths value length" );
ok(!strncmp(value, "v2" , value_len), "multibyte lengths second attr value" );
}
void test_utf8_parser()
{
/* utf8 max byte length per character is 6 */
char name[33 * 6 ], value[1024 * 6 ], packet[1500 * 6 ], *ptr;
uint name_len, value_len;
bool result;
const CHARSET_INFO *cs= &my_charset_utf8mb3_bin;
/* note : this is encoded in utf-8 */
const char *attr1= "Георги" ;
const char *val1= "Кодинов" ;
const char *attr2= "Пловдив" ;
const char *val2= "България" ;
ptr= packet;
*ptr++= strlen(attr1);
memcpy(ptr, attr1, strlen(attr1));
ptr+= strlen(attr1);
*ptr++= strlen(val1);
memcpy(ptr, val1, strlen(val1));
ptr+= strlen(val1);
*ptr++= strlen(attr2);
memcpy(ptr, attr2, strlen(attr2));
ptr+= strlen(attr2);
*ptr++= strlen(val2);
memcpy(ptr, val2, strlen(val2));
ptr+= strlen(val2);
diag("test_utf8_parser attr pair #1" );
result= read_nth_attr((char *) packet, ptr - packet, cs, 0 ,
name, sizeof (name), &name_len,
value, sizeof (value), &value_len);
ok(result == true , "return" );
ok(name_len == strlen(attr1), "name length" );
ok(!strncmp(name, attr1, name_len), "attr name" );
ok(value_len == strlen(val1), "value length" );
ok(!strncmp(value, val1, value_len), "value" );
diag("test_utf8_parser attr pair #2" );
result= read_nth_attr((char *) packet, ptr - packet, cs, 1 ,
name, sizeof (name), &name_len,
value, sizeof (value), &value_len);
ok(result == true , "return" );
ok(name_len == strlen(attr2), "name length" );
ok(!strncmp(name, attr2, name_len), "attr name" );
ok(value_len == strlen(val2), "value length" );
ok(!strncmp(value, val2, value_len), "value" );
}
void test_utf8_parser_bad_encoding()
{
/* utf8 max byte length per character is 3*/
char name[33 * 3 ], value[1024 * 3 ], packet[1500 * 3 ], *ptr;
uint name_len, value_len;
bool result;
const CHARSET_INFO *cs= &my_charset_utf8mb3_bin;
/* note : this is encoded in utf-8 */
const char *attr= "Георги" ;
const char *val= "Кодинов" ;
ptr= packet;
*ptr++= strlen(attr);
memcpy(ptr, attr, strlen(attr));
ptr[0 ]= (char )0 xFA; // invalid UTF-8 char
ptr+= strlen(attr);
*ptr++= strlen(val);
memcpy(ptr, val, strlen(val));
ptr+= strlen(val);
diag("test_utf8_parser_bad_encoding" );
result= read_nth_attr((char *) packet, ptr - packet, cs, 0 ,
name, sizeof (name), &name_len,
value, sizeof (value), &value_len);
ok(result == false , "return" );
}
const CHARSET_INFO *cs_cp1251;
void test_cp1251_parser()
{
/* utf8 max byte length per character is 3*/
char name[33 * 3 ], value[1024 * 3 ], packet[1500 * 3 ], *ptr;
uint name_len, value_len;
bool result;
/* note : this is Георги in windows-1251 */
const char *attr1= "\xc3\xe5\xee\xf0\xe3\xe8" ;
/* note : this is Кодинов in windows-1251 */
const char *val1= "\xca\xee\xe4\xe8\xed\xee\xe2" ;
/* note : this is Пловдив in windows-1251 */
const char *attr2= "\xcf\xeb\xee\xe2\xe4\xe8\xe2" ;
/* note : this is България in windows-1251 */
const char *val2= "\xc1\xfa\xeb\xe3\xe0\xf0\xe8\xff" ;
ptr= packet;
*ptr++= strlen(attr1);
memcpy(ptr, attr1, strlen(attr1));
ptr+= strlen(attr1);
*ptr++= strlen(val1);
memcpy(ptr, val1, strlen(val1));
ptr+= strlen(val1);
*ptr++= strlen(attr2);
memcpy(ptr, attr2, strlen(attr2));
ptr+= strlen(attr2);
*ptr++= strlen(val2);
memcpy(ptr, val2, strlen(val2));
ptr+= strlen(val2);
diag("test_cp1251_parser attr pair #1" );
result= read_nth_attr((char *) packet, ptr - packet, cs_cp1251, 0 ,
name, sizeof (name), &name_len,
value, sizeof (value), &value_len);
ok(result == true , "return" );
/* need to compare to the UTF-8 equivalents */
ok(name_len == strlen("Георги" ), "name length" );
ok(!strncmp(name, "Георги" , name_len), "attr name" );
ok(value_len == strlen("Кодинов" ), "value length" );
ok(!strncmp(value, "Кодинов" , value_len), "value" );
diag("test_cp1251_parser attr pair #2" );
result= read_nth_attr((char *) packet, ptr - packet, cs_cp1251, 1 ,
name, sizeof (name), &name_len,
value, sizeof (value), &value_len);
ok(result == true , "return" );
/* need to compare to the UTF-8 equivalents */
ok(name_len == strlen("Пловдив" ), "name length" );
ok(!strncmp(name, "Пловдив" , name_len), "attr name" );
ok(value_len == strlen("България" ), "value length" );
ok(!strncmp(value, "България" , value_len), "value" );
}
void do_all_tests()
{
test_blob_parser();
test_multibyte_lengths();
test_utf8_parser();
test_utf8_parser_bad_encoding();
test_cp1251_parser();
}
int main(int , char **)
{
MY_INIT("pfs_connect_attr-t" );
cs_cp1251= get_charset_by_csname("cp1251" , MY_CS_PRIMARY, MYF(0 ));
if (!cs_cp1251)
diag("skipping the cp1251 tests : missing character set" );
plan(59 + (cs_cp1251 ? 10 : 0 ));
do_all_tests();
return (exit_status());
}
Messung V0.5 in Prozent C=96 H=93 G=94
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-10-08)
¤
*© Formatika GbR, Deutschland