Add tensor name to some of the error messages produced by tflite::Verify.

PiperOrigin-RevId: 233640378
This commit is contained in:
A. Unique TensorFlower 2019-02-12 11:06:25 -08:00 committed by TensorFlower Gardener
parent ba941c212d
commit 5f5088767d
2 changed files with 48 additions and 42 deletions

View File

@ -54,7 +54,7 @@ const uint32_t kMaxNumString = UINT_MAX / sizeof(int32_t) - 2;
// Verifies string tensor has legit buffer contents that follow the schema
// defined in lite/string_util.h
bool VerifyStringTensorBuffer(const Buffer& buffer,
bool VerifyStringTensorBuffer(const Tensor& tensor, const Buffer& buffer,
ErrorReporter* error_reporter) {
uint32_t buffer_size = buffer.data()->size();
const char* buffer_ptr = reinterpret_cast<const char*>(buffer.data()->data());
@ -62,7 +62,8 @@ bool VerifyStringTensorBuffer(const Buffer& buffer,
uint32_t num_strings = *GetIntPtr(buffer_ptr);
if (num_strings > kMaxNumString) {
ReportError(error_reporter,
"String tensor has invalid num of string set: %d", num_strings);
"String tensor %s has invalid num of string set: %d",
tensor.name()->c_str(), num_strings);
return false;
}
uint32_t header_offsets =
@ -70,9 +71,9 @@ bool VerifyStringTensorBuffer(const Buffer& buffer,
if (buffer_size < header_offsets) {
ReportError(error_reporter,
"String tensor buffer requires at least %d bytes, but is "
"String tensor %s buffer requires at least %d bytes, but is "
"allocated with %d bytes",
header_offsets, buffer_size);
tensor.name()->c_str(), header_offsets, buffer_size);
return false;
}
@ -81,22 +82,24 @@ bool VerifyStringTensorBuffer(const Buffer& buffer,
if (*GetIntPtr(buffer_ptr + offset) != header_offsets) {
ReportError(error_reporter,
"String tensor buffer initial offset must be: %d",
header_offsets);
"String tensor %s buffer initial offset must be: %d",
tensor.name()->c_str(), header_offsets);
return false;
}
offset += sizeof(int32_t);
for (int i = 1; i <= num_strings; i++, offset += sizeof(int32_t)) {
int string_offset = *GetIntPtr(buffer_ptr + offset);
if (string_offset < prev_ptr || string_offset > buffer_size) {
ReportError(error_reporter, "String tensor buffer is invalid: index %d",
i);
ReportError(error_reporter,
"String tensor %s buffer is invalid: index %d",
tensor.name()->c_str(), i);
return false;
}
}
if (*GetIntPtr(buffer_ptr + offset - sizeof(int32_t)) != buffer_size) {
ReportError(error_reporter, "String tensor buffer last offset must be %d",
buffer_size);
ReportError(error_reporter,
"String tensor %s buffer last offset must be %d",
tensor.name()->c_str(), buffer_size);
return false;
}
return true;
@ -107,13 +110,15 @@ bool VerifyNumericTensorBuffer(const Tensor& tensor, const Buffer& buffer,
ErrorReporter* error_reporter) {
uint64_t bytes_required = 1;
if (!tensor.shape()) {
ReportError(error_reporter, "Tensor shape is empty");
ReportError(error_reporter, "Tensor %s shape is empty",
tensor.name()->c_str());
return false;
}
for (int dim : *tensor.shape()) {
bytes_required *= dim;
if (bytes_required > UINT_MAX) {
ReportError(error_reporter, "Tensor dimension overflow");
ReportError(error_reporter, "Tensor %s dimension overflow",
tensor.name()->c_str());
return false;
}
}
@ -133,19 +138,21 @@ bool VerifyNumericTensorBuffer(const Tensor& tensor, const Buffer& buffer,
case TensorType_FLOAT16:
// FALLTHROUGH_INTENDED;
default:
ReportError(error_reporter, "Invalid tensor type: %d", tensor.type());
ReportError(error_reporter, "Tensor %s invalid type: %d",
tensor.name()->c_str(), tensor.type());
return false;
}
if (bytes_required > UINT_MAX) {
ReportError(error_reporter, "Tensor dimension overflow");
ReportError(error_reporter, "Tensor %s dimension overflow",
tensor.name()->c_str());
return false;
}
if (bytes_required != buffer.data()->size()) {
ReportError(
error_reporter,
"Tensor requires %d bytes, but is allocated with %d bytes buffer",
bytes_required, buffer.data()->size());
"Tensor %s requires %d bytes, but is allocated with %d bytes buffer",
tensor.name()->c_str(), bytes_required, buffer.data()->size());
return false;
}
return true;
@ -299,14 +306,14 @@ bool VerifyTensors(const Model& model, ErrorReporter* error_reporter) {
continue;
}
if (tensor->buffer() >= model.buffers()->size()) {
ReportError(error_reporter, "Invalid tensor buffer index: %d",
tensor->buffer());
ReportError(error_reporter, "Tensor %s invalid buffer index: %d",
tensor->name(), tensor->buffer());
return false;
}
auto* buffer = model.buffers()->Get(tensor->buffer());
if (!buffer) {
ReportError(error_reporter, "Tensor buffer %d not set",
tensor->buffer());
ReportError(error_reporter, "Tensor %s buffer %d not set",
tensor->name(), tensor->buffer());
return false;
}
@ -314,7 +321,7 @@ bool VerifyTensors(const Model& model, ErrorReporter* error_reporter) {
// buffers will be allocated by the interpreter at run-time.
if (buffer->data()) {
if (tensor->type() == TensorType_STRING) {
if (!VerifyStringTensorBuffer(*buffer, error_reporter)) {
if (!VerifyStringTensorBuffer(*tensor, *buffer, error_reporter)) {
return false;
}
} else {

View File

@ -161,7 +161,7 @@ TEST(VerifyModel, TestEmptyShape) {
builder.FinishModel({0, 1}, {3});
ASSERT_FALSE(builder.Verify());
EXPECT_THAT(builder.GetErrorString(),
::testing::ContainsRegex("Tensor shape is empty"));
::testing::ContainsRegex("Tensor inputtwo shape is empty"));
}
TEST(VerifyModel, TestSimpleModel) {
@ -221,10 +221,9 @@ TEST(VerifyModel, TestIntTensorShapeIsGreaterThanBuffer) {
builder.AddTensor({2, 3}, TensorType_UINT8, {1, 2, 3, 4}, "input");
builder.FinishModel({}, {});
ASSERT_FALSE(builder.Verify());
EXPECT_THAT(
builder.GetErrorString(),
::testing::ContainsRegex(
"Tensor requires 6 bytes, but is allocated with 4 bytes buffer"));
EXPECT_THAT(builder.GetErrorString(),
::testing::ContainsRegex("Tensor input requires 6 bytes, but is "
"allocated with 4 bytes buffer"));
}
TEST(VerifyModel, TestIntTensorShapeIsSmallerThanBuffer) {
@ -232,10 +231,9 @@ TEST(VerifyModel, TestIntTensorShapeIsSmallerThanBuffer) {
builder.AddTensor({2, 1}, TensorType_UINT8, {1, 2, 3, 4}, "input");
builder.FinishModel({}, {});
ASSERT_FALSE(builder.Verify());
EXPECT_THAT(
builder.GetErrorString(),
::testing::ContainsRegex(
"Tensor requires 2 bytes, but is allocated with 4 bytes buffer"));
EXPECT_THAT(builder.GetErrorString(),
::testing::ContainsRegex("Tensor input requires 2 bytes, but is "
"allocated with 4 bytes buffer"));
}
TEST(VerifyModel, TestIntTensorShapeOverflow) {
@ -245,7 +243,7 @@ TEST(VerifyModel, TestIntTensorShapeOverflow) {
builder.FinishModel({}, {});
ASSERT_FALSE(builder.Verify());
EXPECT_THAT(builder.GetErrorString(),
::testing::ContainsRegex("Tensor dimension overflow"));
::testing::ContainsRegex("Tensor input dimension overflow"));
}
TEST(VerifyModel, TensorBufferIsNotValid) {
@ -284,10 +282,11 @@ TEST(VerifyModel, StringTensorHasInvalidNumString) {
"input");
builder.FinishModel({}, {});
ASSERT_FALSE(builder.Verify());
EXPECT_THAT(builder.GetErrorString(),
::testing::ContainsRegex(
"String tensor buffer requires at least -2147483640 bytes, "
"but is allocated with 18 bytes"));
EXPECT_THAT(
builder.GetErrorString(),
::testing::ContainsRegex(
"String tensor input buffer requires at least -2147483640 bytes, "
"but is allocated with 18 bytes"));
}
TEST(VerifyModel, StringTensorOffsetTooSmall) {
@ -299,7 +298,7 @@ TEST(VerifyModel, StringTensorOffsetTooSmall) {
ASSERT_FALSE(builder.Verify());
EXPECT_THAT(builder.GetErrorString(),
::testing::ContainsRegex(
"String tensor buffer initial offset must be: 16"));
"String tensor input buffer initial offset must be: 16"));
}
TEST(VerifyModel, StringTensorOffsetOutOfRange) {
@ -309,9 +308,9 @@ TEST(VerifyModel, StringTensorOffsetOutOfRange) {
{2, 0, 0, 0, 16, 0, 0, 0, 17, 0, 0, 0, 22, 0, 0, 0, 'A', 'B'}, "input");
builder.FinishModel({}, {});
ASSERT_FALSE(builder.Verify());
EXPECT_THAT(
builder.GetErrorString(),
::testing::ContainsRegex("String tensor buffer is invalid: index 2"));
EXPECT_THAT(builder.GetErrorString(),
::testing::ContainsRegex(
"String tensor input buffer is invalid: index 2"));
}
TEST(VerifyModel, StringTensorIsLargerThanRequired) {
@ -322,9 +321,9 @@ TEST(VerifyModel, StringTensorIsLargerThanRequired) {
"input");
builder.FinishModel({}, {});
ASSERT_FALSE(builder.Verify());
EXPECT_THAT(
builder.GetErrorString(),
::testing::ContainsRegex("String tensor buffer last offset must be 19"));
EXPECT_THAT(builder.GetErrorString(),
::testing::ContainsRegex(
"String tensor input buffer last offset must be 19"));
}
TEST(VerifyModel, AllOpsAreSupported) {