Commit c8b8d009 authored by Marc Alff's avatar Marc Alff

Bug#18319790 QUERY TO INFORMATION_SCHEMA CRASHES SERVER

Before this fix, specially crafted queries
using the INFORMATION_SCHEMA could crash the server.

The root cause was a buffer overflow,
see the (private) bug comments for details.

With this fix, the buffer overflow condition is properly handled,
and the queries involved do return the expected result.
parent 2d5be2fc
/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
/* Copyright (c) 2000, 2014, 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 as published by
......@@ -2394,10 +2394,38 @@ void calc_sum_of_all_status(STATUS_VAR *to)
/* This is only used internally, but we need it here as a forward reference */
extern ST_SCHEMA_TABLE schema_tables[];
/**
Condition pushdown used for INFORMATION_SCHEMA / SHOW queries.
This structure is to implement an optimization when
accessing data dictionary data in the INFORMATION_SCHEMA
or SHOW commands.
When the query contain a TABLE_SCHEMA or TABLE_NAME clause,
narrow the search for data based on the constraints given.
*/
typedef struct st_lookup_field_values
{
LEX_STRING db_value, table_value;
bool wild_db_value, wild_table_value;
/**
Value of a TABLE_SCHEMA clause.
Note that this value length may exceed @c NAME_LEN.
@sa wild_db_value
*/
LEX_STRING db_value;
/**
Value of a TABLE_NAME clause.
Note that this value length may exceed @c NAME_LEN.
@sa wild_table_value
*/
LEX_STRING table_value;
/**
True when @c db_value is a LIKE clause,
false when @c db_value is an '=' clause.
*/
bool wild_db_value;
/**
True when @c table_value is a LIKE clause,
false when @c table_value is an '=' clause.
*/
bool wild_table_value;
} LOOKUP_FIELD_VALUES;
......@@ -2801,14 +2829,22 @@ int make_db_list(THD *thd, List<LEX_STRING> *files,
/*
If we have db lookup vaule we just add it to list and
If we have db lookup value we just add it to list and
exit from the function.
We don't do this for database names longer than the maximum
path length.
name length.
*/
if (lookup_field_vals->db_value.str &&
lookup_field_vals->db_value.length < FN_REFLEN)
if (lookup_field_vals->db_value.str)
{
if (lookup_field_vals->db_value.length > NAME_LEN)
{
/*
Impossible value for a database name,
found in a WHERE DATABASE_NAME = 'xxx' clause.
*/
return 0;
}
if (is_infoschema_db(lookup_field_vals->db_value.str,
lookup_field_vals->db_value.length))
{
......@@ -2945,6 +2981,15 @@ make_table_name_list(THD *thd, List<LEX_STRING> *table_names, LEX *lex,
if (!lookup_field_vals->wild_table_value &&
lookup_field_vals->table_value.str)
{
if (lookup_field_vals->table_value.length > NAME_LEN)
{
/*
Impossible value for a table name,
found in a WHERE TABLE_NAME = 'xxx' clause.
*/
return 0;
}
if (with_i_schema)
{
LEX_STRING *name;
......@@ -3411,6 +3456,9 @@ static int fill_schema_table_from_frm(THD *thd, TABLE_LIST *tables,
bzero((char*) &table_list, sizeof(TABLE_LIST));
bzero((char*) &tbl, sizeof(TABLE));
DBUG_ASSERT(db_name->length <= NAME_LEN);
DBUG_ASSERT(table_name->length <= NAME_LEN);
if (lower_case_table_names)
{
/*
......@@ -3742,6 +3790,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
it.rewind(); /* To get access to new elements in basis list */
while ((db_name= it++))
{
DBUG_ASSERT(db_name->length <= NAME_LEN);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (!(check_access(thd, SELECT_ACL, db_name->str,
&thd->col_access, NULL, 0, 1) ||
......@@ -3763,6 +3812,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
List_iterator_fast<LEX_STRING> it_files(table_names);
while ((table_name= it_files++))
{
DBUG_ASSERT(table_name->length <= NAME_LEN);
restore_record(table, s->default_values);
table->field[schema_table->idx_field1]->
store(db_name->str, db_name->length, system_charset_info);
......@@ -3909,6 +3959,7 @@ int fill_schema_schemata(THD *thd, TABLE_LIST *tables, COND *cond)
List_iterator_fast<LEX_STRING> it(db_names);
while ((db_name=it++))
{
DBUG_ASSERT(db_name->length <= NAME_LEN);
if (with_i_schema) // information schema name is always first in list
{
if (store_schema_shemata(thd, table, db_name,
......
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