Skip to content

fix(security): harden S6069 formatting paths and GenAI ownership - #6036

Closed
renecannao wants to merge 12 commits into
v3.0from
security/s6069-genai-ownership
Closed

fix(security): harden S6069 formatting paths and GenAI ownership#6036
renecannao wants to merge 12 commits into
v3.0from
security/s6069-genai-ownership

Conversation

@renecannao

@renecannao renecannao commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Summary

This branch hardens SonarCloud cpp:S6069 formatting hotspots in ProxySQL-owned code and corrects GenAI handler destruction where forward declarations previously allowed incomplete-type deletes.

  • Replaces bounded and heap-backed sprintf destinations with snprintf using sizeof or the recorded allocation size.
  • Covers the remaining S6069 reports across MySQL, PostgreSQL, ClickHouse, query processing, logging, admin, test, and support code.
  • Keeps vendored sources, including ezOptionParser.hpp, unchanged.

Why

The affected calls did not communicate their destination capacity to the formatting function. Recording or deriving the existing buffer size makes the bound explicit while preserving the generated SQL, protocol output, diagnostics, and test messages.

Validation

  • PROXYSQL40=1 make -j16 debug
  • Static accounting of the public SonarCloud S6069 batch: 106 reported calls removed across 22 source files (105 exact source locations and one known Sonar line-number drift).

Summary by cubic

Hardened all cpp:S6069 formatting paths by bounding string writes and updated GenAI MCP teardown to delete AI/RAG handlers with complete types. This reduces overflow risk and fixes destructor calls without changing runtime behavior.

  • Bug Fixes
    • Replaced unbounded sprintf with snprintf using sizeof or recorded heap sizes across MySQL, PostgreSQL, ClickHouse, logging, admin, tests, and support code.
    • Recorded heap capacities once and reused them in SQL/string builders; kept output formats unchanged.
    • Left vendored sources (e.g., ezOptionParser.hpp) untouched.
    • Included AI_Tool_Handler.h and RAG_Tool_Handler.h in MCP thread to ensure proper handler destruction.
    • Built locally and cleared remaining S6069 hotspots in ProxySQL-owned files.

Written for commit 0836f1b. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Bug Fixes
    • Improved reliability and security by limiting the size of formatted queries, messages, addresses, filenames, and diagnostic output.
    • Preserved existing output, monitoring, logging, and connection behavior while preventing oversized formatting operations.
    • Improved administrative command routing with clearer handling when dispatch fails.
    • Corrected firewall whitelist test wording from “entries” to “rows.”
  • New Features
    • Added integration support for AI and retrieval-augmented generation tools.

MCP_Threads_Handler owns and deletes the AI and RAG tool handlers, but this translation unit previously saw only their forward declarations.

Include both concrete handler definitions before the delete expressions so their destructors and any class-specific deallocation are invoked during MCP thread teardown.
Replace all 52 cpp:S6069 hotspot call sites in MySQL_Thread.cpp, together with the three ordinary S6069 DNS-cache findings. Each fixed-size destination now passes its capacity to snprintf; the processlist address path duplicates the source string directly instead of routing it through a temporary buffer.

The default-variable builder computes the allocated size once and reuses it for formatting, avoiding repeated length scans. Numeric status, port, and audit-message formatting retain their existing output while preventing a write past their local buffers.
Replace the 116 cpp:S6069 formatting hotspots in MySQL_HostGroups_Manager.cpp. Fixed-size diagnostic and statistics buffers now pass their capacity to snprintf, while dynamically allocated SQL buffers retain their allocated size for each subsequent formatting operation.

The group-replication, Galera, and Aurora update paths preserve their existing output formats and allocation margins. Recording each dynamic capacity once also avoids recalculating string lengths at the formatting call, while preventing a write beyond the destination buffer.
Replace the 49 cpp:S6069 hotspots in PgSQL_Thread.cpp with bounded formatting. Listener addresses, variable names, host-cache rows, audit metadata, status output, and process-list fields now pass their destination capacity to snprintf.

The default-variable list calculates the allocated name size once, including its terminator, and uses that same value for allocation and formatting. The existing strings and status values are preserved while preventing a write past local or heap-backed buffers.
Replace the 42 cpp:S6069 hotspots in MySQL_Session.cpp. JSON pointer fields, SQLSTATE copies, session identifiers, hostgroup errors, and user-facing LDAP, authentication, and charset messages now use bounded formatting.

Heap-backed builders record their allocation size once and reuse it for snprintf. The generic SET-variable path also reserves for transaction variable names rewritten for modern MySQL, so its generated statements remain complete while no formatting path can write past its destination buffer.
Replace the 35 cpp:S6069 hotspots in ProxySQL_Statistics.cpp. Interval metric queries record their allocation size for snprintf, while hourly aggregation and retention SQL passes each fixed buffer capacity.

The query strings and time-window calculations remain unchanged. Reusing the recorded heap capacity avoids repeated allocation-size calculations and bounds every SQL formatting operation in this source file.
Replace the 27 cpp:S6069 hotspots in PgSQL_HostGroups_Manager.cpp. PostgreSQL error rows, hostgroup status data, connection metadata, and pointer diagnostics now pass their local buffer capacities to snprintf.

Heap-built server and replication SQL statements retain their allocated capacity and reuse it for formatting. The existing SQL text, diagnostics, and status values are preserved while every Sonar-reported formatting write is bounded.
Replace the 26 cpp:S6069 hotspots in Admin_Handler.cpp. Administrative error responses, lifecycle timeout values, fast-routing counts, version responses, and checksum output now use the capacity of their local buffers.

Config-file errors and temporary SQL messages retain their heap allocation size for snprintf, including the timezone, table-checksum, and admin-error paths. The command responses remain unchanged while each reported formatting write is bounded.
Replace the 22 cpp:S6069 hotspots in ProxySQL_Cluster.cpp. Cluster checksum, metrics, and proxysql-server table rows now use the capacity of their fixed status buffers.

Replication-hostgroup and peer-server synchronization statements record their allocated SQL capacity before calling snprintf. Existing SQL content and escaping paths are retained while the reported formatting writes cannot exceed their destination buffers.
Replace the 19 cpp:S6069 hotspots in MySQL_Monitor.cpp. Monitor query builders, connection-error messages, host:port labels, and Galera status diagnostics now pass a recorded destination capacity to snprintf.

The stack-buffer host labels retain their existing fast path, while heap-backed SQL and error strings record their allocation size once for both allocation and formatting. Existing monitor queries and messages are preserved without unbounded writes.
Replace the 19 cpp:S6069 hotspots in PgSQL_Session.cpp. Internal-session JSON addresses, SQLSTATE values, client-address fallbacks, and hostgroup errors now pass their fixed-buffer capacity to snprintf.

Authentication, SET-variable, tracked-variable, and query-lock messages retain their heap allocation size for formatting. The established PostgreSQL error text and query content are unchanged while each reported write is bounded.
Replace the remaining 106 cpp:S6069 formatting hotspots in 22 ProxySQL-owned source files. Logger, protocol, monitoring, query-processing, configuration, HTTP, support, and admin test code now supply each fixed or heap-backed destination capacity to snprintf.

Heap-backed builders retain allocation sizes for formatting, while fixed buffers consistently use sizeof. The generated SQL, diagnostic strings, protocol output, and test messages retain their existing forms while no reported formatting write can exceed its destination buffer. The vendored ezOptionParser.hpp remains intentionally unchanged.
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The pull request replaces unbounded sprintf calls with size-bounded snprintf across ProxySQL runtime, protocol, logging, monitoring, statistics, test, and integration code. It also adds AI and RAG tool-handler includes to MCP_Thread.cpp.

Changes

Bounded formatting hardening

Layer / File(s) Summary
Admin, routing, and backend query formatting
lib/Admin_Handler.cpp, lib/ClickHouse_Server.cpp, lib/GTID_Server_Data.cpp, lib/MySQL_HostGroups_Manager.cpp
Error messages, addresses, statistics, and generated SQL now use explicit buffer capacities with snprintf.
MySQL runtime, sessions, logging, and monitoring
lib/MySQL_Logger.cpp, lib/MySQL_Monitor.cpp, lib/MySQL_Session.cpp, lib/MySQL_Thread.cpp, lib/MySQL_Protocol.cpp, lib/MySQL_ResultSet.cpp
MySQL runtime formatting now uses bounded output for diagnostics, protocol values, addresses, status data, audit data, and monitoring SQL.
PostgreSQL runtime and protocol formatting
lib/PgSQL_HostGroups_Manager.cpp, lib/PgSQL_Logger.cpp, lib/PgSQL_Protocol.cpp, lib/PgSQL_Session.cpp, lib/PgSQL_Thread.cpp
PostgreSQL SQL, authentication messages, addresses, protocol tags, processlist values, and metrics now use bounded formatting.
Statistics, utilities, tests, and integration
lib/ProxySQL_Statistics.cpp, lib/Query_Processor.cpp, lib/Query_Cache.cpp, lib/ProxySQL_Cluster.cpp, lib/ProxySQL_Admin_Tests*.cpp, lib/sqlite3db.cpp, plugins/genai/src/MCP_Thread.cpp
Statistics and utility formatting now supplies buffer sizes. Test formatting is bounded. MCP includes AI and RAG tool handlers.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

  • sysown/proxysql#5313: Replaces sprintf with bounded snprintf in overlapping runtime code, including MySQL_Session.cpp.
  • sysown/proxysql#5374: Modifies overlapping address and server formatting in MySQL_Logger.cpp.
  • sysown/proxysql#5594: Hardens formatting in shared files such as MySQL_HostGroups_Manager.cpp and MySQL_Session.cpp.

Poem

A rabbit bounds through buffers bright,
snprintf guards each string tonight.
SQL and logs stay neatly penned,
From session start to query end.
AI tools join the MCP trail—
Safe little hops along the rail.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.05% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes both main changes: hardening S6069 formatting paths and correcting GenAI ownership.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch security/s6069-genai-ownership

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gitar-bot

gitar-bot Bot commented Aug 11, 2026

Copy link
Copy Markdown
Code Review ✅ Approved

Hardens SonarCloud S6069 formatting paths by replacing unsafe sprintf destinations with bounded snprintf calls across ProxySQL source files and corrects GenAI handler destruction. No issues found.

Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Auto-apply Compact
gitar auto-apply:on         
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
D Maintainability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@renecannao

Copy link
Copy Markdown
Contributor Author

@cubic-dev-ai help

@cubic-dev-ai

cubic-dev-ai Bot commented Aug 11, 2026

Copy link
Copy Markdown

@cubic-dev-ai help

@renecannao Hi! I'm cubic. Here's how I can help with your PR:

Ask questions

  • @cubic why did you suggest this change?

Request reviews

  • @cubic review this - Run a code review

Give feedback

  • @cubic this suggestion doesn't work for our use case

Request fixes

  • @cubic fix this - Ask me to fix an issue. I can push commits to this PR or open a new PR; tell me which you want.

@renecannao

Copy link
Copy Markdown
Contributor Author

@cubic review this PR

@renecannao
renecannao marked this pull request as ready for review August 11, 2026 16:23
@cubic-dev-ai

cubic-dev-ai Bot commented Aug 11, 2026

Copy link
Copy Markdown

@cubic review this PR

@renecannao I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai

cubic-dev-ai Bot commented Aug 11, 2026

Copy link
Copy Markdown

We've triggered an ultrareview automatically — This large, 33-file hardening sweep across MySQL/PgSQL/ClickHouse, logging, admin, and query processing touches core buffer calculations and fixes an incomplete-delete destructor bug—a subtle miscalculation could cause truncation or corruption in production paths, so a deep review is worthwhile.. I'll post findings when complete.

An ultrareview is cubic's deepest review, catching hard-to-find bugs in the most critical PRs. It runs a longer, multi-pass analysis using cubic's most capable review models, and typically takes around 30 minutes. It consumes your team's reviewed-lines allowance at 3× the standard rate.

Automated ultrareviews are disabled by default. We triggered this run as part of your trial. Want cubic to do this for every high-risk PR? Enable auto-ultrareview in your settings.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
lib/MySQL_HostGroups_Manager.cpp (1)

4327-4347: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Fix the reused query buffer size for the double-hostname CASE statement.

query_size is computed once for the "UPDATE OR IGNORE ..." statement, which references _hostname with a single %s. The buffer and query_size are then reused for the later "UPDATE mysql_servers_incoming SET status=(CASE ...)" statement, which references _hostname with two %s placeholders.

The margin left after accounting for the format-string literal is about 75 bytes minus strlen(_hostname). For hostnames longer than approximately 75 characters (for example, long Kubernetes service DNS names or cloud FQDNs), snprintf truncates this statement silently. The truncated UPDATE can leave a Group Replication server in the wrong hostgroup or fail outright, corrupting routing state without any error being logged.

Compute a size specific to this statement instead of reusing query_size from the earlier allocation. The same pattern repeats in update_group_replication_set_read_only (lines 4433-4451).

🐛 Proposed fix for both functions
 			q=(char *)"UPDATE mysql_servers_incoming SET status=(CASE "
 				" (SELECT status FROM mysql_servers_incoming WHERE hostname='%s' AND port=%d AND"
 					" hostgroup_id=(SELECT offline_hostgroup FROM mysql_group_replication_hostgroups WHERE writer_hostgroup=%d)) WHEN 2 THEN 2 ELSE 0 END)"
 				" WHERE hostname='%s' AND port=%d AND hostgroup_id=(SELECT offline_hostgroup FROM mysql_group_replication_hostgroups WHERE writer_hostgroup=%d)";
-			snprintf(query, query_size, q, _hostname, _port, _writer_hostgroup, _hostname, _port, _writer_hostgroup);
+			{
+				size_t q3_size = strlen(q) + 2 * strlen(_hostname) + 64;
+				if (q3_size > query_size) {
+					query = (char *)realloc(query, q3_size);
+					query_size = q3_size;
+				}
+			}
+			snprintf(query, query_size, q, _hostname, _port, _writer_hostgroup, _hostname, _port, _writer_hostgroup);

Apply the equivalent change to the matching statement in update_group_replication_set_read_only.

Also applies to: 4433-4451

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/MySQL_HostGroups_Manager.cpp` around lines 4327 - 4347, In the
query-building logic of the current function and
update_group_replication_set_read_only, allocate and size the buffer
specifically for the final UPDATE ... CASE statement, accounting for both
_hostname substitutions, instead of reusing query_size computed for the earlier
single-hostname query. Apply the same correction to the matching statement in
update_group_replication_set_read_only and preserve the existing SQL and
execution flow.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/PgSQL_Logger.cpp`:
- Around line 868-874: Update both filename allocation branches in the logger’s
filename construction logic to size filen_size from the actual formatted
events.log_file_id length, while retaining the existing directory and basename
formatting. Ensure nine-digit and larger IDs are not truncated, and add coverage
for a nine-digit log ID.

In `@lib/PgSQL_Thread.cpp`:
- Around line 1625-1626: Update both snprintf calls handling num_threads to use
the unsigned integer format specifier %u instead of %d, preserving the existing
buffer and fallback behavior.

In `@lib/ProxySQL_Statistics.cpp`:
- Around line 563-565: Check the result of every malloc assignment to query in
the affected branches before invoking snprintf. Update the surrounding
query-building flow in the relevant function to return or propagate an error on
allocation failure, ensuring no formatting call dereferences a null buffer;
apply the same guard to all listed allocation sites.
- Around line 555-575: The metric query templates in the interval switch use
`%d` for `time_t` bounds, causing a variadic type mismatch. Update both `query1`
and `query2` to use `%lld`, and cast each `ts-interval` and `ts` argument passed
to `snprintf` to `long long` while preserving the existing query selection and
interval behavior.

---

Outside diff comments:
In `@lib/MySQL_HostGroups_Manager.cpp`:
- Around line 4327-4347: In the query-building logic of the current function and
update_group_replication_set_read_only, allocate and size the buffer
specifically for the final UPDATE ... CASE statement, accounting for both
_hostname substitutions, instead of reusing query_size computed for the earlier
single-hostname query. Apply the same correction to the matching statement in
update_group_replication_set_read_only and preserve the existing SQL and
execution flow.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 37238019-56ed-472a-aa12-c7d81ca0a9db

📥 Commits

Reviewing files that changed from the base of the PR and between 7b0d92f and 0836f1b.

📒 Files selected for processing (33)
  • lib/Admin_Handler.cpp
  • lib/ClickHouse_Server.cpp
  • lib/GTID_Server_Data.cpp
  • lib/MySQL_HostGroups_Manager.cpp
  • lib/MySQL_Logger.cpp
  • lib/MySQL_Monitor.cpp
  • lib/MySQL_PreparedStatement.cpp
  • lib/MySQL_Protocol.cpp
  • lib/MySQL_Query_Processor.cpp
  • lib/MySQL_ResultSet.cpp
  • lib/MySQL_Session.cpp
  • lib/MySQL_Thread.cpp
  • lib/MySQL_encode.cpp
  • lib/PgSQL_HostGroups_Manager.cpp
  • lib/PgSQL_Logger.cpp
  • lib/PgSQL_Protocol.cpp
  • lib/PgSQL_Query_Processor.cpp
  • lib/PgSQL_Session.cpp
  • lib/PgSQL_Thread.cpp
  • lib/ProxySQL_Admin_Tests.cpp
  • lib/ProxySQL_Admin_Tests2.cpp
  • lib/ProxySQL_Cluster.cpp
  • lib/ProxySQL_Config.cpp
  • lib/ProxySQL_HTTP_Server.cpp
  • lib/ProxySQL_Statistics.cpp
  • lib/QP_query_digest_stats.cpp
  • lib/Query_Cache.cpp
  • lib/Query_Processor.cpp
  • lib/debug.cpp
  • lib/mysql_connection.cpp
  • lib/proxysql_coredump.cpp
  • lib/sqlite3db.cpp
  • plugins/genai/src/MCP_Thread.cpp
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
  • GitHub Check: Gitar
  • GitHub Check: lint
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{cpp,h,hpp}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{cpp,h,hpp}: Class names must use PascalCase with protocol prefixes such as MySQL_, PgSQL_, and ProxySQL_.
Member variables must use snake_case.
Constants and macros must use UPPER_SNAKE_CASE.
Use C++17, and gate conditional code with #ifdef PROXYSQL31, #ifdef PROXYSQL40, #ifdef PROXYSQLFFTO, #ifdef PROXYSQLTSDB, and #ifdef PROXYSQLCLICKHOUSE; PROXYSQLGENAI must not guard core code outside plugins/genai/.
Consider performance implications when changing hot paths or other performance-critical code.
Use RAII for resource management and jemalloc for allocation.
Use pthread mutexes for synchronization and std::atomic<> for counters.

Files:

  • lib/GTID_Server_Data.cpp
  • lib/debug.cpp
  • lib/ProxySQL_Admin_Tests.cpp
  • lib/ProxySQL_Config.cpp
  • lib/PgSQL_Query_Processor.cpp
  • lib/MySQL_Query_Processor.cpp
  • plugins/genai/src/MCP_Thread.cpp
  • lib/ProxySQL_HTTP_Server.cpp
  • lib/QP_query_digest_stats.cpp
  • lib/MySQL_PreparedStatement.cpp
  • lib/proxysql_coredump.cpp
  • lib/MySQL_Protocol.cpp
  • lib/MySQL_ResultSet.cpp
  • lib/mysql_connection.cpp
  • lib/Query_Processor.cpp
  • lib/MySQL_Logger.cpp
  • lib/ProxySQL_Cluster.cpp
  • lib/sqlite3db.cpp
  • lib/PgSQL_HostGroups_Manager.cpp
  • lib/ProxySQL_Admin_Tests2.cpp
  • lib/PgSQL_Logger.cpp
  • lib/ProxySQL_Statistics.cpp
  • lib/MySQL_encode.cpp
  • lib/ClickHouse_Server.cpp
  • lib/PgSQL_Protocol.cpp
  • lib/Query_Cache.cpp
  • lib/Admin_Handler.cpp
  • lib/MySQL_Monitor.cpp
  • lib/PgSQL_Session.cpp
  • lib/MySQL_Session.cpp
  • lib/MySQL_HostGroups_Manager.cpp
  • lib/MySQL_Thread.cpp
  • lib/PgSQL_Thread.cpp
🧠 Learnings (1)
📚 Learning: 2026-07-13T08:28:59.932Z
Learnt from: wazir-ahmed
Repo: sysown/proxysql PR: 5861
File: lib/ProxySQL_Cluster.cpp:2251-2255
Timestamp: 2026-07-13T08:28:59.932Z
Learning: When reviewing ProxySQL cluster sync code that populates/updates `mysql_servers_v2` (e.g., paths like `pull_mysql_servers_v2_from_peer` and other cluster sync logic), remember that the MySQL server status `SHUNNED_AWS_BGD` is runtime-only: for cluster synchronization it is normalized together with `SHUNNED` to `ONLINE` before values are exposed/checksummed for synchronization. Therefore, during normal cluster sync operation you should not expect case-mismatched or “raw” `SHUNNED`/`SHUNNED_AWS_BGD` strings to reach the `mysql_servers_v2` insert/update path—if they do, treat it as evidence that the normalization step was bypassed or altered (and verify the normalization logic and call flow).

Applied to files:

  • lib/ProxySQL_Cluster.cpp
🪛 Cppcheck (2.21.0)
lib/debug.cpp

[warning] 384-384: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 385-385: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 387-387: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 388-388: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 390-390: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 392-392: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)

lib/MySQL_PreparedStatement.cpp

[warning] 1008-1008: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 1010-1010: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 1012-1012: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 1015-1015: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 1018-1018: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 1020-1020: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 1022-1022: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 1024-1024: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)

lib/Query_Processor.cpp

[warning] 736-736: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 2810-2810: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)

lib/sqlite3db.cpp

[warning] 551-551: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 581-581: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)

lib/PgSQL_HostGroups_Manager.cpp

[warning] 175-175: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 177-177: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 188-188: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 190-190: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 1370-1370: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 1757-1757: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 1796-1796: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 3024-3024: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 3026-3026: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 3027-3027: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 3047-3047: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 3279-3279: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 3280-3280: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)

lib/PgSQL_Logger.cpp

[warning] 870-870: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 874-874: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 905-905: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 909-909: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 1017-1017: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 1114-1114: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 1237-1237: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 1275-1275: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)

lib/ProxySQL_Statistics.cpp

[warning] 565-565: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 575-575: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 623-623: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 633-633: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 669-669: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 679-679: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 717-717: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 727-727: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 765-765: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 775-775: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)

lib/MySQL_encode.cpp

[error] 42-42: If memory allocation fails

(nullPointerArithmeticOutOfMemory)

lib/ClickHouse_Server.cpp

[warning] 701-701: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 733-733: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 864-864: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 878-878: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 946-946: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 959-959: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 1072-1072: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 1302-1302: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)

lib/Query_Cache.cpp

[warning] 659-659: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 663-663: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 665-665: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 669-669: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 671-671: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 675-675: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 677-677: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 681-681: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 683-683: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 687-687: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 689-689: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 693-693: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 695-695: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 699-699: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)

lib/MySQL_Thread.cpp

[warning] 1526-1526: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 3023-3023: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 3292-3292: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 5420-5420: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 5422-5422: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 5426-5426: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 5428-5428: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 5432-5432: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 5415-5415: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 6041-6041: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)

🔇 Additional comments (34)
lib/Admin_Handler.cpp (1)

621-625: LGTM!

Also applies to: 628-640, 833-841, 843-850, 874-901, 903-917, 926-956, 959-977, 1553-1568, 1620-1631, 1655-1710, 1780-1785, 1795-1800, 1855-1901, 1920-1937, 2251-2267, 2382-2410, 2394-2409, 2517-2534, 2564-2582, 2668-2685, 2796-2813, 3479-3487, 3489-3500, 3769-3792, 3796-3823, 4200-4220, 4560-4582, 5450-5470

lib/ClickHouse_Server.cpp (1)

694-708: LGTM!

Also applies to: 730-740, 858-871, 872-885, 940-951, 953-965, 986-1023, 1066-1078, 1295-1306, 1790-1793

lib/GTID_Server_Data.cpp (1)

172-174: LGTM!

lib/MySQL_HostGroups_Manager.cpp (1)

1339-1352: LGTM!

Also applies to: 1953-1957, 2001-2010, 2438-2449, 3234-3283, 3502-3574, 4297-4326, 4386-4432, 4453-4471, 4523-4693, 4712-4845, 5071-5228, 5230-5310, 5324-5537, 5544-5772, 5820-5862, 5867-5987, 6711-6737, 6896-7131, 7133-7252

lib/MySQL_Logger.cpp (1)

583-594: LGTM!

Also applies to: 691-699, 701-705, 1141-1152, 1155-1171, 1381-1397, 1439-1455, 1556-1565, 1838-1849, 2182-2201, 2220-2229

lib/MySQL_Monitor.cpp (1)

1640-1678: LGTM!

Also applies to: 1762-1774, 1966-1971, 2177-2189, 2440-2449, 2459-2467, 2571-2583, 2740-2745, 2886-2897, 3407-3414, 3468-3475, 3526-3538, 6288-6300, 6396-6409, 8403-8410, 9296-9303, 9448-9460, 9944-9957, 10116-10118

lib/MySQL_PreparedStatement.cpp (1)

1004-1027: LGTM!

lib/MySQL_Protocol.cpp (1)

4202-4206: LGTM!

lib/proxysql_coredump.cpp (1)

74-76: LGTM!

lib/sqlite3db.cpp (1)

545-551: LGTM!

Also applies to: 575-582, 681-688, 1121-1134

plugins/genai/src/MCP_Thread.cpp (1)

11-13: LGTM!

lib/MySQL_Query_Processor.cpp (1)

97-97: LGTM!

Also applies to: 834-834

lib/MySQL_ResultSet.cpp (1)

450-450: LGTM!

lib/MySQL_Session.cpp (1)

1133-1137: LGTM!

Also applies to: 1175-1175, 1245-1247, 2780-2780, 2829-2831, 2904-2906, 2960-2960, 3038-3038, 3087-3095, 3106-3108, 3116-3118, 3129-3131, 3224-3224, 3312-3312, 3398-3398, 3755-3755, 3847-3847, 3947-3947, 4036-4038, 4232-4234, 4448-4448, 4496-4496, 5188-5190, 5662-5662, 5687-5687, 6727-6729, 6796-6798, 6824-6826, 7666-7673, 7971-7973, 8012-8012, 8089-8089, 8273-8273, 8420-8422, 8697-8697, 8782-8782, 9185-9187

lib/MySQL_Thread.cpp (1)

1524-1526: LGTM!

Also applies to: 1874-1874, 1990-1990, 2078-2078, 2140-2144, 2471-2471, 3020-3023, 3291-3293, 3469-3469, 4712-4712, 4827-4827, 4841-4841, 5001-5001, 5343-5343, 5414-5433, 5519-5519, 5536-5536, 5550-5568, 5593-5671, 6040-6042, 6063-6082, 6095-6095, 6112-6120, 6134-6138, 6214-6214, 6228-6228, 6240-6243

lib/MySQL_encode.cpp (1)

42-42: LGTM!

lib/PgSQL_HostGroups_Manager.cpp (1)

174-178: LGTM!

Also applies to: 187-191, 1368-1370, 1755-1757, 1793-1796, 2487-2489, 3023-3028, 3046-3051, 3066-3066, 3278-3281, 3305-3339

lib/PgSQL_Logger.cpp (1)

390-390: LGTM!

Also applies to: 476-476, 485-485, 675-697, 1015-1017, 1112-1114, 1235-1237, 1273-1275, 1584-1584

lib/PgSQL_Protocol.cpp (1)

994-994: LGTM!

Also applies to: 1004-1004, 1185-1187, 1266-1268, 1661-1661, 1670-1670

lib/Query_Processor.cpp (2)

2197-2200: LGTM!

Also applies to: 2737-2738, 2804-2810


730-736: 🎯 Functional Correctness

No change needed. keylen includes 30 bytes of headroom for separators, decimal digits, and the terminating NUL, so the dynamic allocation is sufficient.

			> Likely an incorrect or invalid review comment.
lib/debug.cpp (1)

383-393: LGTM!

lib/mysql_connection.cpp (1)

814-814: LGTM!

Also applies to: 3267-3267, 3298-3298

lib/PgSQL_Query_Processor.cpp (1)

192-193: LGTM!

Also applies to: 452-453

lib/PgSQL_Session.cpp (1)

676-681: LGTM!

Also applies to: 768-770, 788-790, 829-831, 1400-1402, 1456-1459, 1734-1736, 2045-2047, 2089-2091, 2507-2510, 4009-4013, 4081-4085, 4097-4101, 4156-4157, 4175-4177, 4628-4630, 5245-5249, 6135-6137, 6545-6548

lib/PgSQL_Thread.cpp (1)

1239-1243: LGTM!

Also applies to: 1421-1423, 1488-1490, 1627-1630, 1950-1952, 2399-2403, 2634-2638, 2797-2799, 3907-3908, 3922-3923, 3937-3938, 4114-4117, 4434-4435, 4508-4527, 4640-4647, 4658-4661, 4708-4763, 5164-5167, 5186-5197, 5209-5210, 5222-5233, 5246-5255, 5320-5321, 5334-5335, 5346-5349

lib/ProxySQL_Admin_Tests.cpp (1)

89-90: LGTM!

Also applies to: 109-111

lib/ProxySQL_Admin_Tests2.cpp (1)

393-395: LGTM!

Also applies to: 428-430, 1256-1258, 1292-1294, 1308-1310, 1382-1384, 1393-1396, 1403-1406, 1422-1424, 1436-1439, 1454-1459

lib/ProxySQL_Cluster.cpp (1)

2291-2293: LGTM!

Also applies to: 2324-2326, 2335-2337, 2368-2370, 2379-2381, 2879-2881, 4534-4535, 4562-4571, 4610-4627, 4656-4658

lib/ProxySQL_Config.cpp (1)

156-158: LGTM!

lib/ProxySQL_HTTP_Server.cpp (1)

141-148: LGTM!

Also applies to: 168-170

lib/ProxySQL_Statistics.cpp (1)

833-852: LGTM!

Also applies to: 913-932, 1066-1085, 1251-1270, 1356-1375

lib/QP_query_digest_stats.cpp (1)

164-165: LGTM!

Also applies to: 195-197

lib/Query_Cache.cpp (1)

658-700: LGTM!

Comment thread lib/PgSQL_Logger.cpp
Comment on lines +868 to +874
size_t filen_size = strlen(events.base_filename) + 11;
filen=(char *)malloc(filen_size);
snprintf(filen, filen_size, "%s.%08d",events.base_filename,events.log_file_id);
} else { // relative path
filen=(char *)malloc(strlen(events.datadir)+strlen(events.base_filename)+11);
sprintf(filen,"%s/%s.%08d",events.datadir,events.base_filename,events.log_file_id);
size_t filen_size = strlen(events.datadir) + strlen(events.base_filename) + 11;
filen=(char *)malloc(filen_size);
snprintf(filen, filen_size, "%s/%s.%08d",events.datadir,events.base_filename,events.log_file_id);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Size log filenames for the full file ID.

At Line [868] and Line [903], filen_size reserves space for only eight ID digits. %08d pads short values but does not limit longer values. When a log ID reaches nine digits, snprintf truncates the filename. The logger can then open the wrong path or fail to rotate. Compute the required length from the formatted ID, and add a test for a nine-digit ID.

Also applies to: 903-909

🧰 Tools
🪛 Cppcheck (2.21.0)

[warning] 870-870: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 874-874: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/PgSQL_Logger.cpp` around lines 868 - 874, Update both filename allocation
branches in the logger’s filename construction logic to size filen_size from the
actual formatted events.log_file_id length, while retaining the existing
directory and basename formatting. Ensure nine-digit and larger IDs are not
truncated, and add coverage for a nine-digit log ID.

Comment thread lib/PgSQL_Thread.cpp
Comment on lines +1625 to 1626
snprintf(intbuf, sizeof(intbuf), "%d", (num_threads ? num_threads : DEFAULT_NUM_THREADS));
return strdup(intbuf);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 4 --glob '*.{cpp,h,hpp}' '\bnum_threads\b' .

Repository: sysown/proxysql

Length of output: 2043


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- candidate files ---'
git ls-files '*PgSQL_Thread.cpp' '*.{cpp,h,hpp}' | head -200

printf '%s\n' '--- references to num_threads ---'
rg -n -C 6 --glob '*.{cpp,h,hpp}' '\bnum_threads\b' .

printf '%s\n' '--- target regions ---'
file=$(git ls-files '*PgSQL_Thread.cpp' | head -1)
if [ -n "$file" ]; then
  sed -n '1608,1632p;4650,4672p' "$file"
fi

Repository: sysown/proxysql

Length of output: 2014


🌐 Web query:

site:github.com/sysown/proxysql "PgSQL_Thread.cpp" "num_threads"

💡 Result:

PgSQL_Thread.cpp is a source file within the ProxySQL codebase that contains the implementation for handling PostgreSQL thread logic, specifically related to the PgSQL_Threads_Handler class [1][2]. In the context of this file, num_threads is typically a member variable or parameter used to represent the number of active PostgreSQL thread workers within the ProxySQL instance [1][3][2]. Key details regarding num_threads in PgSQL_Thread.cpp include: 1. Thread Management: The variable is used extensively by the PgSQL_Threads_Handler to iterate over and manage thread workers, such as in the creation of backend connections, handling of process lists, and aggregation of transaction-poisoned counters [1][4][3]. 2. Global Status: The number of PgSQL thread workers is exposed in ProxySQL statistics via the PgSQL_Thread_Workers gauge, which is populated by the PgSQL_Threads_Handler::SQL3_GlobalStatus method in PgSQL_Thread.cpp [2]. 3. Resource Management: It is also used to balance connection caching, where it determines the distribution of cached connections between local thread caches and the shared host group manager pool [5]. 4. Default Value: The codebase defines a constant DEFAULT_NUM_THREADS (typically set to 4) within the context of these thread operations [1]. The file is integral to how ProxySQL scales and manages PostgreSQL backend connections, ensuring that workloads are distributed across the configured number of threads [1][5].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

url='https://raw.githubusercontent.com/sysown/proxysql/9cc20a87/lib/PgSQL_Thread.cpp'
tmp=$(mktemp)
trap 'rm -f "$tmp"' EXIT
curl --fail --silent --show-error --location "$url" -o "$tmp"

printf '%s\n' '--- target regions ---'
sed -n '1615,1632p;4655,4672p' "$tmp"

printf '%s\n' '--- declarations, assignments, and uses ---'
rg -n -C 5 '\b(num_threads|DEFAULT_NUM_THREADS)\b' "$tmp"

Repository: sysown/proxysql

Length of output: 2014


🌐 Web query:

site:github.com/sysown/proxysql/blob/lib/PgSQL_Thread.cpp "snprintf(intbuf" "num_threads"

💡 Result:

No matching result was found for:

site:github.com/sysown/proxysql/blob/lib/PgSQL_Thread.cpp "snprintf(intbuf" "num_threads"

The ProxySQL repository exists, but that exact file/path or code fragment was not indexed by search. (github.com)

Citations:


🌐 Web query:

"DEFAULT_NUM_THREADS" "num_threads" "PgSQL_Threads_Handler"

💡 Result:

The term DEFAULT_NUM_THREADS in the context of PgSQL_Threads_Handler refers to a hardcoded constant in the ProxySQL source code, defined as 4 [1][2]. PgSQL_Threads_Handler is a class within ProxySQL responsible for managing PostgreSQL-related threads [3][4]. The constant DEFAULT_NUM_THREADS (defined as 4) sets the initial or default number of worker threads created by the handler when managing PostgreSQL connections [1][2]. The handler uses these threads to process queries and handle client sessions [5][6]. In the ProxySQL source code, the PgSQL_Threads_Handler class includes an initialization function (init) that allows for the specification of the number of threads to create, defaulting to this predefined constant when no specific value is provided [3]. The handler also manages thread heartbeats and allows for the addition or deletion of listeners that utilize these threads [5][7]. It is important to note that DEFAULT_NUM_THREADS is a common naming convention for constants in many C++ and Java projects and appears in various software contexts (such as Apache Druid, Solana, and others) with different assigned values [8][9][10][11]; however, specifically for the ProxySQL PgSQL_Threads_Handler, it is defined as 4 [1][2].

Citations:


🌐 Web query:

site:fossies.org/linux/proxysql/lib/PgSQL_Thread.cpp "num_threads"

💡 Result:

In computer programming, num_threads is a common variable or parameter name used to specify the number of execution threads a program or specific task should utilize [1]. It serves as a configuration setting that allows developers to control concurrency, enabling a workload to be distributed across multiple processing units or to manage how a service handles parallel operations [1]. In practice, this identifier is often used when allocating resources or initializing multi-threaded environments, such as setting up socket listeners for network services or defining the parallelism level for computational tasks [1]. Because it is a generic naming convention rather than a language-specific keyword, its exact implementation depends on the specific library or application code where it is defined [1].

Citations:


🌐 Web query:

site:github.com/sysown/proxysql "unsigned int num_threads"

💡 Result:

In programming, the term unsigned int num_threads is not a keyword or built-in standard; it is a common variable declaration used in C and C++ to store the count of threads to be created or managed by an application [1][2][3]. Because the number of threads must always be a non-negative integer, programmers use the unsigned int data type to explicitly enforce this constraint, ensuring the value cannot be negative [1][3]. Key characteristics include: 1. Data Type: unsigned int (an unsigned integer type) ensures the value is 0 or greater. 2. Purpose: It is typically used as a parameter for thread pool initialization [2][4][5], a counter in loops iterating through threads [1][3], or a configuration variable to define concurrency levels [3]. 3. Context: It appears frequently in multi-threaded applications, such as database proxies or performance testing tools, where managing specific thread counts is required to optimize resource usage and workload distribution [1][2][3]. For example, in codebases like ProxySQL, this variable is used to configure listener managers or worker thread handlers, defining how many concurrent execution units the system should spawn [1][4][5].

Citations:


🌐 Web query:

"PgSQL_Threads_Handler" "num_threads;" ProxySQL

💡 Result:

In ProxySQL, PgSQL_Threads_Handler is the internal C++ class responsible for managing the pool of worker threads that handle PostgreSQL traffic [1][2]. The member variable num_threads within the PgSQL_Threads_Handler class defines the number of worker threads assigned to process PostgreSQL traffic [1][2][3]. When ProxySQL initializes the PgSQL module, it uses this value to determine how many worker threads to create [2]. These worker threads execute the pgsql_worker_thread_func routine to manage client-to-backend communication and handle queries [2]. It is important to distinguish this internal C++ class member from user-configurable settings: 1. Internal Class Member (num_threads): This is an unsigned integer defined within the PgSQL_Threads_Handler C++ code [1][4]. It is set during the initialization of the PgSQL module based on the ProxySQL global configuration [2]. 2. User-Configurable Settings: While users do not directly modify the num_threads member of the PgSQL_Threads_Handler class, they control the number of threads used for PostgreSQL traffic via ProxySQL global variables (typically set in the main configuration or via the admin interface, similar to mysql-threads for MySQL traffic) [5][6]. Additionally, for the PostgreSQL Monitoring module, users can specifically configure the number of worker threads using the pgsql-monitor_threads variable [7]. In summary, PgSQL_Threads_Handler::num_threads is the internal variable representing the active count of worker threads designated for PostgreSQL traffic processing, which is established at runtime based on the configured thread settings [2][8].

Citations:


Use %u for num_threads in both snprintf calls. num_threads is unsigned, but %d requires int; the mismatch causes undefined behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/PgSQL_Thread.cpp` around lines 1625 - 1626, Update both snprintf calls
handling num_threads to use the unsigned integer format specifier %u instead of
%d, preserving the existing buffer and fallback behavior.

Comment on lines +555 to +575
size_t query_size = 0;
char *query1 = (char *)"SELECT SUBSTR(FROM_UNIXTIME(timestamp),0,20) ts, timestamp, Client_Connections_aborted, Client_Connections_connected, Client_Connections_created, Server_Connections_aborted, Server_Connections_connected, Server_Connections_created, ConnPool_get_conn_failure, ConnPool_get_conn_immediate, ConnPool_get_conn_success, Questions, Slow_queries, GTID_consistent_queries FROM mysql_connections WHERE timestamp BETWEEN %d AND %d ORDER BY timestamp";
char *query2 = (char *)"SELECT SUBSTR(FROM_UNIXTIME(timestamp),0,20) ts, timestamp, Client_Connections_aborted, Client_Connections_connected, Client_Connections_created, Server_Connections_aborted, Server_Connections_connected, Server_Connections_created, ConnPool_get_conn_failure, ConnPool_get_conn_immediate, ConnPool_get_conn_success, Questions, Slow_queries, GTID_consistent_queries FROM mysql_connections_hour WHERE timestamp BETWEEN %d AND %d ORDER BY timestamp";
time_t ts = time(NULL);
switch (interval) {
case 1800:
case 3600:
case 7200:
query = (char *)malloc(strlen(query1)+128);
sprintf(query, query1, ts-interval, ts);
query_size = strlen(query1) + 128;
query = (char *)malloc(query_size);
snprintf(query, query_size, query1, ts-interval, ts);
break;
case 28800:
case 86400:
case 259200:
case 604800:
case 2592000:
case 7776000:
query = (char *)malloc(strlen(query2)+128);
sprintf(query, query2, ts-interval, ts);
query_size = strlen(query2) + 128;
query = (char *)malloc(query_size);
snprintf(query, query_size, query2, ts-interval, ts);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 3 'time_t ts|BETWEEN %d|snprintf\(query' lib/ProxySQL_Statistics.cpp
rg -n -C 3 '\btime_t\b' --glob '*.{cpp,h,hpp}' .

Repository: sysown/proxysql

Length of output: 2043


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- target file context ---'
sed -n '520,790p' lib/ProxySQL_Statistics.cpp

printf '%s\n' '--- timestamp declarations and query templates ---'
rg -n -C 4 'time_t|BETWEEN %d|BETWEEN %lld|snprintf\(query|query[12]' lib/ProxySQL_Statistics.cpp

printf '%s\n' '--- related timestamp declarations and schema definitions ---'
rg -n -C 3 '\btimestamp\b' --glob '*.{cpp,h,hpp,sql}' . | head -n 240

Repository: sysown/proxysql

Length of output: 2014


🏁 Script executed:

#!/bin/bash
set -euo pipefail

url='https://raw.githubusercontent.com/sysown/proxysql/master/lib/ProxySQL_Statistics.cpp'
tmp=$(mktemp)
trap 'rm -f "$tmp"' EXIT

curl -fsSL "$url" -o "$tmp"
printf '%s\n' '--- matching declarations and calls ---'
rg -n -C 5 'time_t|BETWEEN %d|BETWEEN %lld|snprintf\(query|query[12]' "$tmp"

printf '%s\n' '--- target regions ---'
sed -n '520,790p' "$tmp"

printf '%s\n' '--- timestamp schema references ---'
curl -fsSL 'https://api.github.com/search/code?q=repo%3Asysown%2Fproxysql+mysql_connections+timestamp' |
  jq -r '.items[]?.html_url' 2>/dev/null || true

Repository: sysown/proxysql

Length of output: 2014


🌐 Web query:

github sysown proxysql lib/ProxySQL_Statistics.cpp "BETWEEN %d" "time_t ts"

💡 Result:

The code snippet WHERE timestamp BETWEEN %d AND %d found in lib/ProxySQL_Statistics.cpp within the sysown/proxysql repository is used in SQL query templates for retrieving time-series metrics from ProxySQL's on-disk SQLite statistics databases [1][2][3]. In this context, the placeholders %d are filled using sprintf to generate queries dynamically at runtime [1][2]. The values injected into these placeholders are time-based integers calculated using a time_t variable (ts), which represents the current time (time(NULL)), and a specified interval [1][2]. Specifically, the queries typically take the form: sprintf(query, query_template, ts - interval, ts); This effectively constructs a SQL BETWEEN clause that filters database records to those falling within the requested time window (from ts - interval to ts) [1][2][3]. This logic is applied across various statistics tables—such as mysql_connections and system_cpu—to aggregate and retrieve metrics stored in high-resolution and low-resolution (hourly) tables [1][3][4]. The pattern ensures that ProxySQL can efficiently extract historical performance data based on the desired reporting duration [4].

Citations:


Use a matching format for time_t in the metric query templates.

The five metric getters pass time_t values to %d. This variadic type mismatch can produce incorrect BETWEEN bounds. Cast the timestamps to long long and use %lld in each query template.

🧰 Tools
🪛 Cppcheck (2.21.0)

[warning] 565-565: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)


[warning] 575-575: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/ProxySQL_Statistics.cpp` around lines 555 - 575, The metric query
templates in the interval switch use `%d` for `time_t` bounds, causing a
variadic type mismatch. Update both `query1` and `query2` to use `%lld`, and
cast each `ts-interval` and `ts` argument passed to `snprintf` to `long long`
while preserving the existing query selection and interval behavior.

Comment on lines +563 to +565
query_size = strlen(query1) + 128;
query = (char *)malloc(query_size);
snprintf(query, query_size, query1, ts-interval, ts);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Check each query-buffer allocation before calling snprintf.

Each branch calls snprintf immediately after malloc(query_size). If allocation fails, query is NULL and the write can crash ProxySQL. Use a checked allocation helper or return an error before formatting.

 query = (char *)malloc(query_size);
+if (query == nullptr) {
+	proxy_error("Unable to allocate metrics query buffer\n");
+	return nullptr;
+}
 snprintf(query, query_size, query1, ...);

Cppcheck reports possible null dereferences at these formatting calls.

Also applies to: 573-575, 621-623, 631-633, 667-669, 677-679, 715-717, 725-727, 763-765, 773-775

🧰 Tools
🪛 Cppcheck (2.21.0)

[warning] 565-565: If memory allocation fails, then there is a possible null pointer dereference

(nullPointerOutOfMemory)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/ProxySQL_Statistics.cpp` around lines 563 - 565, Check the result of
every malloc assignment to query in the affected branches before invoking
snprintf. Update the surrounding query-building flow in the relevant function to
return or propagate an error on allocation failure, ensuring no formatting call
dereferences a null buffer; apply the same guard to all listed allocation sites.

Source: Linters/SAST tools

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ultrareview completed in 22m 40s

7 issues found across 33 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="lib/ProxySQL_Statistics.cpp">

<violation number="1" location="lib/ProxySQL_Statistics.cpp:565">
P2: The metrics range queries can eventually select the wrong timestamp window because the updated `snprintf` calls pass `time_t` values into SQL templates that still use `%d`. `%d` is an `int` specifier, so this introduces a varargs type mismatch and risks truncated timestamps as epoch values grow. It would be safer to align the format specifiers with `time_t` (for example `%ld` with matching casts, or an explicit 64-bit format) across these query templates.</violation>
</file>

<file name="lib/PgSQL_Logger.cpp">

<violation number="1" location="lib/PgSQL_Logger.cpp:868">
P2: Log rotation filename construction can silently truncate once `log_file_id` grows beyond 8 digits. The new `snprintf` calls are bounded by a fixed `+ 11` allocation, but `%08d` allows more than 8 digits for large values, so the path can be cut off without any error handling. Consider sizing from `snprintf(nullptr, 0, ...) + 1` (or otherwise handling variable digit length) and checking the return value so rotation never reuses/truncates filenames.</violation>
</file>

<file name="lib/ProxySQL_Cluster.cpp">

<violation number="1" location="lib/ProxySQL_Cluster.cpp:2880">
P2: The cluster pull path can crash under memory pressure because the new `malloc(query_size)` result is passed to `snprintf` without a null check. If allocation fails, this loop dereferences a null pointer instead of marking the sync as failed and exiting cleanly.</violation>
</file>

<file name="lib/ClickHouse_Server.cpp">

<violation number="1" location="lib/ClickHouse_Server.cpp:864">
P2: The USER()/DATABASE() rewrite still inserts `userinfo->username` into SQL without escaping, so usernames containing quote characters can produce malformed or altered SQL in the generated query. `snprintf` prevents overflow, but it does not make the SQL literal safe. Escaping the username (or using a bound/typed value path) before formatting would keep these rewrites correct for all usernames.</violation>

<violation number="2" location="lib/ClickHouse_Server.cpp:1302">
P2: The startup `USE` query is still assembled from raw `schemaname` text, which can fail for valid names requiring quoting and can alter parsing when special characters are present. Quoting/escaping the schema identifier before building `use_query` would make first-query schema initialization more robust.</violation>
</file>

<file name="lib/MySQL_HostGroups_Manager.cpp">

<violation number="1" location="lib/MySQL_HostGroups_Manager.cpp:4346">
P2: Group-replication status updates can be silently malformed for long hostnames because the SQL buffer is sized for a query shape with one `%s`, then reused for a later query that injects the hostname twice. In this path, `snprintf` will truncate the statement when the hostname is long enough, and the truncated SQL is still passed to `mydb->execute`, which can make OFFLINE/READ_ONLY transitions fail unexpectedly. Recomputing `query_size` for the final status query (or checking `snprintf`’s return value and resizing) would keep this path reliable.</violation>
</file>

<file name="lib/MySQL_Logger.cpp">

<violation number="1" location="lib/MySQL_Logger.cpp:1394">
P2: The relative log filename buffer is sized for only an 8-digit file id. Once `log_file_id` reaches 9 digits, `snprintf` truncates the generated path, which can break log open/rotation behavior. Consider sizing from the formatted id length instead of a fixed `+11` constant.</violation>
</file>

Tip: instead of fixing issues one by one fix them all with cubic

Re-trigger cubic

sprintf(query, query1, ts-interval, ts);
query_size = strlen(query1) + 128;
query = (char *)malloc(query_size);
snprintf(query, query_size, query1, ts-interval, ts);

@cubic-dev-ai cubic-dev-ai Bot Aug 11, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The metrics range queries can eventually select the wrong timestamp window because the updated snprintf calls pass time_t values into SQL templates that still use %d. %d is an int specifier, so this introduces a varargs type mismatch and risks truncated timestamps as epoch values grow. It would be safer to align the format specifiers with time_t (for example %ld with matching casts, or an explicit 64-bit format) across these query templates.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At lib/ProxySQL_Statistics.cpp, line 565:

<comment>The metrics range queries can eventually select the wrong timestamp window because the updated `snprintf` calls pass `time_t` values into SQL templates that still use `%d`. `%d` is an `int` specifier, so this introduces a varargs type mismatch and risks truncated timestamps as epoch values grow. It would be safer to align the format specifiers with `time_t` (for example `%ld` with matching casts, or an explicit 64-bit format) across these query templates.</comment>

<file context>
@@ -552,24 +552,27 @@ SQLite3_result * ProxySQL_Statistics::get_mysql_metrics(int interval) {
-			sprintf(query, query1, ts-interval, ts);
+			query_size = strlen(query1) + 128;
+			query = (char *)malloc(query_size);
+			snprintf(query, query_size, query1, ts-interval, ts);
 			break;
 		case 28800:
</file context>
Fix with cubic

Comment thread lib/PgSQL_Logger.cpp
if (events.base_filename[0]=='/') { // absolute path
filen=(char *)malloc(strlen(events.base_filename)+11);
sprintf(filen,"%s.%08d",events.base_filename,events.log_file_id);
size_t filen_size = strlen(events.base_filename) + 11;

@cubic-dev-ai cubic-dev-ai Bot Aug 11, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Log rotation filename construction can silently truncate once log_file_id grows beyond 8 digits. The new snprintf calls are bounded by a fixed + 11 allocation, but %08d allows more than 8 digits for large values, so the path can be cut off without any error handling. Consider sizing from snprintf(nullptr, 0, ...) + 1 (or otherwise handling variable digit length) and checking the return value so rotation never reuses/truncates filenames.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At lib/PgSQL_Logger.cpp, line 868:

<comment>Log rotation filename construction can silently truncate once `log_file_id` grows beyond 8 digits. The new `snprintf` calls are bounded by a fixed `+ 11` allocation, but `%08d` allows more than 8 digits for large values, so the path can be cut off without any error handling. Consider sizing from `snprintf(nullptr, 0, ...) + 1` (or otherwise handling variable digit length) and checking the return value so rotation never reuses/truncates filenames.</comment>

<file context>
@@ -865,11 +865,13 @@ void PgSQL_Logger::events_open_log_unlocked() {
 	if (events.base_filename[0]=='/') { // absolute path
-		filen=(char *)malloc(strlen(events.base_filename)+11);
-		sprintf(filen,"%s.%08d",events.base_filename,events.log_file_id);
+		size_t filen_size = strlen(events.base_filename) + 11;
+		filen=(char *)malloc(filen_size);
+		snprintf(filen, filen_size, "%s.%08d",events.base_filename,events.log_file_id);
</file context>
Fix with cubic

Comment thread lib/ProxySQL_Cluster.cpp
char *query = (char *)malloc(strlen(q)+l+strlen(o)+64);
sprintf(query,q,row[0],row[1],row[2],o);
size_t query_size = strlen(q) + l + strlen(o) + 64;
char *query = (char *)malloc(query_size);

@cubic-dev-ai cubic-dev-ai Bot Aug 11, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The cluster pull path can crash under memory pressure because the new malloc(query_size) result is passed to snprintf without a null check. If allocation fails, this loop dereferences a null pointer instead of marking the sync as failed and exiting cleanly.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At lib/ProxySQL_Cluster.cpp, line 2880:

<comment>The cluster pull path can crash under memory pressure because the new `malloc(query_size)` result is passed to `snprintf` without a null check. If allocation fails, this loop dereferences a null pointer instead of marking the sync as failed and exiting cleanly.</comment>

<file context>
@@ -2871,8 +2876,9 @@ void ProxySQL_Cluster::pull_proxysql_servers_from_peer(const std::string& expect
-							char *query = (char *)malloc(strlen(q)+l+strlen(o)+64);
-							sprintf(query,q,row[0],row[1],row[2],o);
+							size_t query_size = strlen(q) + l + strlen(o) + 64;
+							char *query = (char *)malloc(query_size);
+							snprintf(query, query_size, q, row[0], row[1], row[2], o);
 							if (o!=row[3]) { // there was a copy
</file context>
Fix with cubic

Comment thread lib/ClickHouse_Server.cpp
sprintf(use_query,"USE %s", sn);
size_t use_query_size = strlen(sn) + 8;
use_query = (char *)malloc(use_query_size);
snprintf(use_query, use_query_size, "USE %s", sn);

@cubic-dev-ai cubic-dev-ai Bot Aug 11, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The startup USE query is still assembled from raw schemaname text, which can fail for valid names requiring quoting and can alter parsing when special characters are present. Quoting/escaping the schema identifier before building use_query would make first-query schema initialization more robust.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At lib/ClickHouse_Server.cpp, line 1302:

<comment>The startup `USE` query is still assembled from raw `schemaname` text, which can fail for valid names requiring quoting and can alter parsing when special characters are present. Quoting/escaping the schema identifier before building `use_query` would make first-query schema initialization more robust.</comment>

<file context>
@@ -1290,8 +1297,9 @@ void ClickHouse_Server_session_handler(MySQL_Session* sess, void *_pa, PtrSize_t
-								sprintf(use_query,"USE %s", sn);
+								size_t use_query_size = strlen(sn) + 8;
+								use_query = (char *)malloc(use_query_size);
+								snprintf(use_query, use_query_size, "USE %s", sn);
 								clickhouse::Query myq(use_query);
 								clickhouse_sess->client->Execute(myq);
</file context>
Fix with cubic

Comment thread lib/ClickHouse_Server.cpp
char *query1=(char *)"SELECT \"%s\" AS 'CURRENT_USER()'";
size_t query2_size = strlen(query1) + strlen(sess->client_myds->myconn->userinfo->username) + 10;
char *query2=(char *)malloc(query2_size);
snprintf(query2, query2_size, query1,sess->client_myds->myconn->userinfo->username);

@cubic-dev-ai cubic-dev-ai Bot Aug 11, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The USER()/DATABASE() rewrite still inserts userinfo->username into SQL without escaping, so usernames containing quote characters can produce malformed or altered SQL in the generated query. snprintf prevents overflow, but it does not make the SQL literal safe. Escaping the username (or using a bound/typed value path) before formatting would keep these rewrites correct for all usernames.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At lib/ClickHouse_Server.cpp, line 864:

<comment>The USER()/DATABASE() rewrite still inserts `userinfo->username` into SQL without escaping, so usernames containing quote characters can produce malformed or altered SQL in the generated query. `snprintf` prevents overflow, but it does not make the SQL literal safe. Escaping the username (or using a bound/typed value path) before formatting would keep these rewrites correct for all usernames.</comment>

<file context>
@@ -855,10 +857,11 @@ void ClickHouse_Server_session_handler(MySQL_Session* sess, void *_pa, PtrSize_t
+			char *query1=(char *)"SELECT \"%s\" AS 'CURRENT_USER()'";
+			size_t query2_size = strlen(query1) + strlen(sess->client_myds->myconn->userinfo->username) + 10;
+			char *query2=(char *)malloc(query2_size);
+			snprintf(query2, query2_size, query1,sess->client_myds->myconn->userinfo->username);
 				query=l_strdup(query2);
 				query_length=strlen(query2)+1;
</file context>
Fix with cubic

" hostgroup_id=(SELECT offline_hostgroup FROM mysql_group_replication_hostgroups WHERE writer_hostgroup=%d)) WHEN 2 THEN 2 ELSE 0 END)"
" WHERE hostname='%s' AND port=%d AND hostgroup_id=(SELECT offline_hostgroup FROM mysql_group_replication_hostgroups WHERE writer_hostgroup=%d)";
sprintf(query,q,_hostname,_port,_writer_hostgroup,_hostname,_port,_writer_hostgroup);
snprintf(query, query_size, q, _hostname, _port, _writer_hostgroup, _hostname, _port, _writer_hostgroup);

@cubic-dev-ai cubic-dev-ai Bot Aug 11, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Group-replication status updates can be silently malformed for long hostnames because the SQL buffer is sized for a query shape with one %s, then reused for a later query that injects the hostname twice. In this path, snprintf will truncate the statement when the hostname is long enough, and the truncated SQL is still passed to mydb->execute, which can make OFFLINE/READ_ONLY transitions fail unexpectedly. Recomputing query_size for the final status query (or checking snprintf’s return value and resizing) would keep this path reliable.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At lib/MySQL_HostGroups_Manager.cpp, line 4346:

<comment>Group-replication status updates can be silently malformed for long hostnames because the SQL buffer is sized for a query shape with one `%s`, then reused for a later query that injects the hostname twice. In this path, `snprintf` will truncate the statement when the hostname is long enough, and the truncated SQL is still passed to `mydb->execute`, which can make OFFLINE/READ_ONLY transitions fail unexpectedly. Recomputing `query_size` for the final status query (or checking `snprintf`’s return value and resizing) would keep this path reliable.</comment>

<file context>
@@ -4338,7 +4343,7 @@ void MySQL_HostGroups_Manager::update_group_replication_set_offline(char *_hostn
 					" hostgroup_id=(SELECT offline_hostgroup FROM mysql_group_replication_hostgroups WHERE writer_hostgroup=%d)) WHEN 2 THEN 2 ELSE 0 END)"
 				" WHERE hostname='%s' AND port=%d AND hostgroup_id=(SELECT offline_hostgroup FROM mysql_group_replication_hostgroups WHERE writer_hostgroup=%d)";
-			sprintf(query,q,_hostname,_port,_writer_hostgroup,_hostname,_port,_writer_hostgroup);
+			snprintf(query, query_size, q, _hostname, _port, _writer_hostgroup, _hostname, _port, _writer_hostgroup);
 			mydb->execute(query);
 			//free(query);
</file context>
Fix with cubic

Comment thread lib/MySQL_Logger.cpp
} else { // relative path
filen=(char *)malloc(strlen(events.datadir)+strlen(events.base_filename)+11);
sprintf(filen,"%s/%s.%08d",events.datadir,events.base_filename,events.log_file_id);
size_t filen_size = strlen(events.datadir) + strlen(events.base_filename) + 11;

@cubic-dev-ai cubic-dev-ai Bot Aug 11, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The relative log filename buffer is sized for only an 8-digit file id. Once log_file_id reaches 9 digits, snprintf truncates the generated path, which can break log open/rotation behavior. Consider sizing from the formatted id length instead of a fixed +11 constant.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At lib/MySQL_Logger.cpp, line 1394:

<comment>The relative log filename buffer is sized for only an 8-digit file id. Once `log_file_id` reaches 9 digits, `snprintf` truncates the generated path, which can break log open/rotation behavior. Consider sizing from the formatted id length instead of a fixed `+11` constant.</comment>

<file context>
@@ -1387,11 +1387,13 @@ void MySQL_Logger::events_open_log_unlocked() {
 	} else { // relative path
-		filen=(char *)malloc(strlen(events.datadir)+strlen(events.base_filename)+11);
-		sprintf(filen,"%s/%s.%08d",events.datadir,events.base_filename,events.log_file_id);
+		size_t filen_size = strlen(events.datadir) + strlen(events.base_filename) + 11;
+		filen=(char *)malloc(filen_size);
+		snprintf(filen, filen_size, "%s/%s.%08d",events.datadir,events.base_filename,events.log_file_id);
</file context>
Fix with cubic

Copy link
Copy Markdown
Contributor Author

Superseded by #6038, which preserves the independent GenAI complete-type destruction fix as a one-file, one-commit change.

This PR also contained the bulk S6069 refactoring. SonarCloud reported 485 new code smells on that broader approach, so it is being restarted separately with a Sonar-validated pattern rather than merged here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant