mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-24 08:32:02 +00:00
Safer readInt
This commit is contained in:
parent
9edfc1641a
commit
6f12781bf1
@ -270,16 +270,37 @@ ReturnType readIntTextImpl(T & x, ReadBuffer & buf)
|
||||
}
|
||||
|
||||
const size_t initial_pos = buf.count();
|
||||
bool has_sign = false;
|
||||
bool has_number = false;
|
||||
while (!buf.eof())
|
||||
{
|
||||
switch (*buf.position())
|
||||
{
|
||||
case '+':
|
||||
{
|
||||
if (has_sign || has_number)
|
||||
{
|
||||
if constexpr (throw_exception)
|
||||
throw ParsingException(
|
||||
"Cannot parse number with multiple sign (+/-) characters or intermediate sign character",
|
||||
ErrorCodes::CANNOT_PARSE_NUMBER);
|
||||
else
|
||||
return ReturnType(false);
|
||||
}
|
||||
has_sign = true;
|
||||
break;
|
||||
}
|
||||
case '-':
|
||||
{
|
||||
if (has_sign || has_number)
|
||||
{
|
||||
if constexpr (throw_exception)
|
||||
throw ParsingException(
|
||||
"Cannot parse number with multiple sign (+/-) characters or intermediate sign character",
|
||||
ErrorCodes::CANNOT_PARSE_NUMBER);
|
||||
else
|
||||
return ReturnType(false);
|
||||
}
|
||||
if constexpr (is_signed_v<T>)
|
||||
negative = true;
|
||||
else
|
||||
@ -289,6 +310,7 @@ ReturnType readIntTextImpl(T & x, ReadBuffer & buf)
|
||||
else
|
||||
return ReturnType(false);
|
||||
}
|
||||
has_sign = true;
|
||||
break;
|
||||
}
|
||||
case '0': [[fallthrough]];
|
||||
@ -302,6 +324,7 @@ ReturnType readIntTextImpl(T & x, ReadBuffer & buf)
|
||||
case '8': [[fallthrough]];
|
||||
case '9':
|
||||
{
|
||||
has_number = true;
|
||||
if constexpr (check_overflow == ReadIntTextCheckOverflow::CHECK_OVERFLOW && !is_big_int_v<T>)
|
||||
{
|
||||
/// Perform relativelly slow overflow check only when
|
||||
@ -330,6 +353,14 @@ ReturnType readIntTextImpl(T & x, ReadBuffer & buf)
|
||||
}
|
||||
|
||||
end:
|
||||
if (has_sign && !has_number)
|
||||
{
|
||||
if constexpr (throw_exception)
|
||||
throw ParsingException(
|
||||
"Cannot parse number with a sign character but without any numeric character", ErrorCodes::CANNOT_PARSE_NUMBER);
|
||||
else
|
||||
return ReturnType(false);
|
||||
}
|
||||
x = res;
|
||||
if constexpr (is_signed_v<T>)
|
||||
{
|
||||
|
12
tests/performance/string_to_int.xml
Normal file
12
tests/performance/string_to_int.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<test>
|
||||
<create_query>DROP TABLE IF EXISTS numeric_strings</create_query>
|
||||
<create_query>CREATE TABLE numeric_strings(num String) ENGINE Memory</create_query>
|
||||
|
||||
<fill_query>
|
||||
INSERT INTO numeric_strings SELECT number FROM numbers(30000000)
|
||||
</fill_query>
|
||||
|
||||
<query short="1">SELECT count(num::Int64) FROM numeric_strings FORMAT Null</query>
|
||||
|
||||
<drop_query>DROP TABLE IF EXISTS numeric_strings</drop_query>
|
||||
</test>
|
@ -8,8 +8,8 @@ $CLICKHOUSE_CLIENT -q "DROP TABLE IF EXISTS empty_strings_deserialization"
|
||||
$CLICKHOUSE_CLIENT -q "CREATE TABLE empty_strings_deserialization(s String, i Int32, f Float32) ENGINE Memory"
|
||||
|
||||
echo ',,' | $CLICKHOUSE_CLIENT -q "INSERT INTO empty_strings_deserialization FORMAT CSV"
|
||||
echo 'aaa,-,' | $CLICKHOUSE_CLIENT -q "INSERT INTO empty_strings_deserialization FORMAT CSV"
|
||||
echo 'bbb,,-' | $CLICKHOUSE_CLIENT -q "INSERT INTO empty_strings_deserialization FORMAT CSV"
|
||||
echo 'aaa,,' | $CLICKHOUSE_CLIENT -q "INSERT INTO empty_strings_deserialization FORMAT CSV"
|
||||
echo 'bbb,,-0' | $CLICKHOUSE_CLIENT -q "INSERT INTO empty_strings_deserialization FORMAT CSV"
|
||||
|
||||
$CLICKHOUSE_CLIENT -q "SELECT * FROM empty_strings_deserialization ORDER BY s"
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
SELECT '-1E9-1E9-1E9-1E9' AS x, toDecimal32(x, 0); -- { serverError 6 }
|
||||
SELECT '-1E9-1E9-1E9-1E9' AS x, toDecimal32(x, 0); -- { serverError 72 }
|
||||
SELECT '-1E9' AS x, toDecimal32(x, 0); -- { serverError 69 }
|
||||
SELECT '1E-9' AS x, toDecimal32(x, 0);
|
||||
SELECT '1E-8' AS x, toDecimal32(x, 0);
|
||||
|
2
tests/queries/0_stateless/01888_read_int_safe.reference
Normal file
2
tests/queries/0_stateless/01888_read_int_safe.reference
Normal file
@ -0,0 +1,2 @@
|
||||
1
|
||||
-1
|
10
tests/queries/0_stateless/01888_read_int_safe.sql
Normal file
10
tests/queries/0_stateless/01888_read_int_safe.sql
Normal file
@ -0,0 +1,10 @@
|
||||
select toInt64('--1'); -- { serverError 72; }
|
||||
select toInt64('+-1'); -- { serverError 72; }
|
||||
select toInt64('++1'); -- { serverError 72; }
|
||||
select toInt64('++'); -- { serverError 72; }
|
||||
select toInt64('+'); -- { serverError 72; }
|
||||
select toInt64('1+1'); -- { serverError 72; }
|
||||
select toInt64('1-1'); -- { serverError 72; }
|
||||
select toInt64(''); -- { serverError 32; }
|
||||
select toInt64('1');
|
||||
select toInt64('-1');
|
Loading…
Reference in New Issue
Block a user