From 499f78265ef31af1020a89f7723e869e88821a4e Mon Sep 17 00:00:00 2001
From: Nguyen Anh Quynh <aquynh@gmail.com>
Date: Tue, 31 May 2016 00:43:35 +0800
Subject: [PATCH] handle error in peekTok(). this fixes
 c-crashes/crash-04-hexagon-readcount-not-equal-to-one.c

---
 bindings/go/keystone/keystone_const.go                   | 1 +
 bindings/nodejs/consts/keystone.js                       | 1 +
 bindings/python/keystone/keystone_const.py               | 1 +
 .../ruby/keystone_gem/lib/keystone/keystone_const.rb     | 1 +
 bindings/rust/src/keystone_const.rs                      | 1 +
 include/keystone/keystone.h                              | 1 +
 llvm/include/llvm/MC/MCParser/MCAsmLexer.h               | 6 ++----
 llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h        | 2 +-
 llvm/keystone/ks.cpp                                     | 2 ++
 llvm/lib/MC/MCParser/AsmParser.cpp                       | 7 ++++++-
 llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp   | 9 +++++++--
 11 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/bindings/go/keystone/keystone_const.go b/bindings/go/keystone/keystone_const.go
index 5a3f530..d3358fd 100644
--- a/bindings/go/keystone/keystone_const.go
+++ b/bindings/go/keystone/keystone_const.go
@@ -94,6 +94,7 @@ const (
 		ERR_ASM_TOKEN_INVALID Error = 157
 		ERR_ASM_INSN_UNSUPPORTED Error = 158
 		ERR_ASM_FIXUP_INVALID Error = 159
+		ERR_ASM_LABEL_INVALID Error = 160
 		ERR_ASM_INVALIDOPERAND Error = 512
 		ERR_ASM_MISSINGFEATURE Error = 513
 		ERR_ASM_MNEMONICFAIL Error = 514
diff --git a/bindings/nodejs/consts/keystone.js b/bindings/nodejs/consts/keystone.js
index ee0b530..5abaffc 100644
--- a/bindings/nodejs/consts/keystone.js
+++ b/bindings/nodejs/consts/keystone.js
@@ -70,6 +70,7 @@ module.exports.ERR_ASM_ESC_STR = 156
 module.exports.ERR_ASM_TOKEN_INVALID = 157
 module.exports.ERR_ASM_INSN_UNSUPPORTED = 158
 module.exports.ERR_ASM_FIXUP_INVALID = 159
+module.exports.ERR_ASM_LABEL_INVALID = 160
 module.exports.ERR_ASM_INVALIDOPERAND = 512
 module.exports.ERR_ASM_MISSINGFEATURE = 513
 module.exports.ERR_ASM_MNEMONICFAIL = 514
diff --git a/bindings/python/keystone/keystone_const.py b/bindings/python/keystone/keystone_const.py
index 17c7068..dfc3f34 100644
--- a/bindings/python/keystone/keystone_const.py
+++ b/bindings/python/keystone/keystone_const.py
@@ -70,6 +70,7 @@ KS_ERR_ASM_ESC_STR = 156
 KS_ERR_ASM_TOKEN_INVALID = 157
 KS_ERR_ASM_INSN_UNSUPPORTED = 158
 KS_ERR_ASM_FIXUP_INVALID = 159
+KS_ERR_ASM_LABEL_INVALID = 160
 KS_ERR_ASM_INVALIDOPERAND = 512
 KS_ERR_ASM_MISSINGFEATURE = 513
 KS_ERR_ASM_MNEMONICFAIL = 514
diff --git a/bindings/ruby/keystone_gem/lib/keystone/keystone_const.rb b/bindings/ruby/keystone_gem/lib/keystone/keystone_const.rb
index 4706645..93f2272 100644
--- a/bindings/ruby/keystone_gem/lib/keystone/keystone_const.rb
+++ b/bindings/ruby/keystone_gem/lib/keystone/keystone_const.rb
@@ -72,6 +72,7 @@ module Keystone
 	KS_ERR_ASM_TOKEN_INVALID = 157
 	KS_ERR_ASM_INSN_UNSUPPORTED = 158
 	KS_ERR_ASM_FIXUP_INVALID = 159
+	KS_ERR_ASM_LABEL_INVALID = 160
 	KS_ERR_ASM_INVALIDOPERAND = 512
 	KS_ERR_ASM_MISSINGFEATURE = 513
 	KS_ERR_ASM_MNEMONICFAIL = 514
diff --git a/bindings/rust/src/keystone_const.rs b/bindings/rust/src/keystone_const.rs
index 0d5c73e..8b34f93 100644
--- a/bindings/rust/src/keystone_const.rs
+++ b/bindings/rust/src/keystone_const.rs
@@ -139,6 +139,7 @@ bitflags! {
 		const ERR_ASM_TOKEN_INVALID = 157,
 		const ERR_ASM_INSN_UNSUPPORTED = 158,
 		const ERR_ASM_FIXUP_INVALID = 159,
+		const ERR_ASM_LABEL_INVALID = 160,
 		const ERR_ASM_INVALIDOPERAND = 512,
 		const ERR_ASM_MISSINGFEATURE = 513,
 		const ERR_ASM_MNEMONICFAIL = 514,
diff --git a/include/keystone/keystone.h b/include/keystone/keystone.h
index c4ba03f..a86311a 100644
--- a/include/keystone/keystone.h
+++ b/include/keystone/keystone.h
@@ -129,6 +129,7 @@ typedef enum ks_err {
     KS_ERR_ASM_TOKEN_INVALID,   // invalid token
     KS_ERR_ASM_INSN_UNSUPPORTED,   // this instruction is unsupported in this mode
     KS_ERR_ASM_FIXUP_INVALID,   // invalid fixup
+    KS_ERR_ASM_LABEL_INVALID,   // invalid label
 
     // generic input assembly errors - architecture specific
     KS_ERR_ASM_INVALIDOPERAND = KS_ERR_ASM_ARCH,
diff --git a/llvm/include/llvm/MC/MCParser/MCAsmLexer.h b/llvm/include/llvm/MC/MCParser/MCAsmLexer.h
index 96e2a53..09b2f8d 100644
--- a/llvm/include/llvm/MC/MCParser/MCAsmLexer.h
+++ b/llvm/include/llvm/MC/MCParser/MCAsmLexer.h
@@ -190,10 +190,8 @@ public:
     AsmToken Tok;
 
     MutableArrayRef<AsmToken> Buf(Tok);
-    size_t ReadCount = peekTokens(Buf, ShouldSkipSpace);
-
-    assert(ReadCount == 1);
-    (void)ReadCount;
+    if (peekTokens(Buf, ShouldSkipSpace) != 1)
+        return AsmToken(AsmToken::Error, nullptr);
 
     return Tok;
   }
diff --git a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
index 93fca92..d62bd4b 100644
--- a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
+++ b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
@@ -209,7 +209,7 @@ public:
   // Return whether this parser uses assignment statements with equals tokens
   virtual bool equalIsAsmAssignment() { return true; };
   // Return whether this start of statement identifier is a label
-  virtual bool isLabel(AsmToken &Token) { return true; };
+  virtual bool isLabel(AsmToken &Token, bool &valid) { valid = true; return true; };
 
   virtual const MCExpr *applyModifierToExpr(const MCExpr *E,
                                             MCSymbolRefExpr::VariantKind,
diff --git a/llvm/keystone/ks.cpp b/llvm/keystone/ks.cpp
index e38c58b..1602c79 100644
--- a/llvm/keystone/ks.cpp
+++ b/llvm/keystone/ks.cpp
@@ -132,6 +132,8 @@ const char *ks_strerror(ks_err code)
             return "Unknown directive (KS_ERR_ASM_DIRECTIVE_UNKNOWN)";
         case KS_ERR_ASM_FIXUP_INVALID:
             return "Invalid fixup (KS_ERR_ASM_FIXUP_INVALID)";
+        case KS_ERR_ASM_LABEL_INVALID:
+            return "Invalid label (KS_ERR_ASM_LABEL_INVALID)";
     }
 }
 
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index 265b24c..3c6141d 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -1563,8 +1563,13 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
   // See what kind of statement we have.
   switch (Lexer.getKind()) {
   case AsmToken::Colon: {
-    if (!getTargetParser().isLabel(ID))
+    bool valid;
+    if (!getTargetParser().isLabel(ID, valid))
       break;
+    if (!valid) {
+        Info.KsError = KS_ERR_ASM_LABEL_INVALID;
+        return true;
+    }
     checkForValidSection();
 
     // identifier ':'   -> Label.
diff --git a/llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp b/llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp
index fe0b26a..9f3a670 100644
--- a/llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp
+++ b/llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp
@@ -73,7 +73,7 @@ class HexagonAsmParser : public MCTargetAsmParser {
   MCAsmLexer &getLexer() const { return Parser.getLexer(); }
 
   bool equalIsAsmAssignment() override { return false; }
-  bool isLabel(AsmToken &Token) override;
+  bool isLabel(AsmToken &Token, bool &valid) override;
 
   void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
   bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
@@ -1195,10 +1195,15 @@ bool HexagonAsmParser::parseOperand(OperandVector &Operands) {
   return splitIdentifier(Operands);
 }
 
-bool HexagonAsmParser::isLabel(AsmToken &Token) {
+bool HexagonAsmParser::isLabel(AsmToken &Token, bool &valid) {
+  valid = true;
   MCAsmLexer &Lexer = getLexer();
   AsmToken const &Second = Lexer.getTok();
   AsmToken Third = Lexer.peekTok();  
+  if (Third.is(AsmToken::Error)) {
+      valid = false;
+      return true;
+  }
   StringRef String = Token.getString();
   if (Token.is(AsmToken::TokenKind::LCurly) ||
       Token.is(AsmToken::TokenKind::RCurly))
-- 
GitLab