Fix operand lookup in functions to check if local index out of range.

BUG= https://code.google.com/p/nativeclient/issues/detail?id=4302
R=stichnot@chromium.org

Review URL: https://codereview.chromium.org/1346723002 .
diff --git a/src/PNaClTranslator.cpp b/src/PNaClTranslator.cpp
index d8d1860..d3c71fd 100644
--- a/src/PNaClTranslator.cpp
+++ b/src/PNaClTranslator.cpp
@@ -1283,16 +1283,14 @@
     if (Index < CachedNumGlobalValueIDs) {
       return Context->getGlobalConstantByID(Index);
     }
+    if (isIRGenerationDisabled())
+      return nullptr;
     NaClBcIndexSize_t LocalIndex = Index - CachedNumGlobalValueIDs;
+    if (LocalIndex >= LocalOperands.size())
+      reportGetOperandUndefined(Index);
     Ice::Operand *Op = LocalOperands[LocalIndex];
-    if (Op == nullptr) {
-      if (isIRGenerationDisabled())
-        return nullptr;
-      std::string Buffer;
-      raw_string_ostream StrBuf(Buffer);
-      StrBuf << "Value index " << Index << " not defined!";
-      Fatal(StrBuf.str());
-    }
+    if (Op == nullptr)
+      reportGetOperandUndefined(Index);
     return Op;
   }
 
@@ -1981,6 +1979,13 @@
     Ice::Variable *Var = getNextInstVar(Ty);
     CurrentNode->appendInst(Ice::InstAssign::create(Func.get(), Var, Var));
   }
+
+  Ice::Operand *reportGetOperandUndefined(NaClBcIndexSize_t Index) {
+    std::string Buffer;
+    raw_string_ostream StrBuf(Buffer);
+    StrBuf << "Value index " << Index << " not defined!";
+    Fatal(StrBuf.str());
+  }
 };
 
 void FunctionParser::ExitBlock() {
diff --git a/tests_lit/parse_errs/Inputs/fcn-value-index-isnt-defined.tbc b/tests_lit/parse_errs/Inputs/fcn-value-index-isnt-defined.tbc
new file mode 100644
index 0000000..887341f
--- /dev/null
+++ b/tests_lit/parse_errs/Inputs/fcn-value-index-isnt-defined.tbc
@@ -0,0 +1,26 @@
+65535,8,2;
+1,1;
+65535,17,2;
+1,4;
+7,32;
+21,0,0;
+7,8;
+2;
+65534;
+8,1,0,0,0;
+65535,19,2;
+5,0;
+65534;
+65535,14,2;
+1,0,102;
+65534;
+65535,12,2;
+1,1;
+65535,11,2;
+1,0;
+4,2;
+65534;
+19,1,3;
+10,0;
+65534;
+65534;
diff --git a/tests_lit/parse_errs/fcn-value-index-isnt-defined.test b/tests_lit/parse_errs/fcn-value-index-isnt-defined.test
new file mode 100644
index 0000000..9359873
--- /dev/null
+++ b/tests_lit/parse_errs/fcn-value-index-isnt-defined.test
@@ -0,0 +1,44 @@
+; Test if we detect duplicate names in a symbol table.
+
+; REQUIRES: no_minimal_build
+
+; RUN: not %pnacl_sz -bitcode-as-text \
+; RUN:     %p/Inputs/fcn-value-index-isnt-defined.tbc \
+; RUN:     -bitcode-format=pnacl -notranslate -build-on-read 2>&1 \
+; RUN:   | FileCheck %s
+
+; CHECK: Value index {{.*}} not defined!
+
+; RUN: pnacl-bcfuzz -bitcode-as-text \
+; RUN:     %p/Inputs/fcn-value-index-isnt-defined.tbc -output - \
+; RUN:   | not pnacl-bcdis -no-records | FileCheck -check-prefix=ASM %s
+
+; ASM: module {  // BlockID = 8
+; ASM:   version 1;
+; ASM:   types {  // BlockID = 17
+; ASM:     count 4;
+; ASM:     @t0 = i32;
+; ASM:     @t1 = i32 ();
+; ASM:     @t2 = i8;
+; ASM:     @t3 = void;
+; ASM:   }
+; ASM:   define external i32 @f0();
+; ASM:   globals {  // BlockID = 19
+; ASM:     count 0;
+; ASM:   }
+; ASM:   valuesymtab {  // BlockID = 14
+; ASM:     @f0 : "f";
+; ASM:   }
+; ASM:   function i32 @f0() {  // BlockID = 12
+; ASM:     blocks 1;
+; ASM:     constants {  // BlockID = 11
+; ASM:       i32:
+; ASM:         %c0 = i32 1;
+; ASM:       }
+; ASM:   %b0:
+; ASM:     %v0 = alloca i8, i32 %c0, align 4;
+; ASM:     ret void %v1;
+; ASM: Error({{.*}}): Can't find type for %v1
+; ASM:   }
+; ASM: }
+