.
diff --git a/src/binary-reader-ir.cc b/src/binary-reader-ir.cc
index ab8fe15..c325135 100644
--- a/src/binary-reader-ir.cc
+++ b/src/binary-reader-ir.cc
@@ -280,6 +280,7 @@
   void PushLabel(LabelType label_type,
                  ExprList* first,
                  Expr* context = nullptr);
+  Result BeginInitExpr(InitExpr* init_expr);
   Result EndInitExpr();
   Result PopLabel();
   Result GetLabelAt(LabelNode** label, Index depth);
@@ -367,13 +368,9 @@
 
 Result BinaryReaderIR::AppendExpr(std::unique_ptr<Expr> expr) {
   expr->loc = GetLocation();
-  if (current_init_expr_) {
-    current_init_expr_->exprs.push_back(std::move(expr));
-  } else {
-    LabelNode* label;
-    CHECK_RESULT(TopLabel(&label));
-    label->exprs->push_back(std::move(expr));
-  }
+  LabelNode* label;
+  CHECK_RESULT(TopLabel(&label));
+  label->exprs->push_back(std::move(expr));
   return Result::Ok;
 }
 
@@ -606,8 +603,7 @@
 Result BinaryReaderIR::BeginGlobalInitExpr(Index index) {
   assert(index == module_->globals.size() - 1);
   Global* global = module_->globals[index];
-  current_init_expr_ = &global->init_expr;
-  return Result::Ok;
+  return BeginInitExpr(&global->init_expr);
 }
 
 Result BinaryReaderIR::EndGlobalInitExpr(Index index) {
@@ -798,9 +794,6 @@
 }
 
 Result BinaryReaderIR::OnEndExpr() {
-  if (current_init_expr_) {
-    return Result::Ok;
-  }
   if (label_stack_.size() > 1) {
     LabelNode* label;
     Expr* expr;
@@ -821,8 +814,12 @@
       case LabelType::Try:
         cast<TryExpr>(expr)->block.end_loc = GetLocation();
         break;
-
+      case LabelType::InitExpr:
+        current_init_expr_->end_loc = GetLocation();
+        break;
       case LabelType::Func:
+        current_func_->end_loc = GetLocation();
+        break;
       case LabelType::Catch:
         break;
     }
@@ -1151,11 +1148,16 @@
   return Result::Ok;
 }
 
+Result BinaryReaderIR::BeginInitExpr(InitExpr* expr) {
+  current_init_expr_ = expr;
+  PushLabel(LabelType::InitExpr, &current_init_expr_->exprs);
+  return Result::Ok;
+}
+
 Result BinaryReaderIR::BeginElemSegmentInitExpr(Index index) {
   assert(index == module_->elem_segments.size() - 1);
   ElemSegment* segment = module_->elem_segments[index];
-  current_init_expr_ = &segment->offset;
-  return Result::Ok;
+  return BeginInitExpr(&segment->offset);
 }
 
 Result BinaryReaderIR::EndInitExpr() {
@@ -1230,8 +1232,7 @@
 Result BinaryReaderIR::BeginDataSegmentInitExpr(Index index) {
   assert(index == module_->data_segments.size() - 1);
   DataSegment* segment = module_->data_segments[index];
-  current_init_expr_ = &segment->offset;
-  return Result::Ok;
+  return BeginInitExpr(&segment->offset);
 }
 
 Result BinaryReaderIR::EndDataSegmentInitExpr(Index index) {
diff --git a/src/binary-reader.cc b/src/binary-reader.cc
index e077543..97f7a7a 100644
--- a/src/binary-reader.cc
+++ b/src/binary-reader.cc
@@ -131,9 +131,7 @@
   Result ReadFunctionBody(Offset end_offset) WABT_WARN_UNUSED;
   // ReadInstructions either until and END instruction, or until
   // the given end_offset.
-  Result ReadInstructions(bool stop_on_end,
-                          Offset end_offset,
-                          Opcode* final_opcode) WABT_WARN_UNUSED;
+  Result ReadInstructions(bool stop_on_end, Offset end_offset) WABT_WARN_UNUSED;
   Result ReadNameSection(Offset section_size) WABT_WARN_UNUSED;
   Result ReadRelocSection(Offset section_size) WABT_WARN_UNUSED;
   Result ReadDylinkSection(Offset section_size) WABT_WARN_UNUSED;
@@ -494,7 +492,7 @@
 
 Result BinaryReader::ReadInitExpr(Index index) {
   // Read instructions until END opcode is reached.
-  return ReadInstructions(/*stop_on_end=*/true, read_end_, NULL);
+  return ReadInstructions(/*stop_on_end=*/true, read_end_);
 }
 
 Result BinaryReader::ReadTable(Type* out_elem_type, Limits* out_elem_limits) {
@@ -597,25 +595,19 @@
 Result BinaryReader::ReadFunctionBody(Offset end_offset) {
   Opcode final_opcode(Opcode::Invalid);
   CHECK_RESULT(
-      ReadInstructions(/*stop_on_end=*/false, end_offset, &final_opcode));
+      ReadInstructions(/*stop_on_end=*/false, end_offset));
   ERROR_UNLESS(state_.offset == end_offset,
                "function body longer than given size");
-  ERROR_UNLESS(final_opcode == Opcode::End,
-               "function body must end with END opcode");
   return Result::Ok;
 }
 
 Result BinaryReader::ReadInstructions(bool stop_on_end,
-                                      Offset end_offset,
-                                      Opcode* final_opcode) {
+                                      Offset end_offset) {
   while (state_.offset < end_offset) {
     Opcode opcode;
     CHECK_RESULT(ReadOpcode(&opcode, "opcode"));
     CALLBACK(OnOpcode, opcode);
     ERROR_UNLESS_OPCODE_ENABLED(opcode);
-    if (final_opcode) {
-      *final_opcode = opcode;
-    }
 
     switch (opcode) {
       case Opcode::Unreachable:
diff --git a/src/common.h b/src/common.h
index 312726e..046cb55 100644
--- a/src/common.h
+++ b/src/common.h
@@ -224,6 +224,7 @@
 
 enum class LabelType {
   Func,
+  InitExpr,
   Block,
   Loop,
   If,
diff --git a/src/expr-visitor.h b/src/expr-visitor.h
index ab7dc9e..fdc2c4b 100644
--- a/src/expr-visitor.h
+++ b/src/expr-visitor.h
@@ -68,6 +68,8 @@
   virtual ~Delegate() {}
 
   virtual Result OnBinaryExpr(BinaryExpr*) = 0;
+  virtual Result BeginInitExpr(InitExpr*) = 0;
+  virtual Result EndInitExpr(InitExpr*) = 0;
   virtual Result BeginBlockExpr(BlockExpr*) = 0;
   virtual Result EndBlockExpr(BlockExpr*) = 0;
   virtual Result OnBrExpr(BrExpr*) = 0;
@@ -141,6 +143,8 @@
 class ExprVisitor::DelegateNop : public ExprVisitor::Delegate {
  public:
   Result OnBinaryExpr(BinaryExpr*) override { return Result::Ok; }
+  Result BeginInitExpr(InitExpr*) override { return Result::Ok; }
+  Result EndInitExpr(InitExpr*) override { return Result::Ok; }
   Result BeginBlockExpr(BlockExpr*) override { return Result::Ok; }
   Result EndBlockExpr(BlockExpr*) override { return Result::Ok; }
   Result OnBrExpr(BrExpr*) override { return Result::Ok; }
diff --git a/src/interp/binary-reader-interp.cc b/src/interp/binary-reader-interp.cc
index 17b3803..9e066c4 100644
--- a/src/interp/binary-reader-interp.cc
+++ b/src/interp/binary-reader-interp.cc
@@ -1096,6 +1096,7 @@
 
 Result BinaryReaderInterp::OnEndExpr() {
   if (reading_init_expr_) {
+    //CHECK_RESULT(validator_.OnEnd(loc));
     return Result::Ok;
   }
   if (label_stack_.size() == 1) {
diff --git a/src/ir.h b/src/ir.h
index 4c82faf..ceca4cb 100644
--- a/src/ir.h
+++ b/src/ir.h
@@ -377,6 +377,7 @@
   explicit InitExpr(ExprList exprs) : exprs(std::move(exprs)) {}
 
   ExprList exprs;
+  Location end_loc;
 };
 
 struct Catch {
@@ -833,6 +834,7 @@
   FuncDeclaration decl;
   LocalTypes local_types;
   BindingHash bindings;
+  Location end_loc;
   ExprList exprs;
 };
 
diff --git a/src/type-checker.cc b/src/type-checker.cc
index 1efc482..9be13bd 100644
--- a/src/type-checker.cc
+++ b/src/type-checker.cc
@@ -644,7 +644,7 @@
 Result TypeChecker::OnEnd() {
   Result result = Result::Ok;
   static const char* s_label_type_name[] = {
-      "function", "block", "loop", "if", "if false branch", "try", "try catch"};
+      "function", "init_expr", "block", "loop", "if", "if false branch", "try", "try catch"};
   WABT_STATIC_ASSERT(WABT_ARRAY_SIZE(s_label_type_name) == kLabelTypeCount);
   Label* label;
   CHECK_RESULT(TopLabel(&label));
diff --git a/src/validator.cc b/src/validator.cc
index f4351f6..1e23419 100644
--- a/src/validator.cc
+++ b/src/validator.cc
@@ -88,6 +88,8 @@
   Result OnBinaryExpr(BinaryExpr*) override;
   Result BeginBlockExpr(BlockExpr*) override;
   Result EndBlockExpr(BlockExpr*) override;
+  Result BeginInitExpr(InitExpr*) override;
+  Result EndInitExpr(InitExpr*) override;
   Result OnBrExpr(BrExpr*) override;
   Result OnBrIfExpr(BrIfExpr*) override;
   Result OnBrTableExpr(BrTableExpr*) override;
@@ -243,6 +245,20 @@
   return Result::Ok;
 }
 
+Result Validator::BeginInitExpr(InitExpr* expr) {
+  /*
+  const Expr& expr = f->global.init_expr.exprs.front();
+  result_ |=
+      validator_.OnBlock(expr->exprs.front()->loc, GetDeclarationType(expr->block.decl));
+      */
+  return Result::Ok;
+}
+
+Result Validator::EndInitExpr(InitExpr* expr) {
+  result_ |= validator_.OnEnd(expr->end_loc);
+  return Result::Ok;
+}
+
 Result Validator::OnBrExpr(BrExpr* expr) {
   result_ |= validator_.OnBr(expr->loc, expr->var);
   return Result::Ok;
diff --git a/src/wat-writer.cc b/src/wat-writer.cc
index 1e8d502..11d54b3 100644
--- a/src/wat-writer.cc
+++ b/src/wat-writer.cc
@@ -552,6 +552,8 @@
   Result OnBinaryExpr(BinaryExpr*) override;
   Result BeginBlockExpr(BlockExpr*) override;
   Result EndBlockExpr(BlockExpr*) override;
+  Result BeginInitExpr(InitExpr*) override;
+  Result EndInitExpr(InitExpr*) override;
   Result OnBrExpr(BrExpr*) override;
   Result OnBrIfExpr(BrIfExpr*) override;
   Result OnBrTableExpr(BrTableExpr*) override;
@@ -639,6 +641,14 @@
   return Result::Ok;
 }
 
+Result WatWriter::ExprVisitorDelegate::BeginInitExpr(InitExpr* expr) {
+  return Result::Ok;
+}
+
+Result WatWriter::ExprVisitorDelegate::EndInitExpr(InitExpr* expr) {
+  return Result::Ok;
+}
+
 Result WatWriter::ExprVisitorDelegate::OnBrExpr(BrExpr* expr) {
   writer_->WritePutsSpace(Opcode::Br_Opcode.GetName());
   writer_->WriteBrVar(expr->var, NextChar::Newline);
diff --git a/test/binary/bad-function-missing-end.txt b/test/binary/bad-function-missing-end.txt
new file mode 100644
index 0000000..d2a7b48
--- /dev/null
+++ b/test/binary/bad-function-missing-end.txt
@@ -0,0 +1,17 @@
+;;; TOOL: run-gen-wasm-interp
+;;; ERROR: 1
+magic
+version
+section(TYPE) { count[1] function params[0] results[0] }
+section(FUNCTION) { count[1] sig[0] }
+section(CODE) {
+  count[1]
+  size[4]
+  locals[0]
+  i32.const
+  leb_i32(42)
+  drop
+}
+(;; STDERR ;;;
+0000019: error: function body longer than given size
+;;; STDERR ;;)