Skip to content

Commit e08f2ae

Browse files
committed
Fix QASM parser integer overflows when handling large literals
1 parent be13a59 commit e08f2ae

1 file changed

Lines changed: 48 additions & 5 deletions

File tree

include/nwqec/parser/ast_generator.hpp

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <string>
88
#include <stdexcept>
99
#include <unordered_map>
10+
#include <limits>
1011

1112
namespace NWQEC
1213
{
@@ -229,14 +230,56 @@ namespace NWQEC
229230
return std::make_unique<IncludeStmt>(filename);
230231
}
231232

233+
size_t parse_register_size(const Token &size_token)
234+
{
235+
try
236+
{
237+
unsigned long long raw = std::stoull(size_token.lexeme);
238+
if (raw > std::numeric_limits<size_t>::max())
239+
{
240+
throw ParseError("Register size " + size_token.lexeme + " exceeds supported range.",
241+
size_token.line, size_token.column);
242+
}
243+
return static_cast<size_t>(raw);
244+
}
245+
catch (const std::invalid_argument &)
246+
{
247+
throw ParseError("Invalid register size: " + size_token.lexeme + ".",
248+
size_token.line, size_token.column);
249+
}
250+
catch (const std::out_of_range &)
251+
{
252+
throw ParseError("Register size " + size_token.lexeme + " is out of range.",
253+
size_token.line, size_token.column);
254+
}
255+
}
256+
257+
long long parse_integer_literal(const Token &token)
258+
{
259+
try
260+
{
261+
return std::stoll(token.lexeme);
262+
}
263+
catch (const std::invalid_argument &)
264+
{
265+
throw ParseError("Invalid integer literal: " + token.lexeme + ".",
266+
token.line, token.column);
267+
}
268+
catch (const std::out_of_range &)
269+
{
270+
throw ParseError("Integer literal " + token.lexeme + " is out of range.",
271+
token.line, token.column);
272+
}
273+
}
274+
232275
std::unique_ptr<Stmt> qreg_declaration()
233276
{
234277
Token name_token = consume(TokenType::IDENTIFIER, "Expected register name after qreg.");
235278
std::string name = name_token.lexeme;
236279

237280
consume(TokenType::LBRACKET, "Expected '[' after register name.");
238281
Token size_token = consume(TokenType::INTEGER, "Expected size after '['.");
239-
int size = std::stoi(size_token.lexeme);
282+
size_t size = parse_register_size(size_token);
240283
consume(TokenType::RBRACKET, "Expected ']' after size.");
241284
consume(TokenType::SEMICOLON, "Expected ';' after register declaration.");
242285

@@ -250,7 +293,7 @@ namespace NWQEC
250293

251294
consume(TokenType::LBRACKET, "Expected '[' after register name.");
252295
Token size_token = consume(TokenType::INTEGER, "Expected size after '['.");
253-
int size = std::stoi(size_token.lexeme);
296+
size_t size = parse_register_size(size_token);
254297
consume(TokenType::RBRACKET, "Expected ']' after size.");
255298
consume(TokenType::SEMICOLON, "Expected ';' after register declaration.");
256299

@@ -419,7 +462,7 @@ namespace NWQEC
419462

420463
std::unique_ptr<Stmt> then_branch = statement();
421464

422-
return std::make_unique<IfStmt>(creg_token.lexeme, std::stoi(value_token.lexeme), std::move(then_branch));
465+
return std::make_unique<IfStmt>(creg_token.lexeme, parse_integer_literal(value_token), std::move(then_branch));
423466
}
424467

425468
std::unique_ptr<Stmt> block_statement()
@@ -594,7 +637,7 @@ namespace NWQEC
594637
{
595638
if (match({TokenType::INTEGER}))
596639
{
597-
int value = std::stoi(previous().lexeme);
640+
long long value = parse_integer_literal(previous());
598641
return std::make_unique<NumberExpr>(static_cast<double>(value), true);
599642
}
600643

@@ -644,4 +687,4 @@ namespace NWQEC
644687
}
645688
};
646689

647-
} // namespace NWQEC
690+
} // namespace NWQEC

0 commit comments

Comments
 (0)