Safer code for parsing commands
Fix some possible past the end of target string reads Fixes #1310 (maybe, probably, who knows)
This commit is contained in:
parent
34bf8c23e1
commit
5103b15b84
|
@ -51,10 +51,15 @@ public:
|
||||||
Reader(StringView s) : str{s}, pos{}, coord{} {}
|
Reader(StringView s) : str{s}, pos{}, coord{} {}
|
||||||
|
|
||||||
[[gnu::always_inline]]
|
[[gnu::always_inline]]
|
||||||
char operator*() const { return str[pos]; }
|
char operator*() const
|
||||||
|
{
|
||||||
|
kak_assert(pos < str.length());
|
||||||
|
return str[pos];
|
||||||
|
}
|
||||||
|
|
||||||
Reader& operator++()
|
Reader& operator++()
|
||||||
{
|
{
|
||||||
|
kak_assert(pos < str.length());
|
||||||
if (str[pos++] == '\n')
|
if (str[pos++] == '\n')
|
||||||
{
|
{
|
||||||
++coord.line;
|
++coord.line;
|
||||||
|
@ -71,6 +76,7 @@ public:
|
||||||
[[gnu::always_inline]]
|
[[gnu::always_inline]]
|
||||||
StringView substr_from(ByteCount start) const
|
StringView substr_from(ByteCount start) const
|
||||||
{
|
{
|
||||||
|
kak_assert(start <= pos);
|
||||||
return str.substr(start, pos - start);
|
return str.substr(start, pos - start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,6 +213,8 @@ Token parse_percent_token(Reader& reader)
|
||||||
if (throw_on_unterminated and not reader)
|
if (throw_on_unterminated and not reader)
|
||||||
throw parse_error{format("expected a string delimiter after '%{}'",
|
throw parse_error{format("expected a string delimiter after '%{}'",
|
||||||
type_name)};
|
type_name)};
|
||||||
|
else if (not reader)
|
||||||
|
return {};
|
||||||
|
|
||||||
Token::Type type = token_type<throw_on_unterminated>(type_name);
|
Token::Type type = token_type<throw_on_unterminated>(type_name);
|
||||||
|
|
||||||
|
@ -310,9 +318,11 @@ TokenList parse(StringView line)
|
||||||
TokenList result;
|
TokenList result;
|
||||||
|
|
||||||
Reader reader{line};
|
Reader reader{line};
|
||||||
while (reader)
|
while (true)
|
||||||
{
|
{
|
||||||
skip_blanks_and_comments(reader);
|
skip_blanks_and_comments(reader);
|
||||||
|
if (not reader)
|
||||||
|
break;
|
||||||
|
|
||||||
ByteCount start = reader.pos;
|
ByteCount start = reader.pos;
|
||||||
auto coord = reader.coord;
|
auto coord = reader.coord;
|
||||||
|
@ -340,12 +350,14 @@ TokenList parse(StringView line)
|
||||||
if (not str.empty())
|
if (not str.empty())
|
||||||
result.emplace_back(Token::Type::Raw, start, reader.pos,
|
result.emplace_back(Token::Type::Raw, start, reader.pos,
|
||||||
coord, unescape(str, "%", '\\'));
|
coord, unescape(str, "%", '\\'));
|
||||||
|
|
||||||
|
if (not reader or is_command_separator(*reader))
|
||||||
|
result.emplace_back(Token::Type::CommandSeparator,
|
||||||
|
reader.pos, reader.pos+1, coord);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_command_separator(*reader))
|
if (not reader)
|
||||||
result.emplace_back(Token::Type::CommandSeparator,
|
break;
|
||||||
reader.pos, reader.pos+1, coord);
|
|
||||||
|
|
||||||
++reader;
|
++reader;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user