From 71c85c554a49ed3a17167e436630ddaff2b9fcb1 Mon Sep 17 00:00:00 2001
From: Olivier Goffart <ogoffart@woboq.com>
Date: Fri, 29 May 2015 12:39:24 +0200
Subject: [PATCH] moc: Fix crash parsing invalid macro invocation

When invoking a macro with less argument than it expect, we would
crash trying to access the vector of arguments from the invocation
as we are trying to substitute an argument.

(Note that we do not show an error in case of argument mismatch
because ithat might happen parsing valid code as moc's c++ parser
is not 100% accurate (that was QTBUG-29331))

Task-number: QTBUG-46210
Change-Id: I3f08d7f5049e593a5bdc02a594ea63cadf66e7a4
Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@theqtcompany.com>
---
 src/tools/moc/preprocessor.cpp   | 8 +++++---
 tests/auto/tools/moc/tst_moc.cpp | 7 +++++++
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/src/tools/moc/preprocessor.cpp b/src/tools/moc/preprocessor.cpp
index 51873033c72..f253c49995c 100644
--- a/src/tools/moc/preprocessor.cpp
+++ b/src/tools/moc/preprocessor.cpp
@@ -661,8 +661,10 @@ Symbols Preprocessor::macroExpandIdentifier(Preprocessor *that, SymbolStack &sym
                     expansion += s;
                 }
             } else if (mode == Hash) {
-                if (index < 0)
+                if (index < 0 || index >= arguments.size()) {
                     that->error("'#' is not followed by a macro parameter");
+                    continue;
+                }
 
                 const Symbols &arg = arguments.at(index);
                 QByteArray stringified;
@@ -681,7 +683,7 @@ Symbols Preprocessor::macroExpandIdentifier(Preprocessor *that, SymbolStack &sym
                     expansion.pop_back();
 
                 Symbol next = s;
-                if (index >= 0) {
+                if (index >= 0 && index < arguments.size()) {
                     const Symbols &arg = arguments.at(index);
                     if (arg.size() == 0) {
                         mode = Normal;
@@ -703,7 +705,7 @@ Symbols Preprocessor::macroExpandIdentifier(Preprocessor *that, SymbolStack &sym
                     expansion += next;
                 }
 
-                if (index >= 0) {
+                if (index >= 0 && index < arguments.size()) {
                     const Symbols &arg = arguments.at(index);
                     for (int i = 1; i < arg.size(); ++i)
                         expansion += arg.at(i);
diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp
index 8bef678af9a..350c6142d20 100644
--- a/tests/auto/tools/moc/tst_moc.cpp
+++ b/tests/auto/tools/moc/tst_moc.cpp
@@ -1882,6 +1882,13 @@ void tst_Moc::warnings_data()
         << 1
         << QString()
         << QString("standard input:5: Error: Class declaration lacks Q_OBJECT macro.");
+
+    QTest::newRow("QTBUG-46210: crash on invalid macro")
+        << QByteArray("#define Foo(a, b, c) a b c #a #b #c a##b##c #d\n Foo(45);")
+        << QStringList()
+        << 1
+        << QString("IGNORE_ALL_STDOUT")
+        << QString(":2: Error: '#' is not followed by a macro parameter");
 }
 
 void tst_Moc::warnings()
-- 
GitLab