From 5a0679b86241993fe16eca60539ef855fa4b0afe Mon Sep 17 00:00:00 2001 From: Ghazi-raad Date: Sat, 6 Dec 2025 12:45:48 +0000 Subject: [PATCH] Fix null pointer dereference in G-API stateful kernels Fixes #28095 Problem: - Stateful kernels dereference null state pointer on line 446 in gcpukernel.hpp - jinboson confirmed state_ptr is null on x86 Ubuntu (7 hours ago) - Causes crash with std::shared_ptr assertion on LoongArch64 and strict platforms Solution (addressing Copilot review feedback from PR #28096): 1. Added null pointer check using CV_Error instead of CV_Assert: - CV_Assert with && 'message' doesn't display the message correctly - CV_Error properly reports cv::Error::StsNullPtr with clear message 2. Fixed test kernels to properly initialize state using std::make_shared: - GOCVStInvalidResize: Initialize state in setup() - GOCVCountStateSetups: Initialize state before incrementing counter - Used std::make_shared() for modern C++ best practice Impact: - Prevents crashes on platforms with strict null pointer checking - Provides actionable error message for developers - Fixes StatefulKernel.StateInitOnceInRegularMode and InvalidReallocatingKernel tests --- modules/gapi/include/opencv2/gapi/cpu/gcpukernel.hpp | 7 ++++++- modules/gapi/test/cpu/gapi_ocv_stateful_kernel_tests.cpp | 9 ++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/modules/gapi/include/opencv2/gapi/cpu/gcpukernel.hpp b/modules/gapi/include/opencv2/gapi/cpu/gcpukernel.hpp index eb5f784747..2763d17eaf 100644 --- a/modules/gapi/include/opencv2/gapi/cpu/gcpukernel.hpp +++ b/modules/gapi/include/opencv2/gapi/cpu/gcpukernel.hpp @@ -443,7 +443,12 @@ struct OCVStCallHelper, std::tuple> : template static void call_impl(GCPUContext &ctx, detail::Seq, detail::Seq) { - auto& st = *ctx.state().get>(); + auto state_ptr = ctx.state().get>(); + if (state_ptr == nullptr) { + CV_Error(cv::Error::StsNullPtr, "Stateful kernel's state is not initialized. " + "Make sure the setup() function properly initializes the state."); + } + auto& st = *state_ptr; call_and_postprocess::get(ctx, IIs))...> ::call(st, get_in::get(ctx, IIs)..., get_out::get(ctx, OIs)...); } diff --git a/modules/gapi/test/cpu/gapi_ocv_stateful_kernel_tests.cpp b/modules/gapi/test/cpu/gapi_ocv_stateful_kernel_tests.cpp index b9985e1377..1ee419aa2c 100644 --- a/modules/gapi/test/cpu/gapi_ocv_stateful_kernel_tests.cpp +++ b/modules/gapi/test/cpu/gapi_ocv_stateful_kernel_tests.cpp @@ -103,8 +103,10 @@ namespace GAPI_OCV_KERNEL_ST(GOCVStInvalidResize, GStInvalidResize, int) { static void setup(const cv::GMatDesc, cv::Size, double, double, int, - std::shared_ptr &/* state */) - { } + std::shared_ptr &state) + { + state = std::make_shared(); + } static void run(const cv::Mat& in, cv::Size sz, double fx, double fy, int interp, cv::Mat &out, int& /* state */) @@ -150,9 +152,10 @@ namespace GAPI_OCV_KERNEL_ST(GOCVCountStateSetups, GCountStateSetups, int) { - static void setup(const cv::GMatDesc &, std::shared_ptr &, + static void setup(const cv::GMatDesc &, std::shared_ptr &state, const cv::GCompileArgs &compileArgs) { + state = std::make_shared(); auto params = cv::gapi::getCompileArg(compileArgs) .value_or(CountStateSetupsParams { }); if (params.pSetupsCount != nullptr) {