Skip to content

Commit

Permalink
Bug #29929684 USING MANY NESTED ARGUMENTS WITH BOOLEAN FTS CAN LEAD
Browse files Browse the repository at this point in the history
TO TERMINATE SERVER.

Problem:
Using a large amount of nested sub-expressions in boolean full-text
search (FTS) can cause a crash.

Analysis:
For each nested sub-expression, we call fts_ast_visit_sub_exp().
which is called recursively until it reaches to the last
sub-expression.
when we use large number of nested sub-expression in FTS. Because of
undefined base condition, recursive calls to fts_ast_visit_sub_exp()
aborts the server with stack overflow error.

Fix:
Added a limit on number of nested arguments should be allowed in
fulltext search.

RB: 23443
Reviewed by : Rahul Agarkar <[email protected]>
  • Loading branch information
sachinagarwal1111 committed Aug 25, 2020
1 parent 7e730bd commit e2a46b4
Showing 9 changed files with 36 additions and 10 deletions.
5 changes: 3 additions & 2 deletions include/my_base.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
/* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
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,
@@ -493,7 +493,8 @@ is the global server default. */
#define HA_ERR_TEMP_FILE_WRITE_FAILURE 189 /* Temporary file write failure */
#define HA_ERR_INNODB_FORCED_RECOVERY 190 /* Innodb is in force recovery mode */
#define HA_ERR_FTS_TOO_MANY_WORDS_IN_PHRASE 191 /* Too many words in a phrase */
#define HA_ERR_LAST 191 /* Copy of last error nr */
#define HA_ERR_FTS_TOO_MANY_NESTED_EXP 192 /* Too many sub-expression in search string */
#define HA_ERR_LAST 192 /* Copy of last error nr */

/* Number of different errors */
#define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1)
5 changes: 3 additions & 2 deletions mysys/my_handler_errors.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#ifndef MYSYS_MY_HANDLER_ERRORS_INCLUDED
#define MYSYS_MY_HANDLER_ERRORS_INCLUDED

/* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
/* Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved.
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,
@@ -106,7 +106,8 @@ static const char *handler_error_messages[]=
"FTS query exceeds result cache memory limit",
"Temporary file write failure",
"Operation not allowed when innodb_forced_recovery > 0",
"Too many words in a FTS phrase or proximity search"
"Too many words in a FTS phrase or proximity search",
"Too many nested sub-expressions in a full-text search"
};

extern void my_handler_error_register(void);
3 changes: 2 additions & 1 deletion sql/handler.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
/* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
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,
@@ -565,6 +565,7 @@ int ha_init_errors(void)
SETMSG(HA_ERR_TEMP_FILE_WRITE_FAILURE, ER_DEFAULT(ER_TEMP_FILE_WRITE_FAILURE));
SETMSG(HA_ERR_INNODB_FORCED_RECOVERY, ER_DEFAULT(ER_INNODB_FORCED_RECOVERY));
SETMSG(HA_ERR_FTS_TOO_MANY_WORDS_IN_PHRASE, "Too many words in a FTS phrase or proximity search");
SETMSG(HA_ERR_FTS_TOO_MANY_NESTED_EXP, "Too many nested sub-expressions in a full-text search");
/* Register the error messages for use with my_error(). */
return my_error_register(get_handler_errmsgs, HA_ERR_FIRST, HA_ERR_LAST);
}
3 changes: 2 additions & 1 deletion sql/log_event.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

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,
@@ -198,6 +198,7 @@ static const char *HA_ERR(int i)
case HA_ERR_CORRUPT_EVENT: return "HA_ERR_CORRUPT_EVENT";
case HA_ERR_ROWS_EVENT_APPLY : return "HA_ERR_ROWS_EVENT_APPLY";
case HA_ERR_INNODB_READ_ONLY: return "HA_ERR_INNODB_READ_ONLY";
case HA_ERR_FTS_TOO_MANY_NESTED_EXP: return "HA_ERR_FTS_TOO_MANY_NESTED_EXP";
}
return "No Error!";
}
15 changes: 14 additions & 1 deletion storage/innobase/fts/fts0que.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 2007, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2007, 2020, Oracle and/or its affiliates. All Rights Reserved.
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,
@@ -153,6 +153,8 @@ struct fts_query_t {
fts_word_freq_t */

bool multi_exist; /*!< multiple FTS_EXIST oper */
ulint nested_exp_count; /*!< number of nested sub expression
limit */
};

/** For phrase matching, first we collect the documents and the positions
@@ -2936,6 +2938,17 @@ fts_ast_visit_sub_exp(

DBUG_ENTER("fts_ast_visit_sub_exp");

/* sub-expression list may contains sub-expressions.
So we increase sub-expression depth counter.
If this counter reaches to the threshold then
we abort the search opertion and reports an error */
if (query->nested_exp_count > FTS_MAX_NESTED_EXP) {
query->error = DB_FTS_TOO_MANY_NESTED_EXP;
DBUG_RETURN(query->error);
}
query->nested_exp_count++;


ut_a(node->type == FTS_AST_SUBEXP_LIST);

cur_oper = query->oper;
2 changes: 2 additions & 0 deletions storage/innobase/handler/ha_innodb.cc
Original file line number Diff line number Diff line change
@@ -1689,6 +1689,8 @@ convert_error_code_to_mysql(
return(HA_ERR_INTERNAL_ERROR);
case DB_FTS_TOO_MANY_WORDS_IN_PHRASE:
return(HA_ERR_FTS_TOO_MANY_WORDS_IN_PHRASE);
case DB_FTS_TOO_MANY_NESTED_EXP:
return(HA_ERR_FTS_TOO_MANY_NESTED_EXP);
}
}

4 changes: 3 additions & 1 deletion storage/innobase/include/db0err.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1996, 2020, Oracle and/or its affiliates. All Rights Reserved.
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,
@@ -161,6 +161,8 @@ enum dberr_t {
schema to be locked in exclusive mode
and if it's not then that API function
will return this error code */
DB_FTS_TOO_MANY_NESTED_EXP, /*< Too many nested sub expression
in full-text search string */

DB_NOT_FOUND /*!< Generic error code for "Not found"
type of errors */
5 changes: 4 additions & 1 deletion storage/innobase/include/fts0fts.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 2011, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2011, 2020, Oracle and/or its affiliates. All Rights Reserved.
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,
@@ -106,6 +106,9 @@ those defined in mysql file ft_global.h */
should not exceed FTS_DOC_ID_MAX_STEP */
#define FTS_DOC_ID_MAX_STEP 65535

/* Maximum nested expression in fulltext binary search string */
#define FTS_MAX_NESTED_EXP 31

/** Variable specifying the FTS parallel sort degree */
extern ulong fts_sort_pll_degree;

4 changes: 3 additions & 1 deletion storage/innobase/ut/ut0ut.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1994, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1994, 2020, Oracle and/or its affiliates. All Rights Reserved.
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,
@@ -858,6 +858,8 @@ ut_strerr(
return("Too many words in a FTS phrase or proximity search");
case DB_TOO_BIG_FOR_REDO:
return("BLOB record length is greater than 10%% of redo log");
case DB_FTS_TOO_MANY_NESTED_EXP:
return("Too many nested sub-expressions in a full-text search");

/* do not add default: in order to produce a warning if new code
is added to the enum but not added here */

0 comments on commit e2a46b4

Please sign in to comment.