[v2,4/5] kconfig: qconf: make debug links work again
diff mbox series

Message ID b10b8bf2c21f4288ecb6081a967c302000346ff1.1593423060.git.mchehab+huawei@kernel.org
State New
Headers show
Series
  • Fix split view search and debug info navigation
Related show

Commit Message

Mauro Carvalho Chehab June 29, 2020, 9:35 a.m. UTC
The Qt5 conversion broke support for debug info links.

Restore the behaviour added by changeset
ab45d190fd4a ("kconfig: create links in info window").

The original approach were to pass a pointer for a data struct
via an <a href>. That doesn't sound a good idea, as, if something
gets wrong, the app could crash. So, instead, pass the name of
the symbol, and validate such symbol at the hyperlink handling
logic.

Link: https://lore.kernel.org/lkml/20200628125421.12458086@coco.lan/
Reported-by: Maxim Levitsky <mlevitsk@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
 scripts/kconfig/qconf.cc | 75 +++++++++++++++++++++++++++++++++++++---
 scripts/kconfig/qconf.h  |  1 +
 2 files changed, 71 insertions(+), 5 deletions(-)

Comments

Masahiro Yamada June 30, 2020, 3:48 a.m. UTC | #1
On Mon, Jun 29, 2020 at 6:35 PM Mauro Carvalho Chehab
<mchehab+huawei@kernel.org> wrote:
>
> The Qt5 conversion broke support for debug info links.
>
> Restore the behaviour added by changeset
> ab45d190fd4a ("kconfig: create links in info window").
>
> The original approach were to pass a pointer for a data struct

"were" -> "was" ?


> via an <a href>. That doesn't sound a good idea, as, if something
> gets wrong, the app could crash. So, instead, pass the name of
> the symbol, and validate such symbol at the hyperlink handling
> logic.
>
> Link: https://lore.kernel.org/lkml/20200628125421.12458086@coco.lan/
> Reported-by: Maxim Levitsky <mlevitsk@redhat.com>
> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>



This patch does not cause segmentation fault any more.
Thanks.


> ---
>  scripts/kconfig/qconf.cc | 75 +++++++++++++++++++++++++++++++++++++---
>  scripts/kconfig/qconf.h  |  1 +
>  2 files changed, 71 insertions(+), 5 deletions(-)
>
> diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc
> index 85782da3e464..49f0688fceb8 100644
> --- a/scripts/kconfig/qconf.cc
> +++ b/scripts/kconfig/qconf.cc
> @@ -7,6 +7,7 @@
>  #include <QAction>
>  #include <QApplication>
>  #include <QCloseEvent>
> +#include <QDebug>
>  #include <QDesktopWidget>
>  #include <QFileDialog>
>  #include <QLabel>
> @@ -1012,7 +1013,7 @@ ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)
>         : Parent(parent), sym(0), _menu(0)
>  {
>         setObjectName(name);
> -
> +       setOpenLinks(false);
>
>         if (!objectName().isEmpty()) {
>                 configSettings->beginGroup(objectName());
> @@ -1085,7 +1086,7 @@ void ConfigInfoView::menuInfo(void)
>                         if (sym->name) {
>                                 head += " (";
>                                 if (showDebug())
> -                                       head += QString().sprintf("<a href=\"s%p\">", sym);
> +                                       head += QString().sprintf("<a href=\"s%s\">", sym->name);
>                                 head += print_filter(sym->name);
>                                 if (showDebug())
>                                         head += "</a>";
> @@ -1094,7 +1095,7 @@ void ConfigInfoView::menuInfo(void)
>                 } else if (sym->name) {
>                         head += "<big><b>";
>                         if (showDebug())
> -                               head += QString().sprintf("<a href=\"s%p\">", sym);
> +                               head += QString().sprintf("<a href=\"s%s\">", sym->name);
>                         head += print_filter(sym->name);
>                         if (showDebug())
>                                 head += "</a>";
> @@ -1145,7 +1146,7 @@ QString ConfigInfoView::debug_info(struct symbol *sym)
>                 switch (prop->type) {
>                 case P_PROMPT:
>                 case P_MENU:
> -                       debug += QString().sprintf("prompt: <a href=\"m%p\">", prop->menu);
> +                       debug += QString().sprintf("prompt: <a href=\"m%s\">", sym->name);
>                         debug += print_filter(prop->text);
>                         debug += "</a><br>";
>                         break;
> @@ -1217,13 +1218,74 @@ void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char
>         QString str2 = print_filter(str);
>
>         if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) {
> -               *text += QString().sprintf("<a href=\"s%p\">", sym);
> +               *text += QString().sprintf("<a href=\"s%s\">", sym->name);
>                 *text += str2;
>                 *text += "</a>";
>         } else
>                 *text += str2;
>  }
>
> +void ConfigInfoView::clicked(const QUrl &url)
> +{
> +       QByteArray str = url.toEncoded();
> +       const std::size_t count = str.size();
> +       char *data = new char[count + 1];
> +       struct symbol **result;
> +       struct menu *m = NULL;
> +       char type;
> +
> +       if (count < 1) {
> +               qInfo() << "Clicked link is empty";
> +               delete data;
> +               return;
> +       }
> +
> +       memcpy(data, str.constData(), count);
> +       data[count] = '\0';
> +       type = data[0];
> +
> +       /* Seek for exact match */
> +       data[0] = '^';
> +       strcat(data, "$");
> +       result = sym_re_search(data);
> +       if (!result) {
> +               qInfo() << "Clicked symbol is invalid:" << data;
> +               delete data;
> +               return;
> +       }
> +
> +       sym = *result;
> +       if (type == 's') {
> +               symbolInfo();
> +               emit showDebugChanged(true);
> +               free(result);
> +               delete data;
> +               return;
> +       }
> +
> +       /* URL is a menu */
> +       for (struct property *prop = sym->prop; prop; prop = prop->next) {
> +                   if (prop->type != P_PROMPT && prop->type != P_MENU)
> +                           continue;
> +                   m = prop->menu;
> +                   break;
> +       }
> +
> +       if (!m) {
> +               qInfo() << "Clicked menu is invalid:" << data;
> +               free(result);
> +               delete data;
> +               return;
> +       }
> +
> +       _menu = m;
> +       menuInfo();
> +
> +       emit showDebugChanged(true);
> +       free(result);
> +       delete data;
> +}
> +
>  QMenu* ConfigInfoView::createStandardContextMenu(const QPoint & pos)
>  {
>         QMenu* popup = Parent::createStandardContextMenu(pos);
> @@ -1497,6 +1559,9 @@ ConfigMainWindow::ConfigMainWindow(void)
>         helpMenu->addAction(showIntroAction);
>         helpMenu->addAction(showAboutAction);
>
> +       connect (helpText, SIGNAL (anchorClicked (const QUrl &)),
> +                helpText, SLOT (clicked (const QUrl &)) );
> +
>         connect(configList, SIGNAL(menuChanged(struct menu *)),
>                 helpText, SLOT(setInfo(struct menu *)));
>         connect(configList, SIGNAL(menuSelected(struct menu *)),
> diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h
> index d913a02967ae..a193137f2314 100644
> --- a/scripts/kconfig/qconf.h
> +++ b/scripts/kconfig/qconf.h
> @@ -250,6 +250,7 @@ public slots:
>         void setInfo(struct menu *menu);
>         void saveSettings(void);
>         void setShowDebug(bool);
> +       void clicked (const QUrl &url);
>
>  signals:
>         void showDebugChanged(bool);
> --
> 2.26.2
>

Patch
diff mbox series

diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc
index 85782da3e464..49f0688fceb8 100644
--- a/scripts/kconfig/qconf.cc
+++ b/scripts/kconfig/qconf.cc
@@ -7,6 +7,7 @@ 
 #include <QAction>
 #include <QApplication>
 #include <QCloseEvent>
+#include <QDebug>
 #include <QDesktopWidget>
 #include <QFileDialog>
 #include <QLabel>
@@ -1012,7 +1013,7 @@  ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)
 	: Parent(parent), sym(0), _menu(0)
 {
 	setObjectName(name);
-
+	setOpenLinks(false);
 
 	if (!objectName().isEmpty()) {
 		configSettings->beginGroup(objectName());
@@ -1085,7 +1086,7 @@  void ConfigInfoView::menuInfo(void)
 			if (sym->name) {
 				head += " (";
 				if (showDebug())
-					head += QString().sprintf("<a href=\"s%p\">", sym);
+					head += QString().sprintf("<a href=\"s%s\">", sym->name);
 				head += print_filter(sym->name);
 				if (showDebug())
 					head += "</a>";
@@ -1094,7 +1095,7 @@  void ConfigInfoView::menuInfo(void)
 		} else if (sym->name) {
 			head += "<big><b>";
 			if (showDebug())
-				head += QString().sprintf("<a href=\"s%p\">", sym);
+				head += QString().sprintf("<a href=\"s%s\">", sym->name);
 			head += print_filter(sym->name);
 			if (showDebug())
 				head += "</a>";
@@ -1145,7 +1146,7 @@  QString ConfigInfoView::debug_info(struct symbol *sym)
 		switch (prop->type) {
 		case P_PROMPT:
 		case P_MENU:
-			debug += QString().sprintf("prompt: <a href=\"m%p\">", prop->menu);
+			debug += QString().sprintf("prompt: <a href=\"m%s\">", sym->name);
 			debug += print_filter(prop->text);
 			debug += "</a><br>";
 			break;
@@ -1217,13 +1218,74 @@  void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char
 	QString str2 = print_filter(str);
 
 	if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) {
-		*text += QString().sprintf("<a href=\"s%p\">", sym);
+		*text += QString().sprintf("<a href=\"s%s\">", sym->name);
 		*text += str2;
 		*text += "</a>";
 	} else
 		*text += str2;
 }
 
+void ConfigInfoView::clicked(const QUrl &url)
+{
+	QByteArray str = url.toEncoded();
+	const std::size_t count = str.size();
+	char *data = new char[count + 1];
+	struct symbol **result;
+	struct menu *m = NULL;
+	char type;
+
+	if (count < 1) {
+		qInfo() << "Clicked link is empty";
+		delete data;
+		return;
+	}
+
+	memcpy(data, str.constData(), count);
+	data[count] = '\0';
+	type = data[0];
+
+	/* Seek for exact match */
+	data[0] = '^';
+	strcat(data, "$");
+	result = sym_re_search(data);
+	if (!result) {
+		qInfo() << "Clicked symbol is invalid:" << data;
+		delete data;
+		return;
+	}
+
+	sym = *result;
+	if (type == 's') {
+		symbolInfo();
+		emit showDebugChanged(true);
+		free(result);
+		delete data;
+		return;
+	}
+
+	/* URL is a menu */
+	for (struct property *prop = sym->prop; prop; prop = prop->next) {
+		    if (prop->type != P_PROMPT && prop->type != P_MENU)
+			    continue;
+		    m = prop->menu;
+		    break;
+	}
+
+	if (!m) {
+		qInfo() << "Clicked menu is invalid:" << data;
+		free(result);
+		delete data;
+		return;
+	}
+
+	_menu = m;
+	menuInfo();
+
+	emit showDebugChanged(true);
+	free(result);
+	delete data;
+}
+
 QMenu* ConfigInfoView::createStandardContextMenu(const QPoint & pos)
 {
 	QMenu* popup = Parent::createStandardContextMenu(pos);
@@ -1497,6 +1559,9 @@  ConfigMainWindow::ConfigMainWindow(void)
 	helpMenu->addAction(showIntroAction);
 	helpMenu->addAction(showAboutAction);
 
+	connect (helpText, SIGNAL (anchorClicked (const QUrl &)),
+		 helpText, SLOT (clicked (const QUrl &)) );
+
 	connect(configList, SIGNAL(menuChanged(struct menu *)),
 		helpText, SLOT(setInfo(struct menu *)));
 	connect(configList, SIGNAL(menuSelected(struct menu *)),
diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h
index d913a02967ae..a193137f2314 100644
--- a/scripts/kconfig/qconf.h
+++ b/scripts/kconfig/qconf.h
@@ -250,6 +250,7 @@  public slots:
 	void setInfo(struct menu *menu);
 	void saveSettings(void);
 	void setShowDebug(bool);
+	void clicked (const QUrl &url);
 
 signals:
 	void showDebugChanged(bool);