Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
cecc99db
Commit
cecc99db
authored
Jan 13, 2011
by
Martin Hansson
Browse files
Options
Browse Files
Download
Plain Diff
Merge of fix for Bug#58165.
parents
8c91dc62
3ef71bfa
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
107 additions
and
26 deletions
+107
-26
mysql-test/r/func_str.result
mysql-test/r/func_str.result
+16
-0
mysql-test/t/func_str.test
mysql-test/t/func_str.test
+11
-0
sql/item_strfunc.cc
sql/item_strfunc.cc
+23
-22
sql/item_strfunc.h
sql/item_strfunc.h
+10
-0
sql/sql_string.cc
sql/sql_string.cc
+37
-4
sql/sql_string.h
sql/sql_string.h
+10
-0
No files found.
mysql-test/r/func_str.result
View file @
cecc99db
...
@@ -2615,6 +2615,22 @@ CONVERT(('' IN (REVERSE(CAST(('') AS DECIMAL)), '')), CHAR(3))
...
@@ -2615,6 +2615,22 @@ CONVERT(('' IN (REVERSE(CAST(('') AS DECIMAL)), '')), CHAR(3))
1
1
Warnings:
Warnings:
Warning 1292 Truncated incorrect DECIMAL value: ''
Warning 1292 Truncated incorrect DECIMAL value: ''
#
# Bug#58165: "my_empty_string" gets modified and causes LOAD DATA to fail
# and other crashes
#
CREATE TABLE t1 ( a TEXT );
SELECT 'aaaaaaaaaaaaaa' INTO OUTFILE 'bug58165.txt';
SELECT insert( substring_index( 'a', 'a', 'b' ), 1, 0, 'x' );
insert( substring_index( 'a', 'a', 'b' ), 1, 0, 'x' )
x
Warnings:
Warning 1292 Truncated incorrect INTEGER value: 'b'
LOAD DATA INFILE 'bug58165.txt' INTO TABLE t1;
SELECT * FROM t1;
a
aaaaaaaaaaaaaa
DROP TABLE t1;
End of 5.1 tests
End of 5.1 tests
Start of 5.4 tests
Start of 5.4 tests
SELECT format(12345678901234567890.123, 3);
SELECT format(12345678901234567890.123, 3);
...
...
mysql-test/t/func_str.test
View file @
cecc99db
...
@@ -1370,6 +1370,17 @@ DROP TABLE t1;
...
@@ -1370,6 +1370,17 @@ DROP TABLE t1;
SELECT
'1'
IN
(
'1'
,
SUBSTRING
(
-
9223372036854775809
,
1
));
SELECT
'1'
IN
(
'1'
,
SUBSTRING
(
-
9223372036854775809
,
1
));
SELECT
CONVERT
((
''
IN
(
REVERSE
(
CAST
((
''
)
AS
DECIMAL
)),
''
)),
CHAR
(
3
));
SELECT
CONVERT
((
''
IN
(
REVERSE
(
CAST
((
''
)
AS
DECIMAL
)),
''
)),
CHAR
(
3
));
--
echo
#
--
echo
# Bug#58165: "my_empty_string" gets modified and causes LOAD DATA to fail
--
echo
# and other crashes
--
echo
#
CREATE
TABLE
t1
(
a
TEXT
);
SELECT
'aaaaaaaaaaaaaa'
INTO
OUTFILE
'bug58165.txt'
;
SELECT
insert
(
substring_index
(
'a'
,
'a'
,
'b'
),
1
,
0
,
'x'
);
LOAD
DATA
INFILE
'bug58165.txt'
INTO
TABLE
t1
;
SELECT
*
FROM
t1
;
DROP
TABLE
t1
;
--
echo
End
of
5.1
tests
--
echo
End
of
5.1
tests
--
echo
Start
of
5.4
tests
--
echo
Start
of
5.4
tests
...
...
sql/item_strfunc.cc
View file @
cecc99db
...
@@ -56,6 +56,9 @@ C_MODE_START
...
@@ -56,6 +56,9 @@ C_MODE_START
#include "../mysys/my_static.h" // For soundex_map
#include "../mysys/my_static.h" // For soundex_map
C_MODE_END
C_MODE_END
/**
@todo Remove this. It is not safe to use a shared String object.
*/
String
my_empty_string
(
""
,
default_charset_info
);
String
my_empty_string
(
""
,
default_charset_info
);
/*
/*
...
@@ -642,7 +645,7 @@ String *Item_func_des_encrypt::val_str(String *str)
...
@@ -642,7 +645,7 @@ String *Item_func_des_encrypt::val_str(String *str)
if
((
null_value
=
args
[
0
]
->
null_value
))
if
((
null_value
=
args
[
0
]
->
null_value
))
return
0
;
// ENCRYPT(NULL) == NULL
return
0
;
// ENCRYPT(NULL) == NULL
if
((
res_length
=
res
->
length
())
==
0
)
if
((
res_length
=
res
->
length
())
==
0
)
return
&
my_empty_string
;
return
make_empty_result
()
;
if
(
arg_count
==
1
)
if
(
arg_count
==
1
)
{
{
/* Protect against someone doing FLUSH DES_KEY_FILE */
/* Protect against someone doing FLUSH DES_KEY_FILE */
...
@@ -832,7 +835,7 @@ String *Item_func_concat_ws::val_str(String *str)
...
@@ -832,7 +835,7 @@ String *Item_func_concat_ws::val_str(String *str)
}
}
if
(
i
==
arg_count
)
if
(
i
==
arg_count
)
return
&
my_empty_string
;
return
make_empty_result
()
;
for
(
i
++
;
i
<
arg_count
;
i
++
)
for
(
i
++
;
i
<
arg_count
;
i
++
)
{
{
...
@@ -978,7 +981,7 @@ String *Item_func_reverse::val_str(String *str)
...
@@ -978,7 +981,7 @@ String *Item_func_reverse::val_str(String *str)
return
0
;
return
0
;
/* An empty string is a special case as the string pointer may be null */
/* An empty string is a special case as the string pointer may be null */
if
(
!
res
->
length
())
if
(
!
res
->
length
())
return
&
my_empty_string
;
return
make_empty_result
()
;
if
(
tmp_value
.
alloced_length
()
<
res
->
length
()
&&
if
(
tmp_value
.
alloced_length
()
<
res
->
length
()
&&
tmp_value
.
realloc
(
res
->
length
()))
tmp_value
.
realloc
(
res
->
length
()))
{
{
...
@@ -1311,8 +1314,7 @@ String *Item_func_left::val_str(String *str)
...
@@ -1311,8 +1314,7 @@ String *Item_func_left::val_str(String *str)
/* if "unsigned_flag" is set, we have a *huge* positive number. */
/* if "unsigned_flag" is set, we have a *huge* positive number. */
if
((
length
<=
0
)
&&
(
!
args
[
1
]
->
unsigned_flag
))
if
((
length
<=
0
)
&&
(
!
args
[
1
]
->
unsigned_flag
))
return
&
my_empty_string
;
return
make_empty_result
();
if
((
res
->
length
()
<=
(
ulonglong
)
length
)
||
if
((
res
->
length
()
<=
(
ulonglong
)
length
)
||
(
res
->
length
()
<=
(
char_pos
=
res
->
charpos
((
int
)
length
))))
(
res
->
length
()
<=
(
char_pos
=
res
->
charpos
((
int
)
length
))))
return
res
;
return
res
;
...
@@ -1357,7 +1359,7 @@ String *Item_func_right::val_str(String *str)
...
@@ -1357,7 +1359,7 @@ String *Item_func_right::val_str(String *str)
/* if "unsigned_flag" is set, we have a *huge* positive number. */
/* if "unsigned_flag" is set, we have a *huge* positive number. */
if
((
length
<=
0
)
&&
(
!
args
[
1
]
->
unsigned_flag
))
if
((
length
<=
0
)
&&
(
!
args
[
1
]
->
unsigned_flag
))
return
&
my_empty_string
;
/* purecov: inspected */
return
make_empty_result
()
;
/* purecov: inspected */
if
(
res
->
length
()
<=
(
ulonglong
)
length
)
if
(
res
->
length
()
<=
(
ulonglong
)
length
)
return
res
;
/* purecov: inspected */
return
res
;
/* purecov: inspected */
...
@@ -1397,7 +1399,7 @@ String *Item_func_substr::val_str(String *str)
...
@@ -1397,7 +1399,7 @@ String *Item_func_substr::val_str(String *str)
/* Negative or zero length, will return empty string. */
/* Negative or zero length, will return empty string. */
if
((
arg_count
==
3
)
&&
(
length
<=
0
)
&&
if
((
arg_count
==
3
)
&&
(
length
<=
0
)
&&
(
length
==
0
||
!
args
[
2
]
->
unsigned_flag
))
(
length
==
0
||
!
args
[
2
]
->
unsigned_flag
))
return
&
my_empty_string
;
return
make_empty_result
()
;
/* Assumes that the maximum length of a String is < INT_MAX32. */
/* Assumes that the maximum length of a String is < INT_MAX32. */
/* Set here so that rest of code sees out-of-bound value as such. */
/* Set here so that rest of code sees out-of-bound value as such. */
...
@@ -1408,12 +1410,12 @@ String *Item_func_substr::val_str(String *str)
...
@@ -1408,12 +1410,12 @@ String *Item_func_substr::val_str(String *str)
/* Assumes that the maximum length of a String is < INT_MAX32. */
/* Assumes that the maximum length of a String is < INT_MAX32. */
if
((
!
args
[
1
]
->
unsigned_flag
&&
(
start
<
INT_MIN32
||
start
>
INT_MAX32
))
||
if
((
!
args
[
1
]
->
unsigned_flag
&&
(
start
<
INT_MIN32
||
start
>
INT_MAX32
))
||
(
args
[
1
]
->
unsigned_flag
&&
((
ulonglong
)
start
>
INT_MAX32
)))
(
args
[
1
]
->
unsigned_flag
&&
((
ulonglong
)
start
>
INT_MAX32
)))
return
&
my_empty_string
;
return
make_empty_result
()
;
start
=
((
start
<
0
)
?
res
->
numchars
()
+
start
:
start
-
1
);
start
=
((
start
<
0
)
?
res
->
numchars
()
+
start
:
start
-
1
);
start
=
res
->
charpos
((
int
)
start
);
start
=
res
->
charpos
((
int
)
start
);
if
((
start
<
0
)
||
((
uint
)
start
+
1
>
res
->
length
()))
if
((
start
<
0
)
||
((
uint
)
start
+
1
>
res
->
length
()))
return
&
my_empty_string
;
return
make_empty_result
()
;
length
=
res
->
charpos
((
int
)
length
,
(
uint32
)
start
);
length
=
res
->
charpos
((
int
)
length
,
(
uint32
)
start
);
tmp_length
=
res
->
length
()
-
start
;
tmp_length
=
res
->
length
()
-
start
;
...
@@ -1476,7 +1478,7 @@ String *Item_func_substr_index::val_str(String *str)
...
@@ -1476,7 +1478,7 @@ String *Item_func_substr_index::val_str(String *str)
null_value
=
0
;
null_value
=
0
;
uint
delimiter_length
=
delimiter
->
length
();
uint
delimiter_length
=
delimiter
->
length
();
if
(
!
res
->
length
()
||
!
delimiter_length
||
!
count
)
if
(
!
res
->
length
()
||
!
delimiter_length
||
!
count
)
return
&
my_empty_string
;
// Wrong parameters
return
make_empty_result
()
;
// Wrong parameters
res
->
set_charset
(
collation
.
collation
);
res
->
set_charset
(
collation
.
collation
);
...
@@ -1826,7 +1828,7 @@ String *Item_func_password::val_str_ascii(String *str)
...
@@ -1826,7 +1828,7 @@ String *Item_func_password::val_str_ascii(String *str)
if
((
null_value
=
args
[
0
]
->
null_value
))
if
((
null_value
=
args
[
0
]
->
null_value
))
return
0
;
return
0
;
if
(
res
->
length
()
==
0
)
if
(
res
->
length
()
==
0
)
return
&
my_empty_string
;
return
make_empty_result
()
;
my_make_scrambled_password
(
tmp_value
,
res
->
ptr
(),
res
->
length
());
my_make_scrambled_password
(
tmp_value
,
res
->
ptr
(),
res
->
length
());
str
->
set
(
tmp_value
,
SCRAMBLED_PASSWORD_CHAR_LENGTH
,
&
my_charset_latin1
);
str
->
set
(
tmp_value
,
SCRAMBLED_PASSWORD_CHAR_LENGTH
,
&
my_charset_latin1
);
return
str
;
return
str
;
...
@@ -1850,7 +1852,7 @@ String *Item_func_old_password::val_str_ascii(String *str)
...
@@ -1850,7 +1852,7 @@ String *Item_func_old_password::val_str_ascii(String *str)
if
((
null_value
=
args
[
0
]
->
null_value
))
if
((
null_value
=
args
[
0
]
->
null_value
))
return
0
;
return
0
;
if
(
res
->
length
()
==
0
)
if
(
res
->
length
()
==
0
)
return
&
my_empty_string
;
return
make_empty_result
()
;
my_make_scrambled_password_323
(
tmp_value
,
res
->
ptr
(),
res
->
length
());
my_make_scrambled_password_323
(
tmp_value
,
res
->
ptr
(),
res
->
length
());
str
->
set
(
tmp_value
,
SCRAMBLED_PASSWORD_CHAR_LENGTH_323
,
&
my_charset_latin1
);
str
->
set
(
tmp_value
,
SCRAMBLED_PASSWORD_CHAR_LENGTH_323
,
&
my_charset_latin1
);
return
str
;
return
str
;
...
@@ -1878,8 +1880,7 @@ String *Item_func_encrypt::val_str(String *str)
...
@@ -1878,8 +1880,7 @@ String *Item_func_encrypt::val_str(String *str)
if
((
null_value
=
args
[
0
]
->
null_value
))
if
((
null_value
=
args
[
0
]
->
null_value
))
return
0
;
return
0
;
if
(
res
->
length
()
==
0
)
if
(
res
->
length
()
==
0
)
return
&
my_empty_string
;
return
make_empty_result
();
if
(
arg_count
==
1
)
if
(
arg_count
==
1
)
{
// generate random salt
{
// generate random salt
time_t
timestamp
=
current_thd
->
query_start
();
time_t
timestamp
=
current_thd
->
query_start
();
...
@@ -2141,7 +2142,7 @@ String *Item_func_soundex::val_str(String *str)
...
@@ -2141,7 +2142,7 @@ String *Item_func_soundex::val_str(String *str)
for
(
;
;
)
/* Skip pre-space */
for
(
;
;
)
/* Skip pre-space */
{
{
if
((
rc
=
cs
->
cset
->
mb_wc
(
cs
,
&
wc
,
(
uchar
*
)
from
,
(
uchar
*
)
end
))
<=
0
)
if
((
rc
=
cs
->
cset
->
mb_wc
(
cs
,
&
wc
,
(
uchar
*
)
from
,
(
uchar
*
)
end
))
<=
0
)
return
&
my_empty_string
;
/* EOL or invalid byte sequence */
return
make_empty_result
()
;
/* EOL or invalid byte sequence */
if
(
rc
==
1
&&
cs
->
ctype
)
if
(
rc
==
1
&&
cs
->
ctype
)
{
{
...
@@ -2166,7 +2167,7 @@ String *Item_func_soundex::val_str(String *str)
...
@@ -2166,7 +2167,7 @@ String *Item_func_soundex::val_str(String *str)
{
{
/* Extra safety - should not really happen */
/* Extra safety - should not really happen */
DBUG_ASSERT
(
false
);
DBUG_ASSERT
(
false
);
return
&
my_empty_string
;
return
make_empty_result
()
;
}
}
to
+=
rc
;
to
+=
rc
;
break
;
break
;
...
@@ -2507,7 +2508,7 @@ String *Item_func_make_set::val_str(String *str)
...
@@ -2507,7 +2508,7 @@ String *Item_func_make_set::val_str(String *str)
else
else
{
{
if
(
tmp_str
.
copy
(
*
res
))
// Don't use 'str'
if
(
tmp_str
.
copy
(
*
res
))
// Don't use 'str'
return
&
my_empty_string
;
return
make_empty_result
()
;
result
=
&
tmp_str
;
result
=
&
tmp_str
;
}
}
}
}
...
@@ -2517,11 +2518,11 @@ String *Item_func_make_set::val_str(String *str)
...
@@ -2517,11 +2518,11 @@ String *Item_func_make_set::val_str(String *str)
{
// Copy data to tmp_str
{
// Copy data to tmp_str
if
(
tmp_str
.
alloc
(
result
->
length
()
+
res
->
length
()
+
1
)
||
if
(
tmp_str
.
alloc
(
result
->
length
()
+
res
->
length
()
+
1
)
||
tmp_str
.
copy
(
*
result
))
tmp_str
.
copy
(
*
result
))
return
&
my_empty_string
;
return
make_empty_result
()
;
result
=
&
tmp_str
;
result
=
&
tmp_str
;
}
}
if
(
tmp_str
.
append
(
STRING_WITH_LEN
(
","
),
&
my_charset_bin
)
||
tmp_str
.
append
(
*
res
))
if
(
tmp_str
.
append
(
STRING_WITH_LEN
(
","
),
&
my_charset_bin
)
||
tmp_str
.
append
(
*
res
))
return
&
my_empty_string
;
return
make_empty_result
()
;
}
}
}
}
}
}
...
@@ -2666,7 +2667,7 @@ String *Item_func_repeat::val_str(String *str)
...
@@ -2666,7 +2667,7 @@ String *Item_func_repeat::val_str(String *str)
null_value
=
0
;
null_value
=
0
;
if
(
count
<=
0
&&
(
count
==
0
||
!
args
[
1
]
->
unsigned_flag
))
if
(
count
<=
0
&&
(
count
==
0
||
!
args
[
1
]
->
unsigned_flag
))
return
&
my_empty_string
;
return
make_empty_result
()
;
/* Assumes that the maximum length of a String is < INT_MAX32. */
/* Assumes that the maximum length of a String is < INT_MAX32. */
/* Bounds check on count: If this is triggered, we will error. */
/* Bounds check on count: If this is triggered, we will error. */
...
@@ -2948,7 +2949,7 @@ String *Item_func_conv::val_str(String *str)
...
@@ -2948,7 +2949,7 @@ String *Item_func_conv::val_str(String *str)
ptr
=
longlong2str
(
dec
,
ans
,
to_base
);
ptr
=
longlong2str
(
dec
,
ans
,
to_base
);
if
(
str
->
copy
(
ans
,
(
uint32
)
(
ptr
-
ans
),
default_charset
()))
if
(
str
->
copy
(
ans
,
(
uint32
)
(
ptr
-
ans
),
default_charset
()))
return
&
my_empty_string
;
return
make_empty_result
()
;
return
str
;
return
str
;
}
}
...
@@ -3115,7 +3116,7 @@ String *Item_func_hex::val_str_ascii(String *str)
...
@@ -3115,7 +3116,7 @@ String *Item_func_hex::val_str_ascii(String *str)
return
0
;
return
0
;
ptr
=
longlong2str
(
dec
,
ans
,
16
);
ptr
=
longlong2str
(
dec
,
ans
,
16
);
if
(
str
->
copy
(
ans
,(
uint32
)
(
ptr
-
ans
),
&
my_charset_numeric
))
if
(
str
->
copy
(
ans
,(
uint32
)
(
ptr
-
ans
),
&
my_charset_numeric
))
return
&
my_empty_string
;
// End of memory
return
make_empty_result
();
// End of memory
return
str
;
return
str
;
}
}
...
...
sql/item_strfunc.h
View file @
cecc99db
...
@@ -27,6 +27,16 @@ class MY_LOCALE;
...
@@ -27,6 +27,16 @@ class MY_LOCALE;
class
Item_str_func
:
public
Item_func
class
Item_str_func
:
public
Item_func
{
{
protected:
/**
Sets the result value of the function an empty string, using the current
character set. No memory is allocated.
@retval A pointer to the str_value member.
*/
String
*
make_empty_result
()
{
str_value
.
set
(
""
,
0
,
collation
.
collation
);
return
&
str_value
;
}
public:
public:
Item_str_func
()
:
Item_func
()
{
decimals
=
NOT_FIXED_DEC
;
}
Item_str_func
()
:
Item_func
()
{
decimals
=
NOT_FIXED_DEC
;
}
Item_str_func
(
Item
*
a
)
:
Item_func
(
a
)
{
decimals
=
NOT_FIXED_DEC
;
}
Item_str_func
(
Item
*
a
)
:
Item_func
(
a
)
{
decimals
=
NOT_FIXED_DEC
;
}
...
...
sql/sql_string.cc
View file @
cecc99db
...
@@ -51,11 +51,33 @@ bool String::real_alloc(uint32 length)
...
@@ -51,11 +51,33 @@ bool String::real_alloc(uint32 length)
}
}
/*
/**
** Check that string is big enough. Set string[alloc_length] to 0
Allocates a new buffer on the heap for this String.
** (for C functions)
*/
- If the String's internal buffer is privately owned and heap allocated,
one of the following is performed.
- If the requested length is greater than what fits in the buffer, a new
buffer is allocated, data moved and the old buffer freed.
- If the requested length is less or equal to what fits in the buffer, a
null character is inserted at the appropriate position.
- If the String does not keep a private buffer on the heap, such a buffer
will be allocated and the string copied accoring to its length, as found
in String::length().
For C compatibility, the new string buffer is null terminated.
@param alloc_length The requested string size in characters, excluding any
null terminator.
@retval false Either the copy operation is complete or, if the size of the
new buffer is smaller than the currently allocated buffer (if one exists),
no allocation occured.
@retval true An error occured when attempting to allocate memory.
*/
bool
String
::
realloc
(
uint32
alloc_length
)
bool
String
::
realloc
(
uint32
alloc_length
)
{
{
uint32
len
=
ALIGN_SIZE
(
alloc_length
+
1
);
uint32
len
=
ALIGN_SIZE
(
alloc_length
+
1
);
...
@@ -128,6 +150,17 @@ bool String::copy()
...
@@ -128,6 +150,17 @@ bool String::copy()
return
FALSE
;
return
FALSE
;
}
}
/**
Copies the internal buffer from str. If this String has a private heap
allocated buffer where new data does not fit, a new buffer is allocated
before copying and the old buffer freed. Character set information is also
copied.
@param str The string whose internal buffer is to be copied.
@retval false Success.
@retval true Memory allocation failed.
*/
bool
String
::
copy
(
const
String
&
str
)
bool
String
::
copy
(
const
String
&
str
)
{
{
if
(
alloc
(
str
.
str_length
))
if
(
alloc
(
str
.
str_length
))
...
...
sql/sql_string.h
View file @
cecc99db
...
@@ -148,6 +148,16 @@ class String
...
@@ -148,6 +148,16 @@ class String
Alloced_length
=
0
;
Alloced_length
=
0
;
str_charset
=
str
.
str_charset
;
str_charset
=
str
.
str_charset
;
}
}
/**
Points the internal buffer to the supplied one. The old buffer is freed.
@param str Pointer to the new buffer.
@param arg_length Length of the new buffer in characters, excluding any
null character.
@param cs Character set to use for interpreting string data.
@note The new buffer will not be null terminated.
*/
inline
void
set
(
char
*
str
,
uint32
arg_length
,
CHARSET_INFO
*
cs
)
inline
void
set
(
char
*
str
,
uint32
arg_length
,
CHARSET_INFO
*
cs
)
{
{
free
();
free
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment