Start doing more validation of intrinsics: assert, new, delete, rand (#2766)

This is adding more validation of intrinsics. It addresses a bug in rand where CHECK-fails would occur for bad range inputs, instead of a runtime error. I'm also addressing what I think was an int32 range issue in the handling by running the generator with int64.
This commit is contained in:
Jon Ross-Perkins
2023-04-13 12:53:34 -07:00
committed by GitHub
parent d52836e854
commit d7978deb3a
23 changed files with 360 additions and 20 deletions
+17 -6
View File
@@ -7,6 +7,7 @@
#include <llvm/Support/raw_ostream.h>
#include <iterator>
#include <limits>
#include <map>
#include <memory>
#include <optional>
@@ -40,8 +41,6 @@ using llvm::isa;
namespace Carbon {
static std::mt19937 generator(12);
// Constructs an ActionStack suitable for the specified phase.
static auto MakeTodo(Phase phase, Nonnull<Heap*> heap) -> ActionStack {
switch (phase) {
@@ -1593,12 +1592,24 @@ auto Interpreter::StepExp() -> ErrorOr<Success> {
}
case IntrinsicExpression::Intrinsic::Rand: {
CARBON_CHECK(args.size() == 2);
const auto& low = cast<IntValue>(*args[0]).value();
const auto& high = cast<IntValue>(*args[1]).value();
CARBON_CHECK(high > low);
const int64_t low = cast<IntValue>(*args[0]).value();
const int64_t high = cast<IntValue>(*args[1]).value();
if (low >= high) {
return ProgramError(exp.source_loc())
<< "Rand inputs must be ordered for a non-empty range: "
<< low << " must be less than " << high;
}
// Use 64-bit to handle large ranges where `high - low` might exceed
// int32_t maximums.
static std::mt19937_64 generator(12);
const int64_t range = high - low;
// We avoid using std::uniform_int_distribution because it's not
// reproducible across builds/platforms.
int r = (generator() % (high - low)) + low;
int64_t r = (generator() % range) + low;
CARBON_CHECK(r >= std::numeric_limits<int32_t>::min() &&
r <= std::numeric_limits<int32_t>::max())
<< "Non-int32 result: " << r;
CARBON_CHECK(r >= low && r <= high) << "Out-of-range result: " << r;
return todo_.FinishAction(arena_->New<IntValue>(r));
}
case IntrinsicExpression::Intrinsic::ImplicitAs: {