From 440ffe5943780574bfe1232e8fbe2693f4256eac Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Tue, 14 Apr 2020 11:22:17 -0400 Subject: [PATCH] Fix: sink.text.pretty: check that port is connected before creating message iterator sink.text.pretty does not check if its input port is connected before trying to create a message iterator on it. This can lead to a precondition assertion failure. It can be reproduced with this Python snippet. import bt2 g = bt2.Graph() g.add_component(bt2.find_plugin('text').sink_component_classes['pretty'], 'snk') g.run() The assertion failure we get is: 04-14 11:35:27.339 1231815 1231815 F LIB/MSG-ITER create_self_component_input_port_message_iterator@iterator.c:295 Babeltrace 2 library precondition not satisfied; error is: 04-14 11:35:27.339 1231815 1231815 F LIB/MSG-ITER create_self_component_input_port_message_iterator@iterator.c:295 Input port is not connected: port-addr=0x607000001d70, port-type=INPUT, port-name="in" 04-14 11:35:27.339 1231815 1231815 F LIB/MSG-ITER create_self_component_input_port_message_iterator@iterator.c:295 Aborting... ./tests/utils/../utils/utils.sh: line 283: 1231815 Aborted (core dumped) env "${env_args[@]}" "$@" Add a check and return an error if that happens instead. A corresponding test is also added. Change-Id: Ibeed94cd6ece543817fe8a765a69cb52bbaaba76 Signed-off-by: Simon Marchi Reviewed-on: https://review.lttng.org/c/babeltrace/+/3403 Reviewed-by: Philippe Proulx Tested-by: jenkins --- src/plugins/text/pretty/pretty.c | 24 ++++++++++++++---- tests/Makefile.am | 3 +++ tests/plugins/sink.text.pretty/test_pretty | 17 +++++++++++++ tests/plugins/sink.text.pretty/test_pretty.py | 25 +++++++++++++++++++ 4 files changed, 64 insertions(+), 5 deletions(-) create mode 100755 tests/plugins/sink.text.pretty/test_pretty create mode 100644 tests/plugins/sink.text.pretty/test_pretty.py diff --git a/src/plugins/text/pretty/pretty.c b/src/plugins/text/pretty/pretty.c index f177ad23..1a5a759d 100644 --- a/src/plugins/text/pretty/pretty.c +++ b/src/plugins/text/pretty/pretty.c @@ -121,20 +121,34 @@ bt_message_iterator_class_next_method_status handle_message( BT_HIDDEN bt_component_class_sink_graph_is_configured_method_status -pretty_graph_is_configured(bt_self_component_sink *comp) +pretty_graph_is_configured(bt_self_component_sink *self_comp_sink) { bt_component_class_sink_graph_is_configured_method_status status; bt_message_iterator_create_from_sink_component_status msg_iter_status; struct pretty_component *pretty; + bt_self_component *self_comp = + bt_self_component_sink_as_self_component(self_comp_sink); + const bt_component *comp = bt_self_component_as_component(self_comp); + bt_self_component_port_input *in_port; + bt_logging_level log_level = bt_component_get_logging_level(comp); - pretty = bt_self_component_get_data( - bt_self_component_sink_as_self_component(comp)); + pretty = bt_self_component_get_data(self_comp); BT_ASSERT(pretty); BT_ASSERT(!pretty->iterator); + + in_port = bt_self_component_sink_borrow_input_port_by_name(self_comp_sink, + in_port_name); + if (!bt_port_is_connected(bt_port_input_as_port_const( + bt_self_component_port_input_as_port_input(in_port)))) { + BT_COMP_LOGE_APPEND_CAUSE(self_comp, "Single input port is not connected: " + "port-name=\"%s\"", in_port_name); + status = BT_COMPONENT_CLASS_SINK_GRAPH_IS_CONFIGURED_METHOD_STATUS_ERROR; + goto end; + } + msg_iter_status = bt_message_iterator_create_from_sink_component( - comp, bt_self_component_sink_borrow_input_port_by_name(comp, - in_port_name), &pretty->iterator); + self_comp_sink, in_port, &pretty->iterator); if (msg_iter_status != BT_MESSAGE_ITERATOR_CREATE_FROM_SINK_COMPONENT_STATUS_OK) { status = (int) msg_iter_status; goto end; diff --git a/tests/Makefile.am b/tests/Makefile.am index 7f3bc8ea..c545f9a7 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -55,6 +55,8 @@ dist_check_SCRIPTS = \ cli/test_trace_read \ cli/test_trimmer \ plugins/sink.text.details/succeed/test_succeed \ + plugins/sink.text.pretty/test_pretty \ + plugins/sink.text.pretty/test_pretty.py \ plugins/src.ctf.lttng-live/test_live \ python-plugin-provider/bt_plugin_test_python_plugin_provider.py \ python-plugin-provider/test_python_plugin_provider \ @@ -145,6 +147,7 @@ TESTS_PYTHON_PLUGIN_PROVIDER = if ENABLE_PYTHON_PLUGINS TESTS_PYTHON_PLUGIN_PROVIDER += python-plugin-provider/test_python_plugin_provider +TESTS_PLUGINS += plugins/sink.text.pretty/test_pretty if ENABLE_DEBUG_INFO TESTS_PLUGINS += \ plugins/flt.lttng-utils.debug-info/test_succeed diff --git a/tests/plugins/sink.text.pretty/test_pretty b/tests/plugins/sink.text.pretty/test_pretty new file mode 100755 index 00000000..3fdac62c --- /dev/null +++ b/tests/plugins/sink.text.pretty/test_pretty @@ -0,0 +1,17 @@ +#!/bin/bash +# +# SPDX-License-Identifier: GPL-2.0-only +# +# Copyright (C) 2017 Philippe Proulx +# + +if [ "x${BT_TESTS_SRCDIR:-}" != "x" ]; then + UTILSSH="$BT_TESTS_SRCDIR/utils/utils.sh" +else + UTILSSH="$(dirname "$0")/../../utils/utils.sh" +fi + +# shellcheck source=../../utils/utils.sh +source "$UTILSSH" + +run_python_bt2_test "${BT_TESTS_SRCDIR}/plugins/sink.text.pretty" "test_*" diff --git a/tests/plugins/sink.text.pretty/test_pretty.py b/tests/plugins/sink.text.pretty/test_pretty.py new file mode 100644 index 00000000..368afb6c --- /dev/null +++ b/tests/plugins/sink.text.pretty/test_pretty.py @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Copyright (C) 2020 EfficiOS, Inc. + +import unittest +import bt2 + + +class Test(unittest.TestCase): + # Test that the component returns an error if the graph is configured while + # the component's input port is left disconnected. + def test_unconnected_port_raises(self): + graph = bt2.Graph() + graph.add_component( + bt2.find_plugin('text').sink_component_classes['pretty'], 'snk' + ) + + with self.assertRaisesRegex( + bt2._Error, 'Single input port is not connected: port-name="in"' + ): + graph.run() + + +if __name__ == '__main__': + unittest.main() -- 2.34.1