From 6e536aba7313590bdaa3c3676e7802703f9292d4 Mon Sep 17 00:00:00 2001 From: Alexey Edelev Date: Wed, 16 Apr 2025 11:12:36 +0200 Subject: [PATCH] Ensure that plugin class name is a valid C indentifier We should prevent using the invalid plugin class names at CMake configure stage already, so users receive the early error. Fixes: QTBUG-135860 Change-Id: I259539f6cce70a035ccf458a62d9e5a02f238ef8 Reviewed-by: Alexandru Croitor --- cmake/QtPublicCMakeHelpers.cmake | 23 ++++++++++++++ src/corelib/Qt6CoreMacros.cmake | 8 +++++ tests/auto/cmake/CMakeLists.txt | 30 +++++++++++++++++++ .../test_plugin_class_name/CMakeLists.txt | 13 ++++++++ .../test_plugin_class_name/plugin.cpp.in | 6 ++++ 5 files changed, 80 insertions(+) create mode 100644 tests/auto/cmake/test_plugin_class_name/CMakeLists.txt create mode 100644 tests/auto/cmake/test_plugin_class_name/plugin.cpp.in diff --git a/cmake/QtPublicCMakeHelpers.cmake b/cmake/QtPublicCMakeHelpers.cmake index 959872c3b64..0888b2a8d49 100644 --- a/cmake/QtPublicCMakeHelpers.cmake +++ b/cmake/QtPublicCMakeHelpers.cmake @@ -918,3 +918,26 @@ function(_qt_internal_configure_file mode) configure_file("${input_file}" "${arg_OUTPUT}" @ONLY) endfunction() + +# The function checks if `value` is a valid C indentifier. +# +# Synopsis +# +# _qt_internal_is_c_identifier( ) +# +# Arguments +# +# `out_var` +# Variable name for the evaluation result. +# +# `value` +# The string for the evaluation. +function(_qt_internal_is_c_identifier out_var value) + string(MAKE_C_IDENTIFIER "${value}" value_valid) + + if(value AND "${value}" STREQUAL "${value_valid}") + set(${out_var} "TRUE" PARENT_SCOPE) + else() + set(${out_var} "FALSE" PARENT_SCOPE) + endif() +endfunction() diff --git a/src/corelib/Qt6CoreMacros.cmake b/src/corelib/Qt6CoreMacros.cmake index e63c8295085..f2e9824cf9f 100644 --- a/src/corelib/Qt6CoreMacros.cmake +++ b/src/corelib/Qt6CoreMacros.cmake @@ -2626,6 +2626,14 @@ function(qt6_add_plugin target) endif() endif() + _qt_internal_is_c_identifier(is_c_indentifier "${plugin_class_name}") + if(NOT is_c_indentifier) + message(FATAL_ERROR "The provided or calculated plugin CLASS_NAME '${plugin_class_name}' of" + " the '${target}' target is not a valid C++ class name. Please use only valid C++" + " identifiers." + ) + endif() + set_target_properties(${target} PROPERTIES QT_PLUGIN_CLASS_NAME "${plugin_class_name}") # Create a plugin initializer object library for static plugins. diff --git a/tests/auto/cmake/CMakeLists.txt b/tests/auto/cmake/CMakeLists.txt index 7973d812e3f..4028fc2c1bb 100644 --- a/tests/auto/cmake/CMakeLists.txt +++ b/tests/auto/cmake/CMakeLists.txt @@ -482,5 +482,35 @@ if(NOT QNX AND NOT WASM AND NOT (WIN32 AND QT_BUILD_MINIMAL_STATIC_TESTS) _qt_internal_test_expect_pass(test_qt_add_ui_11) endif() +# Valid plugin names +set(valid_plugin_class_names + TestPluginNameUpper + Test_Plugin_Name + _Test_plugin_name + testpluginnamelower + Test0PluginName +) +foreach(plugin_class_name IN LISTS valid_plugin_class_names) + _qt_internal_test_expect_pass(test_plugin_class_name + TESTNAME test_plugin_class_name_${plugin_class_name} + BUILD_OPTIONS + -DPLUGIN_CLASS_NAME=${plugin_class_name} + ) +endforeach() + +# Invalid plugin names +set(invalid_plugin_class_names + 0TestPluginName + Test-Plugin-Name + Test.plugin.name +) +foreach(plugin_class_name IN LISTS invalid_plugin_class_names) + _qt_internal_test_expect_fail(test_plugin_class_name + TESTNAME test_plugin_class_name_${plugin_class_name} + BUILD_OPTIONS + -DPLUGIN_CLASS_NAME=${plugin_class_name} + ) +endforeach() + # Add all tests using CMake's RunCMake test module add_subdirectory(RunCMake) diff --git a/tests/auto/cmake/test_plugin_class_name/CMakeLists.txt b/tests/auto/cmake/test_plugin_class_name/CMakeLists.txt new file mode 100644 index 00000000000..e1e40766593 --- /dev/null +++ b/tests/auto/cmake/test_plugin_class_name/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (C) 2025 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.20) + +project(test_plugin_class_name_${PLUGIN_CLASS_NAME} LANGUAGES CXX) + +find_package(Qt6Core REQUIRED) + +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/plugin.cpp.in" + "${CMAKE_CURRENT_BINARY_DIR}/plugin.cpp" @ONLY) + +qt_add_plugin(test_plugin CLASS_NAME ${PLUGIN_CLASS_NAME} "${CMAKE_CURRENT_BINARY_DIR}/plugin.cpp") diff --git a/tests/auto/cmake/test_plugin_class_name/plugin.cpp.in b/tests/auto/cmake/test_plugin_class_name/plugin.cpp.in new file mode 100644 index 00000000000..513c79ca83a --- /dev/null +++ b/tests/auto/cmake/test_plugin_class_name/plugin.cpp.in @@ -0,0 +1,6 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +class @PLUGIN_CLASS_NAME@ { + // noop +};