Permalink
Browse files

Fix #434 ub/sigsegv when using strtod on non-terminated strings. Test…

… added.
  • Loading branch information...
klirichek committed Sep 4, 2018
1 parent 7dbdd17 commit 1366ee06e828397074b69bec9265d7147170c60e
Showing with 108 additions and 1 deletion.
  1. +12 −0 src/gtests_functions.cpp
  2. +9 −1 src/sphinxexpr.cpp
  3. +15 −0 src/sphinxutils.h
  4. +1 −0 test/test_362/model.bin
  5. +71 −0 test/test_362/test.xml
@@ -1225,3 +1225,15 @@ TEST ( functions, int64_le )
ASSERT_EQ ( iTest, iTestLE ) << "little endian allows simplify";
#endif
}
TEST ( functions, FindLastNumeric )
{
static const char * sNum1 = "12345";
ASSERT_EQ ( sNum1, sphFindLastNumeric (sNum1,5 ));
static const char * sNum2 = "1234 ";
ASSERT_EQ ( sNum2+5, sphFindLastNumeric ( sNum2, 5 ) );
static const char * sNum3 = "12 34";
ASSERT_EQ ( sNum3 + 3, sphFindLastNumeric ( sNum3, 5 ) );
}
@@ -4387,6 +4387,8 @@ class Expr_ContainsExprvec_c : public Expr_Contains_c
};
class Expr_ContainsStrattr_c : public Expr_Contains_c
{
protected:
@@ -4404,14 +4406,20 @@ class Expr_ContainsStrattr_c : public Expr_Contains_c
static void ParsePoly ( const char * p, int iLen, CSphVector<float> & dPoly )
{
const char * pMax = p+iLen;
const char * pBegin = p;
const char * pMax = sphFindLastNumeric ( p, iLen );
while ( p<pMax )
{
if ( isdigit(p[0]) || ( p+1<pMax && p[0]=='-' && isdigit(p[1]) ) )
dPoly.Add ( (float)strtod ( p, (char**)&p ) );
else
p++;
}
// edge case - last numeric touches the end
iLen -= pMax - pBegin;
if ( iLen )
dPoly.Add ( (float)strtod ( CSphString(pMax, iLen).cstr (), nullptr ) );
}
int IntEval ( const CSphMatch & tMatch ) const final
@@ -30,6 +30,21 @@ inline int sphIsAlpha ( int c )
return ( c>='0' && c<='9' ) || ( c>='a' && c<='z' ) || ( c>='A' && c<='Z' ) || c=='-' || c=='_';
}
/// symbols allowed in numbers (like 1.84E-20)
inline bool sphIsDigital ( char c )
{
return ( c>='0' && c<='9' ) || c=='.' || c=='E' || c=='e' || c=='+' || c=='-';
}
/// pointer to the last number in the buf, touching it's end
inline const char * sphFindLastNumeric ( const char * pBuf, int iLen )
{
for ( auto pLast = pBuf + iLen - 1; pLast>=pBuf; --pLast )
if ( !sphIsDigital ( *pLast ) )
return pLast + 1;
return pBuf;
}
/// my own isspace
inline bool sphIsSpace ( int iCode )
@@ -0,0 +1 @@
a:1:{i:0;a:1:{i:0;a:3:{s:8:"sphinxql";s:55:"SELECT id, CONTAINS(POLY2D(poly2d_attr),2,40) FROM test";s:10:"total_rows";i:2;s:4:"rows";a:2:{i:0;a:2:{s:2:"id";s:1:"1";s:34:"contains(poly2d(poly2d_attr),2,40)";s:1:"0";}i:1;a:2:{s:2:"id";s:1:"2";s:34:"contains(poly2d(poly2d_attr),2,40)";s:1:"0";}}}}}
@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<test>
<name>asciiz edge effect on string attributes</name>
<requires>
<force-rt/>
</requires>
<config>
indexer
{
mem_limit = 16M
}
searchd
{
<searchd_settings/>
}
source test
{
type = mysql
<sql_settings/>
sql_query = SELECT * FROM test_table
sql_attr_string = kk
sql_attr_string = poly2d_attr
}
index test
{
source = test
path = <data_path/>/test
}
</config>
<db_create>
CREATE TABLE test_table
(
id INT NOT NULL,
title VARCHAR(255) NOT NULL,
kk VARCHAR(255) NOT NULL,
poly2d_attr VARCHAR(255) NOT NULL
);
</db_create>
<db_drop>DROP TABLE IF EXISTS test_table;</db_drop>
<!-- Key point of the test:
Since string attrs in blob are packed and NOT z-terminated,
right after last byte of poly2d_attr of doc 1 will follow
packed attr kk of doc2. Packing first write len of attr (50) and then
the blob of string itself.
Finally it lead to the fact that in the saved blob (at least of RAM-chunk in rt)
will be raw byte sequence '1,2,3,4,4,6210 tenten ...'.
Original version of POLY2D will catch it, and so, reveal that point (2,40) are
in polygon (triangle) (1,2) (3,4) (4,6), because last point is parsed
was (4,6210).
-->
<db_insert>
INSERT INTO test_table ( id, title, kk, poly2d_attr ) VALUES
( 1, 'ohai', 'eleventy', '1,2,3,4,4,6' ),
( 2, 'ohai2', '10 tenten tententen tententen tententen tententen ', '1,2,3,4,4,6' )
</db_insert>
<sphqueries>
<sphinxql>SELECT id, CONTAINS(POLY2D(poly2d_attr),2,40) FROM test</sphinxql>
</sphqueries>
</test>

0 comments on commit 1366ee0

Please sign in to comment.