Skip to content

Commit a183dee

Browse files
author
Amit Patankar
authored
Merge pull request tensorflow#18812 from tensorflow/frankchn-r1.7
Patches for Release 1.7
2 parents 8993865 + 22d3066 commit a183dee

File tree

17 files changed

+405
-116
lines changed

17 files changed

+405
-116
lines changed

tensorflow/compiler/tf2xla/tf2xla_test.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,11 @@ TEST(ConvertGraphDefToXla, Sum) {
9090
TF_EXPECT_OK(result_or.status());
9191
std::unique_ptr<xla::Literal> result = std::move(result_or.ValueOrDie());
9292
EXPECT_EQ("(s32[]) (\n42\n)", result->ToString());
93+
94+
config.mutable_feed(0)->mutable_id()->set_output_index(
95+
123); /* invalid output_index */
96+
EXPECT_TRUE(errors::IsInvalidArgument(
97+
ConvertGraphDefToXla(graph_def, config, client, &computation)));
9398
}
9499

95100
} // namespace

tensorflow/compiler/tf2xla/tf2xla_util.cc

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,15 @@ Status AddPlaceholdersForFeeds(
151151
Status status;
152152
Node* feed_node = g.AddNode(gd.node(0), &status);
153153
TF_RETURN_IF_ERROR(status);
154-
info.data_type =
155-
BaseType(feed_node->output_type(info.feed->id().output_index()));
154+
155+
if (info.feed->id().output_index() < feed_node->num_outputs()) {
156+
info.data_type =
157+
BaseType(feed_node->output_type(info.feed->id().output_index()));
158+
} else {
159+
return errors::InvalidArgument(
160+
"Invalid output_index ", info.feed->id().output_index(),
161+
" for feed node ", info.feed->id().node_name());
162+
}
156163
}
157164
}
158165

tensorflow/contrib/lite/toco/graph_transformations/propagate_fixed_sizes.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@ void ComputeConvSizes(const Shape& input_shape, int output_depth, int kwidth,
3838
const int input_height = input_shape.dims(1);
3939
const int batch = input_shape.dims(0);
4040

41+
CHECK_GE(input_width, 1);
42+
CHECK_GE(input_height, 1);
43+
CHECK_GE(batch, 1);
44+
CHECK_GE(kwidth, 1);
45+
CHECK_GE(kheight, 1);
46+
CHECK_GE(stride_width, 1);
47+
CHECK_GE(stride_height, 1);
48+
CHECK_GE(dilation_width_factor, 1);
49+
CHECK_GE(dilation_height_factor, 1);
50+
4151
int dilated_kwidth = dilation_width_factor * (kwidth - 1) + 1;
4252
int dilated_kheight = dilation_height_factor * (kheight - 1) + 1;
4353

tensorflow/contrib/lite/toco/tensorflow_graph_matching/resolve_cluster.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,9 @@ std::unique_ptr<GraphDef> MaybeReplaceCompositeSubgraph(
144144
MaybeResolveClusters(tf_graph, cluster_factories);
145145

146146
// Copy function definitions
147-
*(pruned_graph->mutable_library()) = tf_graph.library();
147+
if (pruned_graph) {
148+
*(pruned_graph->mutable_library()) = tf_graph.library();
149+
}
148150
return pruned_graph;
149151
}
150152

tensorflow/contrib/lite/toco/tflite/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,11 @@ cc_library(
115115
deps = [
116116
":operator",
117117
":types",
118+
"//tensorflow/contrib/lite:framework",
118119
"//tensorflow/contrib/lite/schema:schema_fbs",
119120
"//tensorflow/contrib/lite/toco:model",
120121
"//tensorflow/contrib/lite/toco:tooling_util",
122+
"//tensorflow/contrib/lite/tools:verifier",
121123
"@flatbuffers",
122124
],
123125
)

tensorflow/contrib/lite/toco/tflite/import.cc

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@ limitations under the License.
1515
#include "tensorflow/contrib/lite/toco/tflite/import.h"
1616

1717
#include "flatbuffers/flexbuffers.h"
18+
#include "tensorflow/contrib/lite/model.h"
1819
#include "tensorflow/contrib/lite/schema/schema_generated.h"
1920
#include "tensorflow/contrib/lite/toco/tflite/operator.h"
2021
#include "tensorflow/contrib/lite/toco/tflite/types.h"
2122
#include "tensorflow/contrib/lite/toco/tooling_util.h"
23+
#include "tensorflow/contrib/lite/tools/verifier.h"
2224

2325
namespace toco {
2426

@@ -162,16 +164,28 @@ void ImportIOTensors(const ::tflite::Model& input_model,
162164
}
163165
}
164166

167+
namespace {
168+
bool Verify(const void* buf, size_t len) {
169+
::flatbuffers::Verifier verifier(static_cast<const uint8_t*>(buf), len);
170+
return ::tflite::VerifyModelBuffer(verifier);
171+
}
172+
} // namespace
173+
165174
std::unique_ptr<Model> Import(const ModelFlags& model_flags,
166175
const string& input_file_contents) {
176+
::tflite::AlwaysTrueResolver r;
177+
if (!::tflite::Verify(input_file_contents.data(), input_file_contents.size(),
178+
r, ::tflite::DefaultErrorReporter())) {
179+
LOG(FATAL) << "Invalid flatbuffer.";
180+
}
167181
const ::tflite::Model* input_model =
168182
::tflite::GetModel(input_file_contents.data());
169183

170184
// Full list of all known operators.
171185
const auto ops_by_name = BuildOperatorByNameMap();
172186

173-
if (input_model->subgraphs()->size() != 1) {
174-
LOG(FATAL) << "# of subgraphs in tflite should be exactly 1 for now.";
187+
if (!input_model->subgraphs() || input_model->subgraphs()->size() != 1) {
188+
LOG(FATAL) << "Number of subgraphs in tflite should be exactly 1.";
175189
}
176190
std::unique_ptr<Model> model;
177191
model.reset(new Model);

tensorflow/contrib/lite/toco/tflite/import_test.cc

Lines changed: 164 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -27,60 +27,110 @@ namespace {
2727

2828
using ::testing::ElementsAre;
2929

30+
using flatbuffers::Offset;
31+
using flatbuffers::Vector;
3032
class ImportTest : public ::testing::Test {
3133
protected:
3234
template <typename T>
33-
flatbuffers::Offset<flatbuffers::Vector<unsigned char>> CreateDataVector(
34-
const std::vector<T>& data) {
35+
Offset<Vector<unsigned char>> CreateDataVector(const std::vector<T>& data) {
3536
return builder_.CreateVector(reinterpret_cast<const uint8_t*>(data.data()),
3637
sizeof(T) * data.size());
3738
}
38-
// This is a very simplistic model. We are not interested in testing all the
39-
// details here, since tf.mini's testing framework will be exercising all the
40-
// conversions multiple times, and the conversion of operators is tested by
41-
// separate unittests.
42-
void BuildTestModel() {
43-
// The tensors
39+
40+
Offset<Vector<Offset<::tflite::Buffer>>> BuildBuffers() {
41+
auto buf0 = ::tflite::CreateBuffer(builder_, CreateDataVector<float>({}));
42+
auto buf1 = ::tflite::CreateBuffer(
43+
builder_, CreateDataVector<float>({1.0f, 2.0f, 3.0f, 4.0f}));
44+
auto buf2 =
45+
::tflite::CreateBuffer(builder_, CreateDataVector<float>({3.0f, 4.0f}));
46+
return builder_.CreateVector(
47+
std::vector<Offset<::tflite::Buffer>>({buf0, buf1, buf2}));
48+
}
49+
50+
Offset<Vector<Offset<::tflite::Tensor>>> BuildTensors() {
4451
auto q = ::tflite::CreateQuantizationParameters(
4552
builder_,
4653
/*min=*/builder_.CreateVector<float>({0.1f}),
4754
/*max=*/builder_.CreateVector<float>({0.2f}),
4855
/*scale=*/builder_.CreateVector<float>({0.3f}),
4956
/*zero_point=*/builder_.CreateVector<int64_t>({100ll}));
50-
auto buf0 = ::tflite::CreateBuffer(builder_, CreateDataVector<float>({}));
51-
auto buf1 =
52-
::tflite::CreateBuffer(builder_, CreateDataVector<float>({1.0f, 2.0f}));
53-
auto buf2 =
54-
::tflite::CreateBuffer(builder_, CreateDataVector<float>({3.0f}));
55-
auto buffers = builder_.CreateVector(
56-
std::vector<flatbuffers::Offset<::tflite::Buffer>>({buf0, buf1, buf2}));
57-
auto t1 = ::tflite::CreateTensor(builder_,
58-
builder_.CreateVector<int>({1, 2, 3, 4}),
59-
::tflite::TensorType_FLOAT32, 1,
60-
builder_.CreateString("tensor_one"), q);
57+
auto t1 =
58+
::tflite::CreateTensor(builder_, builder_.CreateVector<int>({1, 2, 2}),
59+
::tflite::TensorType_FLOAT32, 1,
60+
builder_.CreateString("tensor_one"), q);
6161
auto t2 =
6262
::tflite::CreateTensor(builder_, builder_.CreateVector<int>({2, 1}),
6363
::tflite::TensorType_FLOAT32, 2,
6464
builder_.CreateString("tensor_two"), q);
65-
auto tensors = builder_.CreateVector(
66-
std::vector<flatbuffers::Offset<::tflite::Tensor>>({t1, t2}));
67-
68-
// The operator codes.
69-
auto c1 =
70-
::tflite::CreateOperatorCode(builder_, ::tflite::BuiltinOperator_CUSTOM,
71-
builder_.CreateString("custom_op_one"));
72-
auto c2 = ::tflite::CreateOperatorCode(
73-
builder_, ::tflite::BuiltinOperator_CONV_2D, 0);
74-
auto opcodes = builder_.CreateVector(
75-
std::vector<flatbuffers::Offset<::tflite::OperatorCode>>({c1, c2}));
76-
77-
auto subgraph = ::tflite::CreateSubGraph(builder_, tensors, 0, 0, 0);
78-
std::vector<flatbuffers::Offset<::tflite::SubGraph>> subgraph_vector(
79-
{subgraph});
80-
auto subgraphs = builder_.CreateVector(subgraph_vector);
65+
return builder_.CreateVector(
66+
std::vector<Offset<::tflite::Tensor>>({t1, t2}));
67+
}
68+
69+
Offset<Vector<Offset<::tflite::OperatorCode>>> BuildOpCodes(
70+
std::initializer_list<::tflite::BuiltinOperator> op_codes) {
71+
std::vector<Offset<::tflite::OperatorCode>> op_codes_vector;
72+
for (auto op : op_codes) {
73+
op_codes_vector.push_back(::tflite::CreateOperatorCode(builder_, op, 0));
74+
}
75+
return builder_.CreateVector(op_codes_vector);
76+
}
77+
78+
Offset<Vector<Offset<::tflite::OperatorCode>>> BuildOpCodes() {
79+
return BuildOpCodes({::tflite::BuiltinOperator_MAX_POOL_2D,
80+
::tflite::BuiltinOperator_CONV_2D});
81+
}
82+
83+
Offset<Vector<Offset<::tflite::Operator>>> BuildOperators(
84+
std::initializer_list<int> inputs, std::initializer_list<int> outputs) {
85+
auto is = builder_.CreateVector<int>(inputs);
86+
if (inputs.size() == 0) is = 0;
87+
auto os = builder_.CreateVector<int>(outputs);
88+
if (outputs.size() == 0) os = 0;
89+
auto op = ::tflite::CreateOperator(
90+
builder_, 0, is, os, ::tflite::BuiltinOptions_Conv2DOptions,
91+
::tflite::CreateConv2DOptions(builder_, ::tflite::Padding_VALID, 1, 1,
92+
::tflite::ActivationFunctionType_NONE)
93+
.Union(),
94+
/*custom_options=*/0, ::tflite::CustomOptionsFormat_FLEXBUFFERS);
95+
96+
return builder_.CreateVector(std::vector<Offset<::tflite::Operator>>({op}));
97+
}
98+
99+
Offset<Vector<Offset<::tflite::Operator>>> BuildOperators() {
100+
return BuildOperators({0}, {1});
101+
}
102+
103+
Offset<Vector<Offset<::tflite::SubGraph>>> BuildSubGraphs(
104+
Offset<Vector<Offset<::tflite::Tensor>>> tensors,
105+
Offset<Vector<Offset<::tflite::Operator>>> operators,
106+
int num_sub_graphs = 1) {
107+
std::vector<int32_t> inputs = {0};
108+
std::vector<int32_t> outputs = {1};
109+
std::vector<Offset<::tflite::SubGraph>> v;
110+
for (int i = 0; i < num_sub_graphs; ++i) {
111+
v.push_back(::tflite::CreateSubGraph(
112+
builder_, tensors, builder_.CreateVector(inputs),
113+
builder_.CreateVector(outputs), operators,
114+
builder_.CreateString("subgraph")));
115+
}
116+
return builder_.CreateVector(v);
117+
}
118+
119+
// This is a very simplistic model. We are not interested in testing all the
120+
// details here, since tf.mini's testing framework will be exercising all the
121+
// conversions multiple times, and the conversion of operators is tested by
122+
// separate unittests.
123+
void BuildTestModel() {
124+
auto buffers = BuildBuffers();
125+
auto tensors = BuildTensors();
126+
auto opcodes = BuildOpCodes();
127+
auto operators = BuildOperators();
128+
auto subgraphs = BuildSubGraphs(tensors, operators);
81129
auto s = builder_.CreateString("");
82-
builder_.Finish(::tflite::CreateModel(builder_, TFLITE_SCHEMA_VERSION,
83-
opcodes, subgraphs, s, buffers));
130+
131+
::tflite::FinishModelBuffer(
132+
builder_, ::tflite::CreateModel(builder_, TFLITE_SCHEMA_VERSION,
133+
opcodes, subgraphs, s, buffers));
84134

85135
input_model_ = ::tflite::GetModel(builder_.GetBufferPointer());
86136
}
@@ -89,7 +139,6 @@ class ImportTest : public ::testing::Test {
89139
builder_.GetSize());
90140
}
91141
flatbuffers::FlatBufferBuilder builder_;
92-
// const uint8_t* buffer_ = nullptr;
93142
const ::tflite::Model* input_model_ = nullptr;
94143
};
95144

@@ -106,7 +155,7 @@ TEST_F(ImportTest, LoadOperatorsTable) {
106155

107156
details::OperatorsTable operators;
108157
details::LoadOperatorsTable(*input_model_, &operators);
109-
EXPECT_THAT(operators, ElementsAre("custom_op_one", "CONV_2D"));
158+
EXPECT_THAT(operators, ElementsAre("MAX_POOL_2D", "CONV_2D"));
110159
}
111160

112161
TEST_F(ImportTest, Tensors) {
@@ -118,9 +167,9 @@ TEST_F(ImportTest, Tensors) {
118167
Array& a1 = model->GetArray("tensor_one");
119168
EXPECT_EQ(ArrayDataType::kFloat, a1.data_type);
120169
EXPECT_THAT(a1.GetBuffer<ArrayDataType::kFloat>().data,
121-
ElementsAre(1.0f, 2.0f));
170+
ElementsAre(1.0f, 2.0f, 3.0f, 4.0f));
122171
ASSERT_TRUE(a1.has_shape());
123-
EXPECT_THAT(a1.shape().dims(), ElementsAre(1, 2, 3, 4));
172+
EXPECT_THAT(a1.shape().dims(), ElementsAre(1, 2, 2));
124173

125174
const auto& mm = a1.minmax;
126175
ASSERT_TRUE(mm.get());
@@ -133,6 +182,80 @@ TEST_F(ImportTest, Tensors) {
133182
EXPECT_EQ(100, q->zero_point);
134183
}
135184

185+
TEST_F(ImportTest, NoBuffers) {
186+
auto buffers = 0;
187+
auto tensors = BuildTensors();
188+
auto opcodes = BuildOpCodes();
189+
auto operators = BuildOperators();
190+
auto subgraphs = BuildSubGraphs(tensors, operators);
191+
auto comment = builder_.CreateString("");
192+
::tflite::FinishModelBuffer(
193+
builder_, ::tflite::CreateModel(builder_, TFLITE_SCHEMA_VERSION, opcodes,
194+
subgraphs, comment, buffers));
195+
EXPECT_DEATH(Import(ModelFlags(), InputModelAsString()),
196+
"Missing 'buffers' section.");
197+
}
198+
199+
TEST_F(ImportTest, NoInputs) {
200+
auto buffers = BuildBuffers();
201+
auto tensors = BuildTensors();
202+
auto opcodes = BuildOpCodes();
203+
auto operators = BuildOperators({}, {1});
204+
auto subgraphs = BuildSubGraphs(tensors, operators);
205+
auto comment = builder_.CreateString("");
206+
::tflite::FinishModelBuffer(
207+
builder_, ::tflite::CreateModel(builder_, TFLITE_SCHEMA_VERSION, opcodes,
208+
subgraphs, comment, buffers));
209+
EXPECT_DEATH(Import(ModelFlags(), InputModelAsString()),
210+
"Missing 'inputs' for operator.");
211+
}
212+
213+
TEST_F(ImportTest, NoOutputs) {
214+
auto buffers = BuildBuffers();
215+
auto tensors = BuildTensors();
216+
auto opcodes = BuildOpCodes();
217+
auto operators = BuildOperators({0}, {});
218+
auto subgraphs = BuildSubGraphs(tensors, operators);
219+
auto comment = builder_.CreateString("");
220+
::tflite::FinishModelBuffer(
221+
builder_, ::tflite::CreateModel(builder_, TFLITE_SCHEMA_VERSION, opcodes,
222+
subgraphs, comment, buffers));
223+
EXPECT_DEATH(Import(ModelFlags(), InputModelAsString()),
224+
"Missing 'outputs' for operator.");
225+
}
226+
227+
TEST_F(ImportTest, InvalidOpCode) {
228+
auto buffers = BuildBuffers();
229+
auto tensors = BuildTensors();
230+
auto opcodes = BuildOpCodes({static_cast<::tflite::BuiltinOperator>(-1),
231+
::tflite::BuiltinOperator_CONV_2D});
232+
auto operators = BuildOperators();
233+
auto subgraphs = BuildSubGraphs(tensors, operators);
234+
auto comment = builder_.CreateString("");
235+
::tflite::FinishModelBuffer(
236+
builder_, ::tflite::CreateModel(builder_, TFLITE_SCHEMA_VERSION, opcodes,
237+
subgraphs, comment, buffers));
238+
EXPECT_DEATH(Import(ModelFlags(), InputModelAsString()),
239+
"Operator id '-1' is out of range.");
240+
}
241+
242+
TEST_F(ImportTest, MultipleSubGraphs) {
243+
auto buffers = BuildBuffers();
244+
auto tensors = BuildTensors();
245+
auto opcodes = BuildOpCodes();
246+
auto operators = BuildOperators();
247+
auto subgraphs = BuildSubGraphs(tensors, operators, 2);
248+
auto comment = builder_.CreateString("");
249+
::tflite::FinishModelBuffer(
250+
builder_, ::tflite::CreateModel(builder_, TFLITE_SCHEMA_VERSION, opcodes,
251+
subgraphs, comment, buffers));
252+
253+
input_model_ = ::tflite::GetModel(builder_.GetBufferPointer());
254+
255+
EXPECT_DEATH(Import(ModelFlags(), InputModelAsString()),
256+
"Number of subgraphs in tflite should be exactly 1.");
257+
}
258+
136259
// TODO(ahentz): still need tests for Operators and IOTensors.
137260

138261
} // namespace

0 commit comments

Comments
 (0)