Fix buffer overflow in parser

This commit is contained in:
Alexey Milovidov 2023-01-09 03:31:12 +01:00
parent 4fd22ed515
commit d331f0ce82
4 changed files with 18 additions and 21 deletions

View File

@ -1,13 +1,12 @@
#include <Access/Common/QuotaDefs.h>
#include <Common/Exception.h>
#include <base/range.h>
#include <IO/ReadHelpers.h>
#include <IO/WriteHelpers.h>
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/lexical_cast.hpp>
namespace DB
@ -29,15 +28,15 @@ String QuotaTypeInfo::valueToString(QuotaValue value) const
if (!(value % output_denominator))
return std::to_string(value / output_denominator);
else
return boost::lexical_cast<std::string>(static_cast<double>(value) / output_denominator);
return toString(static_cast<double>(value) / output_denominator);
}
QuotaValue QuotaTypeInfo::stringToValue(const String & str) const
{
if (output_denominator == 1)
return static_cast<QuotaValue>(std::strtoul(str.c_str(), nullptr, 10));
return static_cast<QuotaValue>(parse<UInt64>(str));
else
return static_cast<QuotaValue>(std::strtod(str.c_str(), nullptr) * output_denominator);
return static_cast<QuotaValue>(parse<Float64>(str) * output_denominator);
}
String QuotaTypeInfo::valueToStringWithName(QuotaValue value) const

View File

@ -144,7 +144,7 @@ bool assertOrParseNaN(ReadBuffer & buf)
template <typename T, typename ReturnType>
ReturnType readFloatTextPreciseImpl(T & x, ReadBuffer & buf)
{
static_assert(std::is_same_v<T, double> || std::is_same_v<T, float>, "Argument for readFloatTextFastFloatImpl must be float or double");
static_assert(std::is_same_v<T, double> || std::is_same_v<T, float>, "Argument for readFloatTextPreciseImpl must be float or double");
static_assert('a' > '.' && 'A' > '.' && '\n' < '.' && '\t' < '.' && '\'' < '.' && '"' < '.', "Layout of char is not like ASCII"); //-V590
static constexpr bool throw_exception = std::is_same_v<ReturnType, void>;

View File

@ -1,15 +1,14 @@
#include <cerrno>
#include <cstdlib>
#include <Poco/String.h>
#include <IO/ReadBufferFromMemory.h>
#include <IO/ReadHelpers.h>
#include <Parsers/DumpASTNode.h>
#include <IO/readFloatText.h>
#include <Common/typeid_cast.h>
#include <Common/StringUtils/StringUtils.h>
#include <Common/BinStringDecodeHelper.h>
#include <Parsers/DumpASTNode.h>
#include <Parsers/ASTAsterisk.h>
#include <Parsers/ASTCollation.h>
#include <Parsers/ASTColumnsTransformers.h>
@ -29,22 +28,17 @@
#include <Parsers/ASTAssignment.h>
#include <Parsers/ASTColumnsMatcher.h>
#include <Parsers/ASTExplainQuery.h>
#include <Parsers/ASTSelectQuery.h>
#include <Parsers/ASTTablesInSelectQuery.h>
#include <Parsers/parseIdentifierOrStringLiteral.h>
#include <Parsers/parseIntervalKind.h>
#include <Parsers/ExpressionListParsers.h>
#include <Parsers/IAST_fwd.h>
#include <Parsers/ParserSelectWithUnionQuery.h>
#include <Parsers/ParserCase.h>
#include <Parsers/ExpressionElementParsers.h>
#include <Parsers/ParserCreateQuery.h>
#include <Parsers/ParserExplainQuery.h>
#include <Parsers/queryToString.h>
#include <Interpreters/StorageID.h>
@ -834,10 +828,9 @@ bool ParserNumber::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
auto try_read_float = [&](const char * it, const char * end)
{
char * str_end;
errno = 0; /// Functions strto* don't clear errno.
Float64 float_value = std::strtod(it, &str_end);
if (str_end == end && errno != ERANGE)
Float64 float_value = 0;
ReadBufferFromMemory buf(it, end - it);
if (tryReadFloatTextPrecise(float_value, buf))
{
if (float_value < 0)
throw Exception("Logical error: token number cannot begin with minus, but parsed float number is less than zero.", ErrorCodes::LOGICAL_ERROR);
@ -882,7 +875,10 @@ bool ParserNumber::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
for (const auto * it = pos->begin; it != pos->end; ++it)
{
if (*it != '_')
buf[buf_size++] = *it;
{
buf[buf_size] = *it;
++buf_size;
}
if (unlikely(buf_size > MAX_LENGTH_OF_NUMBER))
{
expected.add(pos, "number");

View File

@ -553,7 +553,9 @@ bool ConstantExpressionTemplate::parseLiteralAndAssertType(
{
Field number;
if (type_info.is_nullable && 4 <= istr.available() && 0 == strncasecmp(istr.position(), "NULL", 4))
{
istr.position() += 4;
}
else
{
/// ParserNumber::parse(...) is about 20x slower than strtod(...)