Skip to content

Commit 162e426

Browse files
Alexey KopytovAlexey Kopytov
authored andcommitted
Manual merge from the bugfix tree.
conflicts: conflict sql/sql_parse.cc
2 parents 5bace3f + 779e2a9 commit 162e426

16 files changed

Lines changed: 182 additions & 61 deletions

mysql-test/r/error_simulation.result

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,14 @@ a
3939
2
4040
DROP TABLE t1;
4141
#
42+
# Bug#42064: low memory crash when importing hex strings, in Item_hex_string::Item_hex_string
43+
#
44+
CREATE TABLE t1(a BLOB);
45+
SET SESSION debug="+d,bug42064_simulate_oom";
46+
INSERT INTO t1 VALUES("");
47+
Got one of the listed errors
48+
SET SESSION debug=DEFAULT;
49+
DROP TABLE t1;
50+
#
4251
# End of 5.1 tests
4352
#

mysql-test/t/error_simulation.test

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,20 @@ SELECT * FROM t1;
4646
DROP TABLE t1;
4747

4848

49+
--echo #
50+
--echo # Bug#42064: low memory crash when importing hex strings, in Item_hex_string::Item_hex_string
51+
--echo #
52+
53+
CREATE TABLE t1(a BLOB);
54+
55+
SET SESSION debug="+d,bug42064_simulate_oom";
56+
# May fail with either ER_OUT_OF_RESOURCES or EE_OUTOFMEMORY
57+
--error ER_OUT_OF_RESOURCES, 5
58+
INSERT INTO t1 VALUES("");
59+
SET SESSION debug=DEFAULT;
60+
61+
DROP TABLE t1;
62+
4963
--echo #
5064
--echo # End of 5.1 tests
5165
--echo #

mysys/my_alloc.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,14 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length)
154154

155155
DBUG_ASSERT(alloc_root_inited(mem_root));
156156

157+
DBUG_EXECUTE_IF("simulate_out_of_memory",
158+
{
159+
if (mem_root->error_handler)
160+
(*mem_root->error_handler)();
161+
DBUG_SET("-d,simulate_out_of_memory");
162+
DBUG_RETURN((void*) 0); /* purecov: inspected */
163+
});
164+
157165
length+=ALIGN_SIZE(sizeof(USED_MEM));
158166
if (!(next = (USED_MEM*) my_malloc(length,MYF(MY_WME))))
159167
{
@@ -176,6 +184,14 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length)
176184
DBUG_PRINT("enter",("root: 0x%lx", (long) mem_root));
177185
DBUG_ASSERT(alloc_root_inited(mem_root));
178186

187+
DBUG_EXECUTE_IF("simulate_out_of_memory",
188+
{
189+
/* Avoid reusing an already allocated block */
190+
if (mem_root->error_handler)
191+
(*mem_root->error_handler)();
192+
DBUG_SET("-d,simulate_out_of_memory");
193+
DBUG_RETURN((void*) 0); /* purecov: inspected */
194+
});
179195
length= ALIGN_SIZE(length);
180196
if ((*(prev= &mem_root->free)) != NULL)
181197
{

mysys/my_malloc.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,23 @@ void *my_malloc(size_t size, myf my_flags)
3131

3232
if (!size)
3333
size=1; /* Safety */
34-
if ((point = (char*)malloc(size)) == NULL)
34+
35+
point= (char *) malloc(size);
36+
DBUG_EXECUTE_IF("simulate_out_of_memory",
37+
{
38+
free(point);
39+
point= NULL;
40+
});
41+
42+
if (point == NULL)
3543
{
3644
my_errno=errno;
3745
if (my_flags & MY_FAE)
3846
error_handler_hook=fatal_error_handler_hook;
3947
if (my_flags & (MY_FAE+MY_WME))
4048
my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG+ME_NOREFRESH),size);
49+
DBUG_EXECUTE_IF("simulate_out_of_memory",
50+
DBUG_SET("-d,simulate_out_of_memory"););
4151
if (my_flags & MY_FAE)
4252
exit(1);
4353
}

mysys/safemalloc.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ void *_mymalloc(size_t size, const char *filename, uint lineno, myf MyFlags)
139139
size + /* size requested */
140140
4 + /* overrun mark */
141141
sf_malloc_endhunc);
142+
DBUG_EXECUTE_IF("simulate_out_of_memory",
143+
{
144+
free(irem);
145+
irem= NULL;
146+
});
142147
}
143148
/* Check if there isn't anymore memory avaiable */
144149
if (!irem)
@@ -159,6 +164,8 @@ void *_mymalloc(size_t size, const char *filename, uint lineno, myf MyFlags)
159164
}
160165
DBUG_PRINT("error",("Out of memory, in use: %ld at line %d, '%s'",
161166
sf_malloc_max_memory,lineno, filename));
167+
DBUG_EXECUTE_IF("simulate_out_of_memory",
168+
DBUG_SET("-d,simulate_out_of_memory"););
162169
if (MyFlags & MY_FAE)
163170
exit(1);
164171
DBUG_RETURN ((void*) 0);

sql/event_data_objects.cc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1434,7 +1434,10 @@ Event_job_data::execute(THD *thd, bool drop)
14341434
thd->set_query(sp_sql.c_ptr_safe(), sp_sql.length());
14351435

14361436
{
1437-
Parser_state parser_state(thd, thd->query(), thd->query_length());
1437+
Parser_state parser_state;
1438+
if (parser_state.init(thd, thd->query(), thd->query_length()))
1439+
goto end;
1440+
14381441
lex_start(thd);
14391442

14401443
if (parse_sql(thd, & parser_state, creation_ctx))

sql/mysqld.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2967,6 +2967,9 @@ int my_message_sql(uint error, const char *str, myf MyFlags)
29672967
DBUG_RETURN(0);
29682968
}
29692969

2970+
/* When simulating OOM, skip writing to error log to avoid mtr errors */
2971+
DBUG_EXECUTE_IF("simulate_out_of_memory", DBUG_RETURN(0););
2972+
29702973
if (!thd->no_warnings_for_error &&
29712974
!(MyFlags & ME_NO_WARNING_FOR_ERROR))
29722975
{
@@ -2979,6 +2982,10 @@ int my_message_sql(uint error, const char *str, myf MyFlags)
29792982
thd->no_warnings_for_error= FALSE;
29802983
}
29812984
}
2985+
2986+
/* When simulating OOM, skip writing to error log to avoid mtr errors */
2987+
DBUG_EXECUTE_IF("simulate_out_of_memory", DBUG_RETURN(0););
2988+
29822989
if (!thd || MyFlags & ME_NOREFRESH)
29832990
sql_print_error("%s: %s",my_progname,str); /* purecov: inspected */
29842991
DBUG_RETURN(0);

sql/sp.cc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -782,7 +782,12 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
782782
thd->spcont= NULL;
783783

784784
{
785-
Parser_state parser_state(thd, defstr.c_ptr(), defstr.length());
785+
Parser_state parser_state;
786+
if (parser_state.init(thd, defstr.c_ptr(), defstr.length()))
787+
{
788+
ret= SP_INTERNAL_ERROR;
789+
goto end;
790+
}
786791

787792
lex_start(thd);
788793

sql/sql_lex.cc

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -110,39 +110,31 @@ st_parsing_options::reset()
110110
allows_derived= TRUE;
111111
}
112112

113-
Lex_input_stream::Lex_input_stream(THD *thd,
114-
const char* buffer,
115-
unsigned int length)
116-
: m_thd(thd),
117-
yylineno(1),
118-
yytoklen(0),
119-
yylval(NULL),
120-
m_ptr(buffer),
121-
m_tok_start(NULL),
122-
m_tok_end(NULL),
123-
m_end_of_query(buffer + length),
124-
m_tok_start_prev(NULL),
125-
m_buf(buffer),
126-
m_buf_length(length),
127-
m_echo(TRUE),
128-
m_cpp_tok_start(NULL),
129-
m_cpp_tok_start_prev(NULL),
130-
m_cpp_tok_end(NULL),
131-
m_body_utf8(NULL),
132-
m_cpp_utf8_processed_ptr(NULL),
133-
next_state(MY_LEX_START),
134-
found_semicolon(NULL),
135-
ignore_space(test(thd->variables.sql_mode & MODE_IGNORE_SPACE)),
136-
stmt_prepare_mode(FALSE),
137-
in_comment(NO_COMMENT),
138-
m_underscore_cs(NULL)
113+
114+
bool Lex_input_stream::init(THD *thd, const char *buff, unsigned int length)
139115
{
116+
DBUG_EXECUTE_IF("bug42064_simulate_oom",
117+
DBUG_SET("+d,simulate_out_of_memory"););
118+
140119
m_cpp_buf= (char*) thd->alloc(length + 1);
120+
121+
DBUG_EXECUTE_IF("bug42064_simulate_oom",
122+
DBUG_SET("-d,bug42064_simulate_oom"););
123+
124+
if (m_cpp_buf == NULL)
125+
return TRUE;
126+
141127
m_cpp_ptr= m_cpp_buf;
128+
m_thd= thd;
129+
m_ptr= buff;
130+
m_end_of_query= buff + length;
131+
m_buf= buff;
132+
m_buf_length= length;
133+
ignore_space= test(thd->variables.sql_mode & MODE_IGNORE_SPACE);
134+
135+
return FALSE;
142136
}
143137

144-
Lex_input_stream::~Lex_input_stream()
145-
{}
146138

147139
/**
148140
The operation is called from the parser in order to

sql/sql_lex.h

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,9 +1149,38 @@ enum enum_comment_state
11491149
class Lex_input_stream
11501150
{
11511151
public:
1152-
Lex_input_stream(THD *thd, const char* buff, unsigned int length);
1153-
~Lex_input_stream();
1152+
Lex_input_stream() :
1153+
yylineno(1),
1154+
yytoklen(0),
1155+
yylval(NULL),
1156+
m_tok_start(NULL),
1157+
m_tok_end(NULL),
1158+
m_tok_start_prev(NULL),
1159+
m_echo(TRUE),
1160+
m_cpp_tok_start(NULL),
1161+
m_cpp_tok_start_prev(NULL),
1162+
m_cpp_tok_end(NULL),
1163+
m_body_utf8(NULL),
1164+
m_cpp_utf8_processed_ptr(NULL),
1165+
next_state(MY_LEX_START),
1166+
found_semicolon(NULL),
1167+
stmt_prepare_mode(FALSE),
1168+
in_comment(NO_COMMENT),
1169+
m_underscore_cs(NULL)
1170+
{
1171+
}
1172+
1173+
~Lex_input_stream()
1174+
{
1175+
}
1176+
1177+
/**
1178+
Object initializer. Must be called before usage.
11541179
1180+
@retval FALSE OK
1181+
@retval TRUE Error
1182+
*/
1183+
bool init(THD *thd, const char *buff, unsigned int length);
11551184
/**
11561185
Set the echo mode.
11571186
@@ -1933,10 +1962,21 @@ class Yacc_state
19331962
class Parser_state
19341963
{
19351964
public:
1936-
Parser_state(THD *thd, const char* buff, unsigned int length)
1937-
: m_lip(thd, buff, length), m_yacc()
1965+
Parser_state()
1966+
: m_yacc()
19381967
{}
19391968

1969+
/**
1970+
Object initializer. Must be called before usage.
1971+
1972+
@retval FALSE OK
1973+
@retval TRUE Error
1974+
*/
1975+
bool init(THD *thd, const char *buff, unsigned int length)
1976+
{
1977+
return m_lip.init(thd, buff, length);
1978+
}
1979+
19401980
~Parser_state()
19411981
{}
19421982

0 commit comments

Comments
 (0)