Commit 2925d0f2 authored by Vladislav Vaintroub's avatar Vladislav Vaintroub

MDEV-27612 Connect : check buffer sizes, fix string format errors

parent b9623383
...@@ -201,7 +201,7 @@ my_bool BJNX::SetArrayOptions(PGLOBAL g, char* p, int i, PSZ nm) ...@@ -201,7 +201,7 @@ my_bool BJNX::SetArrayOptions(PGLOBAL g, char* p, int i, PSZ nm)
p[--n] = 0; p[--n] = 0;
} else if (!IsNum(p)) { } else if (!IsNum(p)) {
// Wrong array specification // Wrong array specification
sprintf(g->Message, "Invalid array specification %s", p); snprintf(g->Message, sizeof(g->Message), "Invalid array specification %s", p);
return true; return true;
} // endif p } // endif p
......
...@@ -5707,10 +5707,10 @@ static int connect_assisted_discovery(handlerton *, THD* thd, ...@@ -5707,10 +5707,10 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
if (ttp == TAB_UNDEF && !topt->http) { if (ttp == TAB_UNDEF && !topt->http) {
topt->type= (src) ? "MYSQL" : (tab) ? "PROXY" : "DOS"; topt->type= (src) ? "MYSQL" : (tab) ? "PROXY" : "DOS";
ttp= GetTypeID(topt->type); 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); push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, 0, g->Message);
} else if (ttp == TAB_NIY) { } 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; rc= HA_ERR_INTERNAL_ERROR;
goto err; goto err;
#if defined(REST_SUPPORT) #if defined(REST_SUPPORT)
......
...@@ -123,7 +123,7 @@ my_bool JSNX::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm) ...@@ -123,7 +123,7 @@ my_bool JSNX::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
p[--n] = 0; p[--n] = 0;
} else if (!IsNum(p)) { } else if (!IsNum(p)) {
// Wrong array specification // Wrong array specification
sprintf(g->Message, "Invalid array specification %s", p); snprintf(g->Message, sizeof(g->Message), "Invalid array specification %s", p);
return true; return true;
} // endif p } // endif p
......
...@@ -399,15 +399,19 @@ PQRYRES SrcColumns(PGLOBAL g, const char *host, const char *db, ...@@ -399,15 +399,19 @@ PQRYRES SrcColumns(PGLOBAL g, const char *host, const char *db,
int w; int w;
MYSQLC myc; MYSQLC myc;
PQRYRES qrp = NULL; PQRYRES qrp = NULL;
const char *p;
if (!port) if (!port)
port = mysqld_port; port = mysqld_port;
if (!strnicmp(srcdef, "select ", 7) || strstr(srcdef, "%s")) { if (!strnicmp(srcdef, "select ", 7) || strstr(srcdef, "%s")) {
query = (char *)PlugSubAlloc(g, NULL, strlen(srcdef) + 10); query = (char *)PlugSubAlloc(g, NULL, strlen(srcdef) + 10);
if (strstr(srcdef, "%s")) if ((p= strstr(srcdef, "%s")))
sprintf(query, srcdef, "1=1"); // dummy where clause {
/* Replace %s with 1=1 */
sprintf(query, "%.*s1=1%s", (int) (p - srcdef), srcdef, p + 2); // dummy where clause
}
else else
strcpy(query, srcdef); strcpy(query, srcdef);
......
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;
# 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) ...@@ -259,6 +259,12 @@ LPCSTR PlugSetPath(LPSTR pBuff, LPCSTR prefix, LPCSTR FileName, LPCSTR defpath)
if (trace(2)) if (trace(2))
htrc("prefix=%s fn=%s path=%s\n", prefix, FileName, defpath); 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)) { if (!strncmp(FileName, "//", 2) || !strncmp(FileName, "\\\\", 2)) {
strcpy(pBuff, FileName); // Remote file strcpy(pBuff, FileName); // Remote file
return pBuff; return pBuff;
......
...@@ -93,7 +93,12 @@ PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char* tab, char* db, bool info) ...@@ -93,7 +93,12 @@ PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char* tab, char* db, bool info)
if (check_valid_path(module, strlen(module))) { if (check_valid_path(module, strlen(module))) {
strcpy(g->Message, "Module cannot contain a path"); strcpy(g->Message, "Module cannot contain a path");
return NULL; 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()); PlugSetPath(soname, module, GetPluginDir());
// The exported name is always in uppercase // The exported name is always in uppercase
......
...@@ -1788,7 +1788,7 @@ bool BSONCOL::SetArrayOptions(PGLOBAL g, char* p, int i, PSZ nm) ...@@ -1788,7 +1788,7 @@ bool BSONCOL::SetArrayOptions(PGLOBAL g, char* p, int i, PSZ nm)
p[--n] = 0; p[--n] = 0;
} else if (!IsNum(p)) { } else if (!IsNum(p)) {
// Wrong array specification // 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; return true;
} // endif p } // endif p
......
...@@ -286,6 +286,37 @@ int TDBEXT::Decode(PCSZ txt, char *buf, size_t n) ...@@ -286,6 +286,37 @@ int TDBEXT::Decode(PCSZ txt, char *buf, size_t n)
return 0; return 0;
} // end of Decode } // 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. */ /* MakeSrcdef: make the SQL statement from SRDEF option. */
/***********************************************************************/ /***********************************************************************/
...@@ -310,16 +341,29 @@ bool TDBEXT::MakeSrcdef(PGLOBAL g) ...@@ -310,16 +341,29 @@ bool TDBEXT::MakeSrcdef(PGLOBAL g)
? To_CondFil->Having : PlugDup(g, "1=1"); ? To_CondFil->Having : PlugDup(g, "1=1");
} // endif ph } // 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 = new(g)STRING(g, strlen(Srcdef) + strlen(fil1));
Query->SetLength(sprintf(Query->GetStr(), Srcdef, 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 = new(g)STRING(g, strlen(Srcdef) + strlen(fil1) + strlen(fil2));
Query->SetLength(sprintf(Query->GetStr(), Srcdef, fil1, 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 = new(g)STRING(g, strlen(Srcdef) + strlen(fil2));
Query->SetLength(sprintf(Query->GetStr(), Srcdef, 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 = new(g)STRING(g, strlen(Srcdef) + strlen(fil1) + strlen(fil2));
Query->SetLength(sprintf(Query->GetStr(), Srcdef, fil2, fil1)); Query->SetLength(sprintf(Query->GetStr(), Srcdef, fil2, fil1));
} else { } else {
......
...@@ -1384,7 +1384,7 @@ bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm) ...@@ -1384,7 +1384,7 @@ bool JSONCOL::SetArrayOptions(PGLOBAL g, char *p, int i, PSZ nm)
p[--n] = 0; p[--n] = 0;
} else if (!IsNum(p)) { } else if (!IsNum(p)) {
// Wrong array specification // 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; return true;
} // endif p } // endif p
......
...@@ -904,6 +904,11 @@ bool TDBMYSQL::OpenDB(PGLOBAL g) ...@@ -904,6 +904,11 @@ bool TDBMYSQL::OpenDB(PGLOBAL g)
/*********************************************************************/ /*********************************************************************/
if (Mode == MODE_READ || Mode == MODE_READX) { if (Mode == MODE_READ || Mode == MODE_READX) {
MakeSelect(g, Mode == MODE_READX); MakeSelect(g, Mode == MODE_READX);
if (Mode == MODE_READ && !Query)
{
Myc.Close();
return true;
}
m_Rc = (Mode == MODE_READ) m_Rc = (Mode == MODE_READ)
? Myc.ExecSQL(g, Query->GetStr()) : RC_OK; ? Myc.ExecSQL(g, Query->GetStr()) : RC_OK;
......
...@@ -1511,9 +1511,13 @@ bool XMLCOL::ParseXpath(PGLOBAL g, bool mode) ...@@ -1511,9 +1511,13 @@ bool XMLCOL::ParseXpath(PGLOBAL g, bool mode)
if (!mode) if (!mode)
// Take care of an eventual extra column node a la html // Take care of an eventual extra column node a la html
if (Tdbp->Colname) { if (Tdbp->Colname) {
sprintf(pbuf, Tdbp->Colname, Rank + ((Tdbp->Usedom) ? 0 : 1)); char *p = strstr(Tdbp->Colname, "%d");
strcat(pbuf, "/"); if (p)
} // endif Colname 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) { if (Xname) {
if (Type == 2) { if (Type == 2) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment