Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions include/utils/errors.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@
#define ERRORS_H

#include <sstream>
#include <limits>
#include <cstdint>
#include <charconv>
#include <string_view>
#include <system_error>

enum class ReturnValue {
SuccessCode = 0,
Expand Down Expand Up @@ -66,4 +71,34 @@ struct base_error : public std::exception {
}
};

inline uint32_t toBoundedTokenCount(uint64_t count) {
if (count > std::numeric_limits<uint32_t>::max()) {
throw base_error("Number of tokens exceeded ", std::numeric_limits<uint32_t>::max());
}
return static_cast<uint32_t>(count);
}

inline int32_t parse_bounded_int32(std::string_view text) {
if (text.empty()) {
throw base_error("Expected an integer constant, got \"\"");
}

int32_t value = 0;
const char* const first = text.data();
const char* const last = first + text.size();
const std::from_chars_result result = std::from_chars(first, last, value);
if (result.ec == std::errc::invalid_argument || result.ptr == first || result.ptr != last) {
throw base_error("Expected an integer constant, got \"", text, "\"");
}
if (result.ec == std::errc::result_out_of_range) {
if (text.front() == '-') {
throw base_error("Integer constant ", text, " is less than ",
std::numeric_limits<int32_t>::min());
}
throw base_error("Integer constant ", text, " exceeded ",
std::numeric_limits<int32_t>::max());
}
return value;
}

#endif /* ERRORS_H */
6 changes: 3 additions & 3 deletions src/PetriEngine/Colored/Multiset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ namespace PetriEngine {
: _set(), _type(nullptr)
{
for (auto& c : colors) {
(*this)[c.first] += c.second;
(*this)[c.first] = toBoundedTokenCount(static_cast<uint64_t>((*this)[c.first]) + c.second);
}
}

Expand Down Expand Up @@ -65,7 +65,7 @@ namespace PetriEngine {
const Color* color = &(*ColorType::dotInstance()->begin());
if (_type != nullptr)
color = &((*_type)[c.first]);
(*this)[color] += c.second;
(*this)[color] = toBoundedTokenCount(static_cast<uint64_t>((*this)[color]) + c.second);
}
}

Expand All @@ -86,7 +86,7 @@ namespace PetriEngine {

void Multiset::operator *=(uint32_t scalar) {
for (auto& c : _set) {
c.second *= scalar;
c.second = toBoundedTokenCount(static_cast<uint64_t>(c.second) * scalar);
}
}

Expand Down
5 changes: 4 additions & 1 deletion src/PetriEngine/PQL/PQLQueryParser.y
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,10 @@ term : term MULTIPLY factor { $$ = new MultiplyExpr(std::vector<Expr_ptr>({Expr_
;

factor : LPAREN expr RPAREN { $$ = $2; }
| INT { $$ = new LiteralExpr(atol($1->c_str())); delete $1; }
| INT {
std::unique_ptr<std::string> token($1);
$$ = new LiteralExpr(parse_bounded_int32(*token));
}
| named { $$ = $1; }
;

Expand Down
2 changes: 1 addition & 1 deletion src/PetriParse/PNMLParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1005,7 +1005,7 @@ void PNMLParser::parseValue(rapidxml::xml_node<>* element, std::string& text) {
uint32_t PNMLParser::parseNumberConstant(rapidxml::xml_node<>* element) {
if (strcmp(element->name(), "numberconstant") == 0) {
auto value = element->first_attribute("value")->value();
return (uint32_t)atoll(value);
return toBoundedTokenCount(static_cast<uint64_t>(atoll(value)));
} else if (strcmp(element->name(), "subterm") == 0) {
return parseNumberConstant(element->first_node());
}
Expand Down
8 changes: 1 addition & 7 deletions src/PetriParse/QueryXMLParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -466,13 +466,7 @@ Condition_ptr QueryXMLParser::parseBooleanFormula(rapidxml::xml_node<>* element
Expr_ptr QueryXMLParser::parseIntegerExpression(rapidxml::xml_node<>* element) {
std::string elementName = element->name();
if (elementName == "integer-constant") {
int i;
if (sscanf(element->value(), "%d", &i) == EOF)
{
assert(false);
return nullptr;
}
return std::make_shared<LiteralExpr>(i);
return std::make_shared<LiteralExpr>(parse_bounded_int32(element->value()));
} else if (elementName == "tokens-count") {
auto children = element->first_node();
std::vector<Expr_ptr> ids;
Expand Down
Loading