mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
MDEV-27612 Connect : check buffer sizes, fix string format errors
This commit is contained in:
parent
b9623383cc
commit
2925d0f2ee
13 changed files with 280 additions and 17 deletions
|
@ -201,7 +201,7 @@ my_bool BJNX::SetArrayOptions(PGLOBAL g, char* p, int i, PSZ nm)
|
|||
p[--n] = 0;
|
||||
} else if (!IsNum(p)) {
|
||||
// Wrong array specification
|
||||
sprintf(g->Message, "Invalid array specification %s", p);
|
||||
snprintf(g->Message, sizeof(g->Message), "Invalid array specification %s", p);
|
||||
return true;
|
||||
} // endif p
|
||||
|
||||
|
|
|
@ -5707,10 +5707,10 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
|
|||
if (ttp == TAB_UNDEF && !topt->http) {
|
||||
topt->type= (src) ? "MYSQL" : (tab) ? "PROXY" : "DOS";
|
||||
ttp= GetTypeID(topt->type);
|
||||
sprintf(g->Message, "No table_type. Was set to %s", topt->type);
|
||||
snprintf(g->Message, sizeof(g->Message), "No table_type. Was set to %s", topt->type);
|
||||
push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, 0, g->Message);
|
||||
} else if (ttp == TAB_NIY) {
|
||||
sprintf(g->Message, "Unsupported table type %s", topt->type);
|
||||
snprintf(g->Message, sizeof(g->Message), "Unsupported table type %s", topt->type);
|
||||
rc= HA_ERR_INTERNAL_ERROR;
|
||||
goto err;
|
||||
#if defined(REST_SUPPORT)
|
||||
|
|
|
@ -123,7 +123,7 @@ my_bool JSNX::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
|
|||
p[--n] = 0;
|
||||
} else if (!IsNum(p)) {
|
||||
// Wrong array specification
|
||||
sprintf(g->Message, "Invalid array specification %s", p);
|
||||
snprintf(g->Message, sizeof(g->Message), "Invalid array specification %s", p);
|
||||
return true;
|
||||
} // endif p
|
||||
|
||||
|
|
|
@ -399,6 +399,7 @@ PQRYRES SrcColumns(PGLOBAL g, const char *host, const char *db,
|
|||
int w;
|
||||
MYSQLC myc;
|
||||
PQRYRES qrp = NULL;
|
||||
const char *p;
|
||||
|
||||
if (!port)
|
||||
port = mysqld_port;
|
||||
|
@ -406,8 +407,11 @@ PQRYRES SrcColumns(PGLOBAL g, const char *host, const char *db,
|
|||
if (!strnicmp(srcdef, "select ", 7) || strstr(srcdef, "%s")) {
|
||||
query = (char *)PlugSubAlloc(g, NULL, strlen(srcdef) + 10);
|
||||
|
||||
if (strstr(srcdef, "%s"))
|
||||
sprintf(query, srcdef, "1=1"); // dummy where clause
|
||||
if ((p= strstr(srcdef, "%s")))
|
||||
{
|
||||
/* Replace %s with 1=1 */
|
||||
sprintf(query, "%.*s1=1%s", (int) (p - srcdef), srcdef, p + 2); // dummy where clause
|
||||
}
|
||||
else
|
||||
strcpy(query, srcdef);
|
||||
|
||||
|
|
54
storage/connect/mysql-test/connect/r/misc.result
Normal file
54
storage/connect/mysql-test/connect/r/misc.result
Normal file
|
@ -0,0 +1,54 @@
|
|||
execute immediate concat('create table t engine=CONNECT table_type=JSON',REPEAT('1',5000),
|
||||
' FILE_NAME=''users.json'' HTTP=''http://localhost:4142'' URI=''/users''');
|
||||
ERROR HY000: Unsupported table type JSON1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
|
||||
execute immediate concat('create table t engine=CONNECT table_type=OEM module=''libname''
|
||||
Option_list=''Myopt=foo'' subtype=''MYTYPE',REPEAT('1', 10000), '''');
|
||||
ERROR HY000: Subtype string too long
|
||||
execute immediate concat('create table t engine=CONNECT table_type=DBF file_name=''',
|
||||
REPLACE(@@secure_file_priv,'\\','/'),'cust.dbf', REPEAT('1', 10000), '''');
|
||||
ERROR HY000: Cannot open
|
||||
create table t engine=connect table_type=mysql
|
||||
CONNECTION='mysql://root@localhost:MASTER_MYPORT/test/foobar'
|
||||
SRCDEF='SELECT 1,''%n'' FROM DUAL WHERE %s';
|
||||
select *from t;
|
||||
ERROR HY000: Got error 174 'MakeSQL: Wrong place holders specification' from CONNECT
|
||||
drop table t;
|
||||
create table t engine=connect table_type=mysql
|
||||
CONNECTION='mysql://root@localhost:MASTER_MYPORT/test/foobar'
|
||||
SRCDEF='SELECT 1,%n FROM DUAL WHERE %s';
|
||||
ERROR HY000: (1064) You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '%n FROM DUAL WHERE 1=1 LIMIT 0' at line 1 [SELECT 1,%n FROM DUAL WHERE 1=1 LIMIT 0]
|
||||
create table t engine=connect table_type=mysql
|
||||
CONNECTION='mysql://root@localhost:MASTER_MYPORT/test/foobar'
|
||||
SRCDEF='SELECT 1 FROM DUAL WHERE %s';
|
||||
select *from t;
|
||||
1
|
||||
1
|
||||
drop table t;
|
||||
create table beers (
|
||||
`Name` char(16) xpath='brandName',
|
||||
`Origin` char(16) xpath='origin',
|
||||
`Description` char(32) xpath='details')
|
||||
engine=CONNECT table_type=XML file_name='MYSQLTEST_VARDIR/tmp/beer.xml'
|
||||
tabname='table' option_list='rownode=tr,colnode=td%n';
|
||||
select * from beers;
|
||||
Name Origin Description
|
||||
NULL NULL NULL
|
||||
NULL NULL NULL
|
||||
drop table beers;
|
||||
create table beers (
|
||||
`Name` char(16) xpath='brandName',
|
||||
`Origin` char(16) xpath='origin',
|
||||
`Description` char(32) xpath='details')
|
||||
engine=CONNECT table_type=XML file_name='MYSQLTEST_VARDIR/tmp/beer.xml'
|
||||
tabname='table' option_list='rownode=tr,colnode=td';
|
||||
insert into beers values('11','22','33');
|
||||
drop table beers;
|
||||
execute immediate CONCAT('create table jsampall
|
||||
(Author char(128) jpath=''$.AUTHOR["', REPEAT('a',10000),'"]'')
|
||||
engine=CONNECT table_type=JSON
|
||||
file_name=''',REPLACE(@@secure_file_priv,'\\','/'),'tmp/test.json''');
|
||||
select author from jsampall;
|
||||
author
|
||||
Jean-Christophe Bernadacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
William J. Pardi
|
||||
drop table jsampall;
|
141
storage/connect/mysql-test/connect/t/misc.test
Normal file
141
storage/connect/mysql-test/connect/t/misc.test
Normal file
|
@ -0,0 +1,141 @@
|
|||
|
||||
# Overlong table type
|
||||
--error ER_UNKNOWN_ERROR
|
||||
execute immediate concat('create table t engine=CONNECT table_type=JSON',REPEAT('1',5000),
|
||||
' FILE_NAME=''users.json'' HTTP=''http://localhost:4142'' URI=''/users''');
|
||||
|
||||
# Overlong subtype
|
||||
--error ER_UNKNOWN_ERROR
|
||||
execute immediate concat('create table t engine=CONNECT table_type=OEM module=''libname''
|
||||
Option_list=''Myopt=foo'' subtype=''MYTYPE',REPEAT('1', 10000), '''');
|
||||
|
||||
|
||||
# Overlong filename
|
||||
--error ER_UNKNOWN_ERROR
|
||||
execute immediate concat('create table t engine=CONNECT table_type=DBF file_name=''',
|
||||
REPLACE(@@secure_file_priv,'\\','/'),'cust.dbf', REPEAT('1', 10000), '''');
|
||||
|
||||
|
||||
# Format string in SRCDEF
|
||||
--replace_result $MASTER_MYPORT MASTER_MYPORT
|
||||
eval create table t engine=connect table_type=mysql
|
||||
CONNECTION='mysql://root@localhost:$MASTER_MYPORT/test/foobar'
|
||||
SRCDEF='SELECT 1,''%n'' FROM DUAL WHERE %s';
|
||||
--error ER_GET_ERRMSG
|
||||
select *from t;
|
||||
drop table t;
|
||||
|
||||
--replace_result $MASTER_MYPORT MASTER_MYPORT
|
||||
--error ER_UNKNOWN_ERROR
|
||||
eval create table t engine=connect table_type=mysql
|
||||
CONNECTION='mysql://root@localhost:$MASTER_MYPORT/test/foobar'
|
||||
SRCDEF='SELECT 1,%n FROM DUAL WHERE %s';
|
||||
|
||||
--replace_result $MASTER_MYPORT MASTER_MYPORT
|
||||
eval create table t engine=connect table_type=mysql
|
||||
CONNECTION='mysql://root@localhost:$MASTER_MYPORT/test/foobar'
|
||||
SRCDEF='SELECT 1 FROM DUAL WHERE %s';
|
||||
select *from t;
|
||||
drop table t;
|
||||
|
||||
write_file $MYSQLTEST_VARDIR/tmp/beer.xml;
|
||||
<?xml version="1.0"?>
|
||||
<Beers>
|
||||
<table>
|
||||
<th><td>Name</td><td>Origin</td><td>Description</td></th>
|
||||
<tr>
|
||||
<td><brandName>Huntsman</brandName></td>
|
||||
<td><origin>Bath, UK</origin></td>
|
||||
<td><details>Wonderful hop, light alcohol</details></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><brandName>Tuborg</brandName></td>
|
||||
<td><origin>Danmark</origin></td>
|
||||
<td><details>In small bottles</details></td>
|
||||
</tr>
|
||||
</table>
|
||||
</Beers>
|
||||
EOF
|
||||
|
||||
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||
# Format string in colnode
|
||||
eval create table beers (
|
||||
`Name` char(16) xpath='brandName',
|
||||
`Origin` char(16) xpath='origin',
|
||||
`Description` char(32) xpath='details')
|
||||
engine=CONNECT table_type=XML file_name='$MYSQLTEST_VARDIR/tmp/beer.xml'
|
||||
tabname='table' option_list='rownode=tr,colnode=td%n';
|
||||
select * from beers;
|
||||
drop table beers;
|
||||
|
||||
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||
eval create table beers (
|
||||
`Name` char(16) xpath='brandName',
|
||||
`Origin` char(16) xpath='origin',
|
||||
`Description` char(32) xpath='details')
|
||||
engine=CONNECT table_type=XML file_name='$MYSQLTEST_VARDIR/tmp/beer.xml'
|
||||
tabname='table' option_list='rownode=tr,colnode=td';
|
||||
insert into beers values('11','22','33');
|
||||
drop table beers;
|
||||
|
||||
remove_file $MYSQLTEST_VARDIR/tmp/beer.xml;
|
||||
|
||||
write_file $MYSQLTEST_VARDIR/tmp/test.json;
|
||||
[
|
||||
{
|
||||
"ISBN": "9782212090819",
|
||||
"LANG": "fr",
|
||||
"SUBJECT": "applications",
|
||||
"AUTHOR": [
|
||||
{
|
||||
"FIRSTNAME": "Jean-Christophe",
|
||||
"LASTNAME": "Bernadac"
|
||||
},
|
||||
{
|
||||
"FIRSTNAME": "François",
|
||||
"LASTNAME": "Knab"
|
||||
}
|
||||
],
|
||||
"TITLE": "Construire une application XML",
|
||||
"PUBLISHER": {
|
||||
"NAME": "Eyrolles",
|
||||
"PLACE": "Paris"
|
||||
},
|
||||
"DATEPUB": 1999
|
||||
},
|
||||
{
|
||||
"ISBN": "9782840825685",
|
||||
"LANG": "fr",
|
||||
"SUBJECT": "applications",
|
||||
"AUTHOR": [
|
||||
{
|
||||
"FIRSTNAME": "William J.",
|
||||
"LASTNAME": "Pardi"
|
||||
}
|
||||
],
|
||||
"TITLE": "XML en Action",
|
||||
"TRANSLATED": {
|
||||
"PREFIX": "adapté de l'anglais par",
|
||||
"TRANSLATOR": {
|
||||
"FIRSTNAME": "James",
|
||||
"LASTNAME": "Guerin"
|
||||
}
|
||||
},
|
||||
"PUBLISHER": {
|
||||
"NAME": "Microsoft Press",
|
||||
"PLACE": "Paris"
|
||||
},
|
||||
"DATEPUB": 1999
|
||||
}
|
||||
]
|
||||
EOF
|
||||
|
||||
execute immediate CONCAT('create table jsampall
|
||||
(Author char(128) jpath=''$.AUTHOR["', REPEAT('a',10000),'"]'')
|
||||
engine=CONNECT table_type=JSON
|
||||
file_name=''',REPLACE(@@secure_file_priv,'\\','/'),'tmp/test.json''');
|
||||
|
||||
select author from jsampall;
|
||||
drop table jsampall;
|
||||
remove_file $MYSQLTEST_VARDIR/tmp/test.json;
|
||||
|
|
@ -259,6 +259,12 @@ LPCSTR PlugSetPath(LPSTR pBuff, LPCSTR prefix, LPCSTR FileName, LPCSTR defpath)
|
|||
if (trace(2))
|
||||
htrc("prefix=%s fn=%s path=%s\n", prefix, FileName, defpath);
|
||||
|
||||
if (strlen(FileName) >= _MAX_PATH)
|
||||
{
|
||||
*pBuff= 0; /* Hope this is treated as error of some kind*/
|
||||
return FileName;
|
||||
}
|
||||
|
||||
if (!strncmp(FileName, "//", 2) || !strncmp(FileName, "\\\\", 2)) {
|
||||
strcpy(pBuff, FileName); // Remote file
|
||||
return pBuff;
|
||||
|
|
|
@ -93,7 +93,12 @@ PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char* tab, char* db, bool info)
|
|||
if (check_valid_path(module, strlen(module))) {
|
||||
strcpy(g->Message, "Module cannot contain a path");
|
||||
return NULL;
|
||||
} else
|
||||
}
|
||||
else if (strlen(subtype)+1+3 >= sizeof(getname)) {
|
||||
strcpy(g->Message, "Subtype string too long");
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
PlugSetPath(soname, module, GetPluginDir());
|
||||
|
||||
// The exported name is always in uppercase
|
||||
|
|
|
@ -1788,7 +1788,7 @@ bool BSONCOL::SetArrayOptions(PGLOBAL g, char* p, int i, PSZ nm)
|
|||
p[--n] = 0;
|
||||
} else if (!IsNum(p)) {
|
||||
// Wrong array specification
|
||||
sprintf(g->Message, "Invalid array specification %s for %s", p, Name);
|
||||
snprintf(g->Message, sizeof(g->Message), "Invalid array specification %s for %s", p, Name);
|
||||
return true;
|
||||
} // endif p
|
||||
|
||||
|
|
|
@ -286,6 +286,37 @@ int TDBEXT::Decode(PCSZ txt, char *buf, size_t n)
|
|||
return 0;
|
||||
} // end of Decode
|
||||
|
||||
/*
|
||||
Count number of %s placeholders in string.
|
||||
Returns -1 if other sprintf placeholders are found, .g %d
|
||||
*/
|
||||
static int count_placeholders(const char *fmt)
|
||||
{
|
||||
int cnt= 0;
|
||||
for (const char *p=fmt; *p; p++)
|
||||
{
|
||||
if (*p == '%')
|
||||
{
|
||||
switch (p[1])
|
||||
{
|
||||
case 's':
|
||||
/* %s found */
|
||||
cnt++;
|
||||
p++;
|
||||
break;
|
||||
case '%':
|
||||
/* masking char for % found */
|
||||
p++;
|
||||
break;
|
||||
default:
|
||||
/* some other placeholder found */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
/* MakeSrcdef: make the SQL statement from SRDEF option. */
|
||||
/***********************************************************************/
|
||||
|
@ -310,16 +341,29 @@ bool TDBEXT::MakeSrcdef(PGLOBAL g)
|
|||
? To_CondFil->Having : PlugDup(g, "1=1");
|
||||
} // endif ph
|
||||
|
||||
if (!stricmp(ph, "W")) {
|
||||
int n_placeholders = count_placeholders(Srcdef);
|
||||
if (n_placeholders < 0)
|
||||
{
|
||||
strcpy(g->Message, "MakeSQL: Wrong place holders specification");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!stricmp(ph, "W") && n_placeholders <= 1) {
|
||||
Query = new(g)STRING(g, strlen(Srcdef) + strlen(fil1));
|
||||
Query->SetLength(sprintf(Query->GetStr(), Srcdef, fil1));
|
||||
} else if (!stricmp(ph, "WH")) {
|
||||
}
|
||||
else if (!stricmp(ph, "WH") && n_placeholders <= 2)
|
||||
{
|
||||
Query = new(g)STRING(g, strlen(Srcdef) + strlen(fil1) + strlen(fil2));
|
||||
Query->SetLength(sprintf(Query->GetStr(), Srcdef, fil1, fil2));
|
||||
} else if (!stricmp(ph, "H")) {
|
||||
}
|
||||
else if (!stricmp(ph, "H") && n_placeholders <= 1)
|
||||
{
|
||||
Query = new(g)STRING(g, strlen(Srcdef) + strlen(fil2));
|
||||
Query->SetLength(sprintf(Query->GetStr(), Srcdef, fil2));
|
||||
} else if (!stricmp(ph, "HW")) {
|
||||
}
|
||||
else if (!stricmp(ph, "HW") && n_placeholders <= 2)
|
||||
{
|
||||
Query = new(g)STRING(g, strlen(Srcdef) + strlen(fil1) + strlen(fil2));
|
||||
Query->SetLength(sprintf(Query->GetStr(), Srcdef, fil2, fil1));
|
||||
} else {
|
||||
|
|
|
@ -1384,7 +1384,7 @@ bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
|
|||
p[--n] = 0;
|
||||
} else if (!IsNum(p)) {
|
||||
// Wrong array specification
|
||||
sprintf(g->Message, "Invalid array specification %s for %s", p, Name);
|
||||
snprintf(g->Message, sizeof(g->Message), "Invalid array specification %s for %s", p, Name);
|
||||
return true;
|
||||
} // endif p
|
||||
|
||||
|
|
|
@ -904,6 +904,11 @@ bool TDBMYSQL::OpenDB(PGLOBAL g)
|
|||
/*********************************************************************/
|
||||
if (Mode == MODE_READ || Mode == MODE_READX) {
|
||||
MakeSelect(g, Mode == MODE_READX);
|
||||
if (Mode == MODE_READ && !Query)
|
||||
{
|
||||
Myc.Close();
|
||||
return true;
|
||||
}
|
||||
m_Rc = (Mode == MODE_READ)
|
||||
? Myc.ExecSQL(g, Query->GetStr()) : RC_OK;
|
||||
|
||||
|
|
|
@ -1511,8 +1511,12 @@ bool XMLCOL::ParseXpath(PGLOBAL g, bool mode)
|
|||
if (!mode)
|
||||
// Take care of an eventual extra column node a la html
|
||||
if (Tdbp->Colname) {
|
||||
sprintf(pbuf, Tdbp->Colname, Rank + ((Tdbp->Usedom) ? 0 : 1));
|
||||
strcat(pbuf, "/");
|
||||
char *p = strstr(Tdbp->Colname, "%d");
|
||||
if (p)
|
||||
snprintf(pbuf, len + 3, "%.*s%d%s/", (int) (p - Tdbp->Colname), Tdbp->Colname,
|
||||
Rank + (Tdbp->Usedom ? 0 : 1), p + 2);
|
||||
else
|
||||
snprintf(pbuf, len + 3, "%s/", Tdbp->Colname);
|
||||
} // endif Colname
|
||||
|
||||
if (Xname) {
|
||||
|
|
Loading…
Reference in a new issue